Hyperledger Fabric chaincode调用函数返回值



我理解Chaincode Invoke函数是异步的,除非达成共识,否则无法传达分类账修改的成功/失败。然而,在调用任何链码存根api之前捕获的简单验证错误怎么办?在验证失败的情况下,应该有一种方法将错误返回给调用者。否则函数的返回值有什么用。例如

    func (t *MyChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
        if len(args) == 0 {
            return nil, errors.New("Incorrect number of arguments. Expecting greater than 0")
       }
      err = stub.PutState("Somevalue", args[0])
      if err != nil {
          return nil, err
      }
      return nil, nil 
}

现在,如果我在调用时不传递任何参数给REST API,我仍然会得到成功的响应。

{ "jsonrpc": "2.0" "result": { "status": "OK" "message": "bf4f2e2c-ed0f-4240-aae5-1dc295515b3f" }, "id": 4 }。仅表示事务已成功提交。它没有给出任何指示,如果链码功能完成成功或失败。

如果你使用node.js HFC客户端发送事务,它会返回一个错误消息,这是推荐的发送事务的方式。

据我所知,调用事务确实没有办法根据链码的执行返回值。更多详细信息请参阅这篇文章https://github.com/IBM-Blockchain/ibm-blockchain-issues/issues/85

然而,你能做的是在执行出错或一切按计划进行的情况下,从你的链码发出一个事件。例如:

    func (t *SimpleChaincode) publish(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
...
//Execution of chaincode finished successfully
                        tosend := "Tx chaincode finished OK." + stub.GetTxID()
                        err = stub.SetEvent("evtsender", []byte(tosend))
                        if err != nil {
                            return nil, err
                        }
...
//transactions cannot return errors this way we have to use an event
                        // return nil, errors.New("No Supplement Found with the given ID")
                        tosend := "Error, No Supplement Found with the given ID" + suplementId + "." + stub.GetTxID()
                        err = stub.SetEvent("evtsender", []byte(tosend))
                        if err != nil {
                            return nil, err
                        }
...

在这些事件中,您可以添加事务Id。因此,在你的sdk应用程序(在使用hfc与nodejs的情况下),你包装调用事务调用在一个承诺和解决它,拒绝它取决于发出的事件。例如:

function invokeWithParams(userObj,invReq) {
    var txHash="qwe";
    return new Promise(function(resolve,reject){
      var eh = networkConfig.chain.getEventHub();
      // Trigger the invoke transaction
      var invokeTx = userObj.invoke(invReq);
      // Print the invoke results
      invokeTx.on('submitted', function(results) {
        // Invoke transaction submitted successfully
        console.log(util.format("nSuccessfully submitted chaincode invoke transaction: request=%j, response=%j", invReq, results));
        txHash = results.uuid;
      });
      invokeTx.on('complete', function(results) {
        // Invoke transaction completed successfully
        console.log(util.format("nSuccessfully completed chaincode invoke transaction: request=%j, response=%j", invReq, results));
        // resolve(results);
        // txHash = results.uuid;
      });
      invokeTx.on('error', function(err) {
        // Invoke transaction submission failed
        console.log(util.format("nFailed to submit chaincode invoke transaction: request=%j, error=%j", invReq, err));
        reject(err);
      });
      //Listen to custom events
      var regid = eh.registerChaincodeEvent(invReq.chaincodeID, "evtsender", function(event) {
        console.log(util.format("Custom event received, payload: %jn", event.payload.toString()));
        if(event.payload.toString().indexOf("Error") >= 0){
          let uuid = event.payload.toString().split(".")[1];
          eh.unregisterChaincodeEvent(regid);
          if(uuid === txHash){ //resolve promise only when the current transaction has finished
            eh.unregisterChaincodeEvent(regid);
            reject(event.payload.toString());
          }
        }
        if(event.payload.toString().indexOf("Tx chaincode finished OK") >= 0){
            let uuid = event.payload.toString().split(".")[1];
            console.log("nUUID " + uuid);
            console.log("ntxHash " + txHash);
            if(uuid === txHash){ //resolve promise only when the current transaction has finished
              eh.unregisterChaincodeEvent(regid);
              resolve(event.payload.toString());
            }
        }
      });
    });

}

无论如何,我知道这是一个远非完美的方法,但它帮助了我,所以我希望它能帮助你:)

最新更新