如何解码Hyperledger Fabric中qscc的GetBlockByTxID返回的数字结果
通过TxID获取区块编号的问题解决(Ubuntu 20.04 + Fabric 2.4.4)
问题背景
- 环境:Ubuntu 20.04,Hyperledger Fabric 2.4.4
- 需求:根据交易ID(TxID)查询对应的区块编号
- 遇到的问题:调用系统链码
qscc的GetBlockByTxID接口后,返回结果以十进制数字数组形式呈现(peer chaincode query全为数字,peer chaincode invoke部分为数字),直接转字符串无法解析出区块编号。
解决方法
方法1:命令行解析二进制结果(通用方案)
qscc返回的是区块的Protobuf二进制数据,被命令行工具转成了数字数组,需要转回二进制再解析:
- 安装依赖工具:
sudo apt update && sudo apt install jq protobuf-compiler -y - 获取Fabric 2.4.4的Protobuf定义文件:
git clone https://github.com/hyperledger/fabric.git -b v2.4.4 cd fabric/protos - 执行查询并解析区块编号:
# 替换<通道名>和<TxID>为实际值,执行查询并保存结果 peer chaincode query -C <通道名> -n qscc -c '{"Args":["GetBlockByTxID", "<通道名>", "<TxID>"]}' > block_data.json # 将数字数组转为二进制文件 jq -r '.result | map(. | tostring) | join(",")' block_data.json | xargs -I {} printf "%b" "$(echo {} | sed 's/,/\\x/g')" > block.bin # 解析二进制文件,提取区块编号 protoc --decode=common.Block ./common/common.proto ./common/block.proto < block.bin | grep "number:"
方法2:使用SDK直接获取结构化数据(以Go SDK为例)
如果命令行解析繁琐,用Fabric SDK可以直接拿到结构化的区块对象,快速提取编号:
package main import ( "fmt" "github.com/golang/protobuf/proto" common "github.com/hyperledger/fabric-protos-go/common" "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" ) func main() { // 加载SDK配置文件(替换为你的config.yaml路径) sdk, err := fabsdk.New(config.FromFile("config.yaml")) if err != nil { fmt.Printf("SDK初始化失败: %v\n", err) return } defer sdk.Close() // 创建通道客户端(替换<通道名>、<用户名>、<组织名>为实际值) clientCtx := sdk.ChannelContext("<通道名>", fabsdk.WithUser("<用户名>"), fabsdk.WithOrg("<组织名>")) client, err := channel.New(clientCtx) if err != nil { fmt.Printf("通道客户端创建失败: %v\n", err) return } // 调用qscc查询区块 req := channel.Request{ ChaincodeID: "qscc", Fcn: "GetBlockByTxID", Args: [][]byte{[]byte("<通道名>"), []byte("<TxID>")}, } resp, err := client.Query(req) if err != nil { fmt.Printf("查询失败: %v\n", err) return } // 反序列化区块数据 var block common.Block if err := proto.Unmarshal(resp.Payload, &block); err != nil { fmt.Printf("区块反序列化失败: %v\n", err) return } // 输出区块编号 fmt.Printf("对应区块编号: %d\n", block.Header.Number) }
方法3:简化命令行解析(仅支持部分版本)
如果你的Fabric 2.4.4支持--output json参数,可以直接用jq提取:
peer chaincode query -C <通道名> -n qscc -c '{"Args":["GetBlockByTxID", "<通道名>", "<TxID>"]}' --output json | jq '.result.header.number'
内容的提问来源于stack exchange,提问作者hzau-cp3
相关产品推荐
相关产品推荐

