Go语言 是否可以在超级账本链代码中使用gRPC,如果可以,我如何避免在测试网络上调用时出错?

ssgvzors  于 2023-05-27  发布在  Go
关注(0)|答案(1)|浏览(163)

我想在fabric chaincode中使用gRPC来实现跨链通信,而不是使用fabric SDK。但是当我在fabric-sample/test-network上调用chaincode函数时,总是出现错误。

Error: endorsement failure during invoke. response: status:500 message:"error in simulation: failed to execute transaction eb5e480bd4075a767f56ae263741ca0f5f19620ef88952e26b7f1952bdbe83cd: could not launch chaincode chaincode_1.2:d3f97f15a635e73d3de230c8e5899e5fb95a68cf897c03e19f9e4eeca7ca3fd5: chaincode registration failed: container exited with 2"

谁能告诉我是什么原因导致这个错误?我的chaincode有bug或者gRPC不能在chaincode函数中使用?
关于gRPC的chaincode:

func (s *SmartContract) begin(ctx contractapi.TransactionContextInterface) error {
    server.Main()
    return nil
}

func (s *SmartContract) client(ctx contractapi.TransactionContextInterface) error {
    // client.Clientfunc is the client main function
    client.Clientfunc(Xt, R, sign, m)
}

server.go

func Main() {
    listen, err := net.Listen("tcp", ":9090")
    if err != nil {
        fmt.Printf("failed to listen: %v", err)
        return
    }
    grpcServer := grpc.NewServer()
    pb.RegisterSendServiceServer(grpcServer, &server{})
    err2 := grpcServer.Serve(listen)
    if err2 != nil {
        fmt.Printf("failed to serve: %v", err2)
        return
    }
}

client.go

func Clientfunc(Xt *btcec.PublicKey, R *btcec.PublicKey, s *big.Int, m []byte) []byte {
    conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    client := pb.NewSendServiceClient(conn)
    output := &pb.SignInput{
        XtX: Xt.X().Int64(),
        XtY: Xt.Y().Int64(),
        M:   m,
        RX:  R.X().Int64(),
        RY:  R.Y().Int64(),
        S:   s.Int64(),
    }
    resp, _ := client.Send(context.Background(), output)
    return resp.GetM()
}
6jjcrrmo

6jjcrrmo1#

谁能告诉我是什么原因导致这个错误?
Hyperledger Fabric v2.x/ Logging Control中所述,服务器日志可以告诉您导致error 500(内部服务器错误)的原因
取决于您如何运行它:

docker logs <chaincode_container_id>
kubectl logs -n <namespace> <pod_name>
oc logs -n <namespace> <pod_name>

这可能是由于链代码中的问题(如gRPC代码中的错误),也可能是由于链代码运行的环境。
从您的代码中,您可以考虑在链码中 * 不 * 启动gRPC服务器(server.Main())。Chaincode在Hyperledger Fabric网络中运行,并不意味着像独立应用程序那样处理网络通信。
相反,您应该使gRPC服务器成为独立运行的单独服务,然后链代码可以根据需要与此服务进行通信。
另外,client.Clientfunc()函数似乎建立了一个gRPC连接,发送一个请求,并等待响应。这是一个同步操作,如果响应需要很长时间才能到达,则可能会出现问题。最好使用异步操作(即,在回调函数中发送请求并处理响应),以避免阻塞链代码的执行。
而且...你不应该忽略来自client.Send()的错误;)
请确保您的gRPC服务器不需要安全连接,否则grpc.WithTransportCredentials(insecure.NewCredentials())(没有SSL/TLS的不安全连接)将失败。
通常,建议在Fabric客户端应用程序中处理与外部系统的通信(如通过gRPC),而不是在链代码本身中。
如果我只想使用链码而不是结构应用程序,是否有任何方法可以在不同渠道的组织之间进行通信?
不同渠道上的组织之间的通信可能很复杂,因为这是Hyperledger Fabric设计的一个基本方面,即channels彼此隔离以维护数据隐私。
您可以考虑:

  • Chaincode Functions:一个组织可以在自己的通道上调用链码函数,然后在另一个通道上调用链码函数。这是可能的,因为链码可以与多个通道相关联。

请注意,这种方法有一个限制,即第二个函数调用与第一个函数调用不是同一个事务的一部分,因此如果第一个事务失败,它不能回滚。

  • Dual Membership:组织可以是多个渠道的一部分。因此,它可以从一个通道读取数据并将数据写入另一个通道。但是,这是在两个单独的事务中完成的,因此不能保证原子性。
  • Private Data Collections (PDCs):如果目标是在特定组织之间共享私有数据,甚至跨不同渠道共享,那么PDC可能是一个选择。PDC允许通道上定义的组织子集认可、提交或查询私有数据,而无需跨通道上的所有组织分发数据。
    *互操作解决方案:还有更先进的区块链互操作性解决方案,如Interledger Protocol(ILP),可以用于在不同的Fabric网络之间(甚至在完全不同类型的区块链网络之间)移动数据或资产。

然而,这些产品仍处于研究和开发阶段,可能尚未准备好投入生产使用。

相关问题