英文:
Is it possible to use gRPC in hyperledger-chaincode and if so, how can I avoid errors during invocation on test-network?
问题
我想在Fabric链码中使用gRPC实现跨链通信,而不是使用Fabric SDK。但是当我在fabric-sample/test-network上调用链码函数时,总是出现错误。
错误:在调用期间出现背书失败。响应:状态:500 消息:"error in simulation: failed to execute transaction eb5e480bd4075a767f56ae263741ca0f5f19620ef88952e26b7f1952bdbe83cd: could not launch chaincode chaincode_1.2:d3f97f15a635e73d3de230c8e5899e5fb95a68cf897c03e19f9e4eeca7ca3fd5: chaincode registration failed: container exited with 2"
谁能告诉我这个错误的原因?是我的链码有问题还是链码函数不能使用gRPC?
我的关于gRPC的链码代码如下:
func (s *SmartContract) begin(ctx contractapi.TransactionContextInterface) error {
server.Main()
return nil
}
func (s *SmartContract) client(ctx contractapi.TransactionContextInterface) error {
// client.Clientfunc是客户端的主要函数
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()
}
英文:
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
得分: 1
谁能告诉我是什么原因导致了这个错误?
根据Hyperledger Fabric v2.x/ Logging Control中的详细说明,可以通过服务器日志来确定导致错误500(内部服务器错误)的原因。
根据你的运行方式不同:
docker logs <chaincode_container_id>
kubectl logs -n <namespace> <pod_name>
oc logs -n <namespace> <pod_name>
可能是由于链码中的问题(比如gRPC代码中的错误)或链码运行环境的问题导致的。
从你的代码来看,你可能考虑在链码中不启动gRPC服务器(server.Main()
)。链码在Hyperledger Fabric网络中运行,不应该像独立应用程序那样处理网络通信。
相反,你应该将gRPC服务器作为一个独立的服务运行,并让链码根据需要与该服务进行通信。
此外,client.Clientfunc()
函数似乎建立了一个gRPC连接,发送请求并等待响应。这是一个同步操作,如果响应时间很长,可能会出现问题。最好使用异步操作(即发送请求并在回调函数中处理响应),以避免阻塞链码的执行。
另外...你不应该忽略client.Send()
的错误
确保你的gRPC服务器不需要安全连接,否则grpc.WithTransportCredentials(insecure.NewCredentials())
(不安全的无SSL/TLS连接)将失败。
通常情况下,建议在Fabric客户端应用程序中处理与外部系统的通信(如通过gRPC),而不是在链码本身中处理。
如果我只想使用链码而不是Fabric应用程序,有没有办法在不同通道的组织之间进行通信?
不同通道上组织之间的通信可能很复杂,因为Hyperledger Fabric的设计基本原则之一是通道之间是隔离的,以保持数据的隐私性。
你可以考虑以下方法:
-
链码函数:一个组织可以在自己的通道上调用一个链码函数,该函数再调用另一个通道上的链码函数。这是可能的,因为一个链码可以与多个通道关联。
请注意,这种方法的局限性在于第二次函数调用不属于与第一次相同的事务,因此如果第一次事务失败,无法回滚第二次事务。 -
双重成员资格:一个组织可以是多个通道的成员。因此,它可以从一个通道读取数据并将数据写入另一个通道。然而,这是通过两个单独的事务完成的,因此无法保证原子性。
-
私有数据集合(PDCs):如果目标是在不同通道之间共享特定组织的私有数据,PDCs可能是一个选择。PDC允许通道上的一组定义的组织在不将数据分发到通道上的所有组织的情况下对私有数据进行背书、提交或查询。
-
互操作性解决方案:还有一些更高级的解决方案正在开发中,用于区块链互操作性,比如Interledger Protocol(ILP),它可以用于在不同的Fabric网络之间(甚至在完全不同类型的区块链网络之间)移动数据或资产。
然而,这些解决方案目前仍处于研究和开发阶段,可能还没有准备好用于生产环境。
英文:
> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论