Код цепочки Hyperledger Fabric Возвращаемые значения функции вызова

Я понимаю, что функция 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 во время вызова, я все равно получу успех в качестве ответа.


person JavaD    schedule 15.09.2016    source источник
comment
каков твой вопрос ?   -  person Sufiyan Ghori    schedule 15.09.2016
comment
Если я вызываю вышеуказанную функцию через REST, передавая 0 параметров, я получаю следующий (аналогичный) ответ { "jsonrpc": "2.0" "result": { "status": "OK" "message": "bf4f2e2c-ed0f-4240-aae5-1dc295515b3f" }- "id": 4 } В идеале он должен возвращать ответ об ошибке, а не ответ OK   -  person JavaD    schedule 16.09.2016


Ответы (2)


{ "jsonrpc": "2.0" "result": { "status": "OK" "message": "bf4f2e2c-ed0f-4240-aae5-1dc295515b3f" }, "id": 4 } . Только означает, что транзакция была успешно отправлена. Это не дает никаких указаний на то, завершилась ли функция чейнкода успешно или неудачно.

Он возвращает сообщение об ошибке, если вы используете клиент node.js HFC для отправки транзакций, что рекомендуемый способ отправки транзакций.

person Clyde D'Cruz    schedule 16.09.2016
comment
Я наблюдаю то же самое, видимо, гиперледжер предназначен для того, чтобы никогда не возвращать сообщение об ошибке на Иновке (и вы не можете отклонить транзакцию в чейнкоде). Не интуитивно. - person tribbloid; 26.09.2016

привет, насколько мне известно, действительно, транзакция вызова не может вернуть значение в зависимости от выполнения цепного кода. Подробнее см. в этом сообщении 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
                        }
...

В эти события вы можете добавить идентификатор транзакции. Таким образом, в вашем приложении 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: %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());
            }
        }
      });
    });


}

В любом случае, я знаю, что это далеко не идеальный подход, но он помог мне, поэтому я надеюсь, что он поможет вам :)

person Nikos T    schedule 29.05.2017