【问题标题】:Hyperledger Fabric: check if the transaction has been committed to the ledgerHyperledger Fabric:检查交易是否已提交到账本
【发布时间】:2019-09-29 21:15:02
【问题描述】:

我有三个客户端应用程序,它们分别使用 Java、Node.js 和 Go SDK 与我的区块链 Fabric 进行交互。使用它们,我可以成功地查询和更新账本。

现在我想测量账本更新期间的延迟。所以,我想在提交请求之前获取一个时间戳,在事务成功提交到账本之后再获取一个时间戳,然后计算差异。

我的问题是我找不到任何关于Java、Go和Node.js的SDK API的完整文档,所以我不知道当提交方法返回时,我是否可以认为事务已正确提交到账本。

这是我的三个客户的代码。 爪哇:

NetworkConfig ccp = NetworkConfig.fromJsonFile(networkConfigPath.toFile());
// initialize default cryptosuite and setup the client
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(cryptoSuite);

Channel channel = client.loadChannelFromConfig(ccp.getChannelNames().iterator().next(), ccp);
channel.initialize();

TransactionProposalRequest transactionProposal = client.newTransactionProposalRequest();
// build chaincode id providing the chaincode name
ChaincodeID mychaincodeID = ChaincodeID.newBuilder().setName("mychaincode").build();
transactionProposal.setChaincodeID(mychaincodeID);
// calling chaincode function
transactionProposal.setFcn("mymethod");
transactionProposal.setArgs("a1");

Collection<ProposalResponse> res = channel.sendTransactionProposal(transactionProposal);
channel.sendTransaction(res);

Node.js:

const gateway = new Gateway();
await gateway.connect(ccp, { wallet: wallet, identity: userName, discovery: { enabled: false } });

// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');

// Get the contract from the network.
const contract = network.getContract('mychaincode');

const result = await contract.submitTransaction('mymethod', 'a1');

去:

sdk, err := fabsdk.New(config.FromFile(configFile))
if err != nil {
    fmt.Printf("failed to create SDK: %v\n", err)
    return
}
fmt.Println("SDK created")

// Prepare channel client context using client context
clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser(userName), fabsdk.WithOrg(orgName))
// ChannelClient is used to query and execute transactions
client, err := channel.New(clientChannelContext)
if err != nil {
    fmt.Printf("failed to create new channel client: %v\n", err)
    return
}
fmt.Println("channel client created")

response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))
if err != nil {
    fmt.Printf("failed to execute the invoke function: %v\n", err)
} else {
    fmt.Println("Proposal responses: ")
    for _, element := range response.Responses {
        fmt.Printf("Endorser: %s Status: %d ChaincodeStatus: %d\n", element.Endorser, element.Status, element.ChaincodeStatus)
    }
    fmt.Println("chaincode transaction completed: " + string(response.Payload))
}
// Close SDK
sdk.Close()

这些代码有效。我的问题是:我可以确定在这些行之后

channel.sendTransaction(res)

(在 Java 中)

const result = await contract.submitTransaction('mymethod', 'a1');

(在 Node.js 中)

response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))

(在围棋中) 交易是否已提交到账本?

我只在文档中发现:

"向账本提交交易。交易函数名称将在背书节点上进行评估,然后提交给排序服务以提交账本。"在https://fabric-sdk-node.github.io/release-1.4/module-fabric-network.Contract.html#submitTransaction__anchorhttps://fabric-sdk-node.github.io/release-1.4/module-fabric-network.Contract.html#submitTransaction__anchor

的 Node.js 中的 submitTransaction

“使用请求和可选请求选项执行准备和执行事务”用于在 Go 中执行 https://godoc.org/github.com/hyperledger/fabric-sdk-go/pkg/client/channel#Client.Execute

对于 Java,我找不到文档...我也不确定 Node.js 和 Go。

【问题讨论】:

    标签: hyperledger-fabric hyperledger-fabric-sdk-js hyperledger-fabric-sdk-go


    【解决方案1】:

    我想我解决了。在每个客户端应用程序中,我尝试在请求之后的行中向分类帐添加查询。这个测试的结果是Node.js和Go版本运行良好:after

    const result = await contract.submitTransaction('mymethod', 'a1');
    

    response, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "mymethod", Args: [][]byte{[]byte("a1")}}, channel.WithRetry(retry.DefaultChannelOpts))
    

    查询结果没问题,我得到了正确的新值。所以这意味着账本在方法执行后正确更新。

    对于我这样解决的Java版本:

    NetworkConfig ccp = NetworkConfig.fromJsonFile(networkConfigPath.toFile());
    // initialize default cryptosuite and setup the client
    CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
    HFClient client = HFClient.createNewInstance();
    client.setCryptoSuite(cryptoSuite);
    
    Channel channel = client.loadChannelFromConfig(ccp.getChannelNames().iterator().next(), ccp);
    channel.initialize();
    
    TransactionProposalRequest transactionProposal = client.newTransactionProposalRequest();
    // build chaincode id providing the chaincode name
    ChaincodeID mychaincodeID = ChaincodeID.newBuilder().setName("mychaincode").build();
    transactionProposal.setChaincodeID(mychaincodeID);
    // calling chaincode function
    transactionProposal.setFcn("mymethod");
    transactionProposal.setArgs("a1");
    
    Collection<ProposalResponse> res = channel.sendTransactionProposal(transactionProposal);
    CompletableFuture<TransactionEvent> cf = channel.sendTransaction(res);
    TransactionEvent te = cf.get();
    
    logger.info("Status: " + te.isValid());
    logger.info("Committed the transaction with transactionID + " + te.getTransactionID());
    

    希望对您有所帮助。当然,如果有人有 cmets,他们会很受欢迎。

    【讨论】:

      【解决方案2】:

      另一个答案可以帮助可能需要 CLI 提供此功能的人。

      默认情况下,当订单收到交易时,CLI 会返回成功。

      要等到peer chaincode invoke commnad 上的提交,请添加标志--waitForEvent

      这样 cli 将等待来自同行的提交事件。

      希望对您有所帮助。

      【讨论】:

      • 绝对有帮助!谢谢!
      【解决方案3】:

      我认为执行此操作的更好方法是使用 Fabric EventHub,这样您就可以注册一个侦听器并在事件提交时接收它。使用查询可能会导致您处理不一致的结果并为延迟的事务执行重试。

      下面的代码 sn-p 可以与 NodeSDK 一起使用,我认为会很有用,更多示例和文档可以在这里找到:https://fabric-sdk-node.github.io/release-1.4/tutorial-listening-to-events.html

      var options = {
          wallet_path: path.join(__dirname, './creds'),
          user_id: 'PeerAdmin',
          channel_id: 'mychannel',
          chaincode_id: 'fabcar',
          peer_url: 'grpc://localhost:7051',
          event_url: 'grpc://localhost:7053',
          orderer_url: 'grpc://localhost:7050'
      };
      
      
      
          let eh = client.newEventHub();
          eh.setPeerAddr(options.event_url);
          eh.connect();
      
      
          let txPromise = new Promise((resolve, reject) => {
              let handle = setTimeout(() => {
                  eh.disconnect();
                  reject();
              }, 30000);
      
              eh.registerTxEvent(transactionID, (tx, code) => {
                  clearTimeout(handle);
                  eh.unregisterTxEvent(transactionID);
                  eh.disconnect();
      
                  if (code !== 'VALID') {
                      console.error(
                          'The transaction was invalid, code = ' + code);
                      reject();
                  } else {
                      console.log(
                          'The transaction has been committed on peer ' +
                          eh._ep._endpoint.addr);
                      resolve();
                  }
              });
          });
          eventPromises.push(txPromise);
      

      【讨论】:

        猜你喜欢
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-25
        相关资源
        最近更新 更多