2

I want to use gRPC in fabric chaincode to achieve cross-chain communcation instead of using fabric SDK. But when I invoke chaincode function on fabric-sample/test-network, it always occurs errors.

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"

Who can tell me what cause this error? My chaincode has bug or gRPC cannot be used in chaincode function?

my chaincode about gRPC:

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()
}

1 Answers1

1

Who can tell me what cause this error?

As detailed in Hyperledger Fabric v2.x/ Logging Control, what can tell you what caused an error 500 (internal server error) are the server logs

Depending on how you are running it:

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

It could be due to a problem in your chaincode (like a bug in the gRPC code), or it could be due to the environment in which the chaincode is running.


From your code, you might consider not starting the gRPC server (server.Main()) in the chaincode. Chaincode runs within the Hyperledger Fabric network and is not meant to handle network communications like a standalone application does.
Instead, you should make the gRPC server a separate service that runs independently, and then the chaincode can communicate with this service as needed.

Plus the client.Clientfunc() function seems to establish a gRPC connection, send a request, and wait for a response. This is a synchronous operation and can be problematic if the response takes a long time to arrive. It's better to use an asynchronous operation (i.e., send the request and handle the response in a callback function) to avoid blocking the chaincode execution.
And... you should not ignore the error from client.Send() ;)

Make sure your gRPC server does not require secure connections, or a grpc.WithTransportCredentials(insecure.NewCredentials()) (insecure connection without SSL/TLS) will fail.


Typically, it's advisable to handle communication with external systems (like via gRPC) in the Fabric client application, not within the chaincode itself.

If I just want to use chaincode instead of fabric application, is there any way to communicate between orgs of different channels?

Communication between organizations on different channels can be complex, as it is a fundamental aspect of Hyperledger Fabric's design that channels are isolated from one another to maintain data privacy.

You might consider:

  • Chaincode Functions: One organization can invoke a chaincode function on its own channel, which in turn invokes a chaincode function on another channel. This is possible because a chaincode can be associated with multiple channels.
    Note that this approach has the limitation that the second function invocation is not part of the same transaction as the first, so it can't be rolled back if the first transaction fails.

  • Dual Membership: An organization can be part of multiple channels. Therefore, it can read data from one channel and write data to another channel. However, this is done in two separate transactions, so atomicity cannot be guaranteed.

  • Private Data Collections (PDCs): If the goal is to share private data between specific organizations, even across different channels, PDCs might be an option. A PDC allows a defined subset of organizations on a channel to endorse, commit, or query private data without distributing the data across all the organizations on the channel.

  • Interoperability Solutions: There are also more advanced solutions being developed for blockchain interoperability, like the Interledger Protocol (ILP), that could potentially be used to move data or assets between different Fabric networks (or even between entirely different types of blockchain networks).
    However, these are still largely in the research and development stage and might not be ready for production use.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for your helpful answer! After asking this question, I tried to remove the gRPC function in my chaincode. The Invoke is okay. So the problem is in my gRPC code. I use the regular gRPC client and server code and turn .go into a function that can be called in chaincode function. I don`t know if this way is right or not. – Lawrence Yang May 21 '23 at 06:09
  • And I add the code about chaincode server.go and client.go. Maybe I used the wrong way to use gRPC in the fabric chaincode. – Lawrence Yang May 21 '23 at 06:15
  • @LawrenceYang OK, I have edited the answer to address your comments. – VonC May 21 '23 at 06:34
  • Thanks for your patience! According to your answer, Using gRPC in chaincode isn't a suitable way to communicate. I should use gRPC as a fabric application. I don‘t know if my understanding is correct. My demo doesn`t need asynchrony and secure connections, but your suggestion is more suitable for a project, thanks! And I also have a problem, if I just want to use chaincode instead of fabric application, is there any way to communicate between orgs of different channels? – Lawrence Yang May 21 '23 at 07:17
  • @LawrenceYang No problem. I have edited the answer (again) to address your comments. – VonC May 21 '23 at 09:31
  • Thank you very much for your patience! Maybe the most suitable way for me is to use Fabric Client Application with gRPC. Thanks for your time! – Lawrence Yang May 21 '23 at 10:32