javahyperledger-fabrichyperledger-fabric-sdk-java

How to query block and transaction info by using the new recommended Gateway Client API


I have started building my Hyperledger Fabric Networks with v2.5 and since I still need to connect my client applications to the network I was going to keep using the popular Hyperledger Fabric Gateway SDK v2.2 but I noticed an alert on the repository about this being deprecated:

Note: This API is deprecated as of Fabric v2.5. When developing applications for Hyperledger Fabric v2.4 and later, you should use the Fabric Gateway client API.

This is where this info comes from: https://github.com/hyperledger/fabric-gateway-java

The old and new gateways dependencies are:

'org.hyperledger.fabric:fabric-gateway-java:2.2.8' //old gateway sdk
'org.hyperledger.fabric:fabric-gateway:1.5.0' // new gateway client

So I am exploring this new library to interact with the network, and though I can connect my application to the network and send transactions and query the chain codes, I noticed that the following functionality does not exist with the recommended library (the client):

network.getChannel().queryTransactionByID(txID);

network.getChannel().queryBlockByTransactionID(txID);

// and other methods that getChannel had available in the deprecated sdk

Does anybody have an explanation for this loss of functionality or knows an alternative I can use?

I would like keep querying channel info like blocks, transactions envelopes, transactions, etc. I did not find an alternative on the new gateway client.


Solution

  • The implementation of queryTransactionByID and queryBlockByTransactionID in the legacy client SDK are convenience functions for the invocation of the qscc system chaincode's GetTransactionByID and GetBlockByTxID transaction functions. The qscc system chaincode exists on all network peers. The same transaction functions can be evaluated using the newer Fabric Gateway client API just as any other transaction function. Both transaction functions take a channel name and transaction ID as parameters. For example:

    var contract = network.getContract("qscc");
    var transactionBytes = contract.evaluateTransaction("GetTransactionByID", network.getName(), transactionId);
    var blockBytes = contract.evaluateTransaction("GetBlockByTxID", network.getName(), transactionId);
    

    The complete set of transaction functions provided by the qscc system chaincode is:

    Their implementation is here. Rather than using GetBlockByNumber, it is probably more efficient to use the Fabric Gateway client API's block eventing capability to read blocks from a specific starting block number and close the event iterator once the desired block is read.

    The legacy SDK returns a wrapper object to aid access to key properties of the transaction and block responses. Since the Fabric Gateway client API is performing a generic transaction evaluate call, the return value is a byte array. The content of the byte array is a serialized protocol buffer message. In the case of GetTransactionByID the return value is a serialized peer.ProcessedTransaction message, and for GetBlockByTxID the return value is a serialized common.Block message. These messages can be deserialized using the fabric-protos package.

    The fabric-protos package contains protocol buffer bindings generated directly from the Fabric protocol buffer definitions. The Fabric protocol buffer definitions are fairly complex and embed serialized messages within other messages. The generated bindings do expose this complexity but they also provide complete access to all the available information within the messages.

    There are examples of deserializing Fabric protocol buffer messages in the parser package of the off_chain_data sample, which you could reuse.

    You can deserialize the ProcessedTransaction using:

    var processedTransaction = org.hyperledger.fabric.protos.peer.ProcessedTransaction.parseFrom(transactionBytes);
    

    For deserializing the Payload within the ProcessedTransaction's transactionEnvelope property, look at the ParsedPayload and ParsedTransaction classes.

    You can deserialize the Block message using:

    var block = org.hyperledger.fabric.protos.common.Block.parseFrom(blockBytes);
    

    Look at the ParsedBlock class for an example of unpacking the block structure.