如何在Hyperledger Fabric 2.0中按ID查询事务

Querying transaction content out from a blockchain network is a common practice used by common scenarios like exploring the blockchain history or verifying the blockchain transaction content from a known ID. In Hyperledger Fabric, the transaction can be queried using a special system chaincode QSCC (Query System Chaincode) which is for ledger and other Fabric-related queries. For querying transaction by its ID, we can query/invoke the GetTransactionByID function from QSCC.

区块链 网络中查询交易内容是常见场景使用的一种惯例,例如探索区块链历史或从已知ID验证区块链交易内容。 在Hyperledger Fabric中,可以使用特殊的系统链代码QSCC(查询系统链代码)查询交易,该系统链代码用于分类帐和其他与Fabric相关的查询。 为了通过其ID查询事务,我们可以从QSCC查询/调用GetTransactionByID函数

This tutorial assumes you have just finished installing Hyperledger Fabric 2.0 in Ubuntu 18.04 and we introduce the steps using the test-network.

教程假定您刚刚在Ubuntu 18.04中完成Hyperledger Fabric 2.0的安装,并且我们将介绍使用测试网络的步骤。

更改工作目录并设置环境 (Change the working directory and set up the environment)

First change the working directory to the test-network directory from the fabric-samples repository which was pulled by the installation script during installing Hyperledger Fabric 2.0 following the tutorial mentioned above.

首先,按照上述教程,在安装Hyperledger Fabric 2.0的过程中将工作目录从fabric-samples存储库更改为test-network目录,该存储库是由安装脚本提取的。

$ cd $GOPATH/src/github.com/hyperledger/fabric-samples/test-network

Set up the environment variables correctly so that the peer command can work correctly.

正确设置环境变量,以便peer命令可以正常工作。

$ export FABRIC_CFG_PATH=../config/
$ source scripts/envVar.sh 
$ setGlobals 1
$ parsePeerConnectionParameters 1 2

Here, parsePeerConnectionParameters 1 2 sets the variables, especially $PEER_CONN_PARMS, so that endorsement requests for the invocation will be sent to both organization 1 and 2.

在这里, parsePeerConnectionParameters 1 2设置变量,尤其是$PEER_CONN_PARMS ,以便将对调用的认可请求发送到组织1和组织2。

调用链码 (Invoke a chaincode)

Now let’s invoke the fabcar chaincode to generate one transaction and its ID so that we can query the transaction out.

现在,我们调用fabcar链码来生成一个事务及其ID,以便我们可以查询该事务。

$ peer chaincode invoke \
-o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA \
$PEER_CONN_PARMS \
-C mychannel -n fabcar \
-c '{"function":"CreateCar","Args":["abc", "makeM", "modelX", "red", "ownerO"]}' \
--waitForEvent

It will show output as follows. The txid field contains the transaction ID for the new transaction.

它将显示如下输出。 txid字段包含新交易的交易ID。

2020-04-08 12:58:38.703 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f] committed with status (VALID) at localhost:7051
2020-04-08 12:58:38.713 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f] committed with status (VALID) at localhost:9051
2020-04-08 12:58:38.713 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 003 Chaincode invoke successful. result: status:200

通过交易ID查询交易 (Query the transaction out by transaction ID)

Now let’s query it out. For query, we only need to query from one organization 1. So set the environment variable again.

现在让我们查询一下。 对于查询,我们只需要从一个组织中查询1。因此,请再次设置环境变量。

$ parsePeerConnectionParameters 1

Now we are ready to invoke qscc chaincode’s GetTransactionByID function with the channel ID and transaction ID as the arguments:

现在,我们准备使用通道ID和事务ID作为参数来调用qscc chaincode的GetTransactionByID函数:

$ peer chaincode invoke \
-o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA \
$PEER_CONN_PARMS \
-C mychannel -n qscc \
-c '{"function":"GetTransactionByID","Args":["mychannel", "fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f"]}'

It will return the transaction payload out as a very long string.

它将以非常长的字符串形式返回事务负载。

2020-04-08 13:06:46.297 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"\n\232\037\n\317\036\n\301\007\ni\010\003\032\014\010\374\224\267\364\005\020\245\214\347\256\002\"\tmychannel*@fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f:\n\022\010\022\006fabcar\022\323\006\n\266\006\n\007Org2MSP\022\252\006-----BEGIN CERTIFICATE-----\nMIICKTCCAdCgAwIBAgIRANB520WsRCPUtHxGxXAF/zQwCgYIKoZIzj0EAwIwczEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzIuZXhhbXBsZS5jb20wHhcNMjAwNDA4MTAxMDAwWhcNMzAwNDA2MTAxMDAw\nWjBrMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\nU2FuIEZyYW5jaXNjbzEOMAwGA1UECxMFYWRtaW4xHzAdBgNVBAMMFkFkbWluQG9y\nZzIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT87rGWke+T\nMcPm5IWJ2Z345AgSSMyYM56oCAQw5pU6HiSzkIX2SYyfM3qhgxXuDKtDLRl+6oAQ\nH9TkdJXiuDwIo00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNV\nHSMEJDAigCB3CtCiWYUiHns2+BB5oaDbGmkpCFLgi/AHVgS1ZQHvzzAKBggqhkjO\nPQQDAgNHADBEAiA4+SsMgSJY1iMyBaqmqhUWCAdPeiFgjZcoPwxP6mXxigIgWDU2\nNLpKgqSXz0Qkv4f560F2HmjDcE2OiXH2RnSn/DU=\n-----END CERTIFICATE-----\n\022\030\337\033\362\341\3530\362 \243\357\316i\257\247\244y0D\246\274\241\240\013\267\022\210\027\n\205\027\n\323\006\n\266\006\n\007Org2MSP\022\252\006-----BEGIN CERTIFICATE-----\nMIICKTCCAdCgAwIBAgIRANB520WsRCPUtHxGxXAF/zQwCgYIKoZIzj0EAwIwczEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzIuZXhhbXBsZS5jb20wHhcNMjAwNDA4MTAxMDAwWhcNMzAwNDA2MTAxMDAw\nWjBrMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\nU2FuIEZyYW5jaXNjbzEOMAwGA1UECxMFYWRtaW4xHzAdBgNVBAMMFkFkbWluQG9y\nZzIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT87rGWke+T\nMcPm5IWJ2Z345AgSSMyYM56oCAQw5pU6HiSzkIX2SYyfM3qhgxXuDKtDLRl+6oAQ\nH9TkdJXiuDwIo00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNV\nHSMEJDAigCB3CtCiWYUiHns2+BB5oaDbGmkpCFLgi/AHVgS1ZQHvzzAKBggqhkjO\nPQQDAgNHADBEAiA4+SsMgSJY1iMyBaqmqhUWCAdPeiFgjZcoPwxP6mXxigIgWDU2\nNLpKgqSXz0Qkv4f560F2HmjDcE2OiXH2RnSn/DU=\n-----END CERTIFICATE-----\n\022\030\337\033\362\341\3530\362 \243\357\316i\257\247\244y0D\246\274\241\240\013\267\022\254\020\n>\n<\n:\010\001\022\010\022\006fabcar\032,\n\tCreateCar\n\003abc\n\005makeM\n\006modelX\n\003red\n\006ownerO\022\351\017\n\341\001\n \224\316G\014Piw[C\356\342\241\223\360\314\026+\317\370\271\2405\207\202r\242\361\253\270\207\275\271\022\274\001\n\247\001\0227\n\n_lifecycle\022)\n'\n!namespaces/fields/fabcar/Sequence\022\002\010\005\022l\n\006fabcar\022b\n\026\n\020\000\364\217\277\277initialized\022\002\010\006\032H\n\003abc\032A{\"make\":\"makeM\",\"model\":\"modelX\",\"colour\":\"red\",\"owner\":\"ownerO\"}\032\003\010\310\001\"\013\022\006fabcar\032\0011\022\375\006\n\262\006\n\007Org2MSP\022\246\006-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIPT1M5v/RIw2pFGFV43bRcMAoGCCqGSM49BAMCMHMxCzAJ\nBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJh\nbmNpc2NvMRkwFwYDVQQKExBvcmcyLmV4YW1wbGUuY29tMRwwGgYDVQQDExNjYS5v\ncmcyLmV4YW1wbGUuY29tMB4XDTIwMDQwODEwMTAwMFoXDTMwMDQwNjEwMTAwMFow\najELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xDTALBgNVBAsTBHBlZXIxHzAdBgNVBAMTFnBlZXIwLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATED9XSksxuJut0\nFMoFakmzA6T3xWg5ktg720SDBjaKX03YOT+c+d4gIyWt+OoVp1CgSrGDZD1+P/BH\ntc4OY7uio00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNVHSME\nJDAigCB3CtCiWYUiHns2+BB5oaDbGmkpCFLgi/AHVgS1ZQHvzzAKBggqhkjOPQQD\nAgNHADBEAiAofLpGCn75/iezwWRutN7O8YMDiji2i8+gwPItfaRLzwIgFvgqbGCY\nWzJOKtfwoDVWamWpMWlMWNFqDrD37IEeGs8=\n-----END CERTIFICATE-----\n\022F0D\002 _2\220B\327]\306\2522ZDa\224\211\231\257\320\313\306\026\254\307\307\344\330+\352\006\001\3752\003\002 *3\250\214lfK\353\267\235\233\333`0\241\2102\033\202F>\207|p\352\330\341\271\264\2453\033\022\202\007\n\266\006\n\007Org1MSP\022\252\006-----BEGIN CERTIFICATE-----\nMIICKDCCAc+gAwIBAgIRAONRdxDRTUieH3V5HwUgOnUwCgYIKoZIzj0EAwIwczEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwNDA4MTAxMDAwWhcNMzAwNDA2MTAxMDAw\nWjBqMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\nU2FuIEZyYW5jaXNjbzENMAsGA1UECxMEcGVlcjEfMB0GA1UEAxMWcGVlcjAub3Jn\nMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBjL6HrhcvoK\n/pWpiQlGG2Y+gbz/norGp+M8ep+8J4pop4qAU+tu2rm46AZBwkn7o76zRWcbDfRp\n9hf8jBlETRijTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1Ud\nIwQkMCKAIP1CJqu24vSd4ZMQUFEHS2d5USD8U5gYAjbHPxnhZpjRMAoGCCqGSM49\nBAMCA0cAMEQCIBR7lI1wwY4641P9Kg4n7Nq3trhc5ztQeQxadcwybBG/AiBE7M4d\n8LTCTMksf4d4QN50oSTussem8HmilE6Wt7iYCQ==\n-----END CERTIFICATE-----\n\022G0E\002!\000\263x.O\360G\315\276b\325\377\272]$\177@Z\375B^\017K\036\222\251\001lwS%\202v\002 \034\333%\214\023s\202\270?\270>\212:M\274\360\275O\"s\317\210\267\375F\363\316K\202\370PN\022F0D\002 M/7\005\276\312:\337\361Z\033\272a.\326\017\314\006Ov\244\374V\271W\341\034\336[\314@\245\002 \005\216i\345 \304\222\306C\330\370A\301\236etb\005P\361\242\2731[\330u\225l#\271\022\r"

Now we get the serialized transaction content in the payload part of the response. From the beginning part, we can find the mychannel*@fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f string which contains the channel ID and the transaction ID.

现在,我们在响应的payload部分中获取序列化的事务内容。 从开始部分,我们可以找到mychannel*@fa0f757bc278fdf6a32d00975602eb853e23a86a156781588d99ddef5b80720f字符串,其中包含通道ID和事务ID。

反序列化交易 (Deserialize the transaction)

From the GetTransactionByID query implementation, the chaincode calls func (l *kvLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) and marshals the returned peer.ProcessedTransaction struct for the response.

GetTransactionByID查询实现中 ,链码调用func (l *kvLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error)peer.ProcessedTransaction返回的peer.ProcessedTransaction结构以获取响应。

The peer.ProcessedTransaction struct is a protobuf struct defined in peer/transaction.proto and the generated Go struct is defined in the peer/transaction.pb.go file.

peer.ProcessedTransaction结构是在peer/transaction.proto定义的protobuf结构,并且生成的Go结构在peer/transaction.pb.go文件中定义。

If you would like to deserizlie the transaction, you may parse it into a peer.ProcessedTransaction struct using any programming language that can unmarshal the marshalled protobuf struct.

如果您想反序列化事务,则可以使用可以解组封送的protobuf结构的任何编程语言将其解析为peer.ProcessedTransaction结构。

翻译自: https://www.systutorials.com/how-to-query-transaction-by-id-in-hyperledger-fabric-2-0/