据我所知,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传递任何参数,我仍然可以作为响应获得成功。
答案 0 :(得分:1)
{ "jsonrpc": "2.0" "result": { "status": "OK" "message": "bf4f2e2c-ed0f-4240-aae5-1dc295515b3f" }, "id": 4 }
。仅表示事务已成功提交。如果链代码功能成功或失败,它不会给出任何指示。
如果您使用node.js HFC客户端发送事务,它会返回错误消息,这是发送事务的推荐方法。
答案 1 :(得分:1)
嗨据我所知,确实调用事务无法根据链代码的执行返回值。有关详细信息,请参阅此帖子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应用程序中(在使用带有nodejs的hfc的情况下)你将invoke事务调用包装在一个promise中,并根据发出的事件解决它拒绝它。类似的东西:
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: %j\n", 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());
}
}
});
});
}
无论如何,我知道这是一个远非完美的方法,但它帮助了我,所以我希望它会帮助你:)。