Hyperledger Fabric:检查事务是否已提交到分类帐

时间:2019-05-12 20:53:23

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

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

现在,我想测量分类帐更新期间的延迟。因此,我当时想在提交请求之前先加上一个时间戳,然后在事务已成功提交到分类账之后再加上一个时间戳,然后计算差异。

我的问题是我找不到关于Java,Go和Node.js的SDK API的完整文档,所以我不知道在提交方法返回时,是否可以将事务视为已正确提交到分类帐。

这是我三个客户的代码。 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);
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))

(在Go中) 交易已提交到分类帐吗?

我只在文档上发现了这一点

“将事务提交到分类帐。将在背书的对等方上评估事务功能名称,然后将其提交到订购服务以提交到分类帐。” https://fabric-sdk-node.github.io/release-1.4/module-fabric-network.Contract.html#submitTransaction__anchor

中的Node.js中的SubmitTransaction

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

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

3 个答案:

答案 0 :(得分:2)

另一个答案,以帮助可能需要CLI的人。

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

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

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

希望有帮助。

答案 1 :(得分:1)

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

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());

希望它会有所帮助。当然,如果有人发表评论,他们就会被接受。

答案 2 :(得分:0)

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

下面的代码段可以与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);