Reputation: 33
I understand that Chaincode Invoke function is asynchronous and cannot convey success/failure of ledger modification unless consensus is completed. However what about simple validation errors caught before invocation of any chaincode stub APIs? There should be a way to return error to caller in case of validation failure. Otherwise what is use of return value of function. e.g.
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
}
Now if I pass no arguments to REST API while calling, I still get success as a response.
Upvotes: 0
Views: 2244
Reputation: 106
hi to the best of my knowledge indeed there is no way for an invoke transaction to return a value depending on the execution of the chaincode. See this post for more details https://github.com/IBM-Blockchain/ibm-blockchain-issues/issues/85
However, what you can do is to emit an event from your chaincode in the case something goes wrong with the execution or if everything goes as planned. For example you could have:
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
}
...
In these events you can add the transaction Id. So in your sdk app (in the case of using hfc with nodejs) you wrap the invoke transaction call in a promise and resolve it reject it depending on the emitted events. Something like :
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());
}
}
});
});
}
Anyway I know its a far from perfect approach but it has helped me so I hope it will help you :)
Upvotes: 1
Reputation: 2065
{ "jsonrpc": "2.0" "result": { "status": "OK" "message": "bf4f2e2c-ed0f-4240-aae5-1dc295515b3f" }, "id": 4 }
. Only means that the transaction was submitted successfully. It does not give any indication if the chaincode function completed with a success or failure.
It does return an error message if you use the node.js HFC client to send transactions, which is the recommended way of sending transactions.
Upvotes: 1