根据TxID获取上链数据
根据TxID获取上链信息
前段时间应甲方爸爸的要求,需要在现有的业务系统中新增一个根据TxID来查询上链信息的接口。搜了一圈发现相关的信息很少,最后只能祭出终极大招:Read Source Code。
本文主要记录我实现这一功能的过程。
1、获取交易信息
首先要做的就是拿到交易信息,我这里是通过fabric-sdk-go提供的接口ledger.Client.QueryTransaction(transactionID fab.TransactionID, options ...RequestOption) (*pb.ProcessedTransaction, error)来获取交易信息;交易信息就包含在ProcessedTransaction结构中。
1.1、ProcessedTransaction
ProcessedTransaction定义如下:
type ProcessedTransaction struct {
// 封装了所有的交易信息
TransactionEnvelope *common.Envelope `protobuf:"bytes,1,opt,name=transactionEnvelope,proto3" json:"transactionEnvelope,omitempty"`
// 标识交易是否通过验证
ValidationCode int32 `protobuf:"varint,2,opt,name=validationCode,proto3" json:"validationCode,omitempty"`
}
2、解析TransactionEnvelope
交易信息全都封装在common.Envelope结构中:
// Envelope wraps a Payload with a signature so that the message may be authenticated
type Envelope struct {
// 编码后的交易信息,是common.Payload编码后的
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
// 交易发起人的签名
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
}
2.1、common.Payload
common.Payload定义如下:
// Payload is the message contents (and header to allow for signing)
type Payload struct {
// Header is included to provide identity and prevent replay
Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
// 编码后的peer.Transaction,该结构保存交易信息
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
}
2.2、peer.Transaction
peer.Transaction结构中包含了该交易的所有活动:
type Transaction struct {
// The payload is an array of TransactionAction. An array is necessary to
// accommodate multiple actions per transaction
Actions []*TransactionAction `protobuf:"bytes,1,rep,name=actions,proto3" json:"actions,omitempty"`
}
这个结构就是整个接口的核心,说白了就是要解析TransactionAction结构。
3、解析peer.TransactionAction
peer.TransactionAction定义如下:
type TransactionAction struct {
// The header of the proposal action, which is the proposal header
Header []byte `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
// bytes格式的ChaincodeActionPayload
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
}
其中Payload中包含着我们想要的信息。
3.1、peer.ChaincodeActionPayload
peer.ChaincodeActionPayload定义如下:
type ChaincodeActionPayload struct {
ChaincodeProposalPayload []byte `protobuf:"bytes,1,opt,name=chaincode_proposal_payload,json=chaincodeProposalPayload,proto3" json:"chaincode_proposal_payload,omitempty"`
// 在账本中执行的操作
Action *ChaincodeEndorsedAction `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"`
}
其中的我们要找的信息就在这个Action里。
3.2、peer.ChaincodeEndorsedAction
peer.ChaincodeEndorsedAction定义如下:
type ChaincodeEndorsedAction struct {
// This is the bytes of the ProposalResponsePayload message signed by the
// endorsers. Recall that for the CHAINCODE type, the
// ProposalResponsePayload's extenstion field carries a ChaincodeAction
ProposalResponsePayload []byte `protobuf:"bytes,1,opt,name=proposal_response_payload,json=proposalResponsePayload,proto3" json:"proposal_response_payload,omitempty"`
Endorsements []*Endorsement `protobuf:"bytes,2,rep,name=endorsements,proto3" json:"endorsements,omitempty"`
}
从ProposalResponsePayload字段解出peer.ProposalResponsePayload结构:
type ProposalResponsePayload struct {
ProposalHash []byte `protobuf:"bytes,1,opt,name=proposal_hash,json=proposalHash,proto3" json:"proposal_hash,omitempty"`
// 对chaincode来说, Extension保存ChaincodeAction信息
Extension []byte `protobuf:"bytes,2,opt,name=extension,proto3" json:"extension,omitempty"`
}
接下来就是解Extension。
3.3、peer.ChaincodeAction
peer.ChaincodeAction定义如下:
type ChaincodeAction struct {
// chaincode执行影响到的读写集
Results []byte `protobuf:"bytes,1,opt,name=results,proto3" json:"results,omitempty"`
// This field contains the events generated by the chaincode executing this
// invocation.
Events []byte `protobuf:"bytes,2,opt,name=events,proto3" json:"events,omitempty"`
// chaincode调用结果
Response *Response `protobuf:"bytes,3,opt,name=response,proto3" json:"response,omitempty"`
// 调用的chaincode的信息
ChaincodeId *ChaincodeID `protobuf:"bytes,4,opt,name=chaincode_id,json=chaincodeId,proto3" json:"chaincode_id,omitempty"`
// This field contains the token expectation generated by the chaincode
// executing this invocation
TokenExpectation *token.TokenExpectation `protobuf:"bytes,5,opt,name=token_expectation,json=tokenExpectation,proto3" json:"token_expectation,omitempty"`
}
至此,我们才算拿到我们真正想要的东西 --- 没错,就是这个Results。
4、解析TxReadWriteSet
rwset.TxReadWriteSet结构定义如下:
type TxReadWriteSet struct {
DataModel TxReadWriteSet_DataModel `protobuf:"varint,1,opt,name=data_model,json=dataModel,proto3,enum=rwset.TxReadWriteSet_DataModel" json:"data_model,omitempty"`
NsRwset []*NsReadWriteSet `protobuf:"bytes,2,rep,name=ns_rwset,json=nsRwset,proto3" json:"ns_rwset,omitempty"`
}
NsReadWriteSet定义:
type NsReadWriteSet struct {
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Rwset []byte `protobuf:"bytes,2,opt,name=rwset,proto3" json:"rwset,omitempty"`
CollectionHashedRwset []*CollectionHashedReadWriteSet `protobuf:"bytes,3,rep,name=collection_hashed_rwset,json=collectionHashedRwset,proto3" json:"collection_hashed_rwset,omitempty"`
}
其中这个Rwset就是我们的目标,它是kvrwset.KVRWSet编码后得到的。
4.1、kvrwset.KVRWSet
kvrwset.KVRWSet定义如下:
type KVRWSet struct {
Reads []*KVRead `protobuf:"bytes,1,rep,name=reads,proto3" json:"reads,omitempty"`
RangeQueriesInfo []*RangeQueryInfo `protobuf:"bytes,2,rep,name=range_queries_info,json=rangeQueriesInfo,proto3" json:"range_queries_info,omitempty"`
Writes []*KVWrite `protobuf:"bytes,3,rep,name=writes,proto3" json:"writes,omitempty"`
MetadataWrites []*KVMetadataWrite `protobuf:"bytes,4,rep,name=metadata_writes,json=metadataWrites,proto3" json:"metadata_writes,omitempty"`
}
之后通过解析Writes就能获取到上链的数据,即调用shim.PutState(key string, value []byte)使用的key和value。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: MengBin
根据TxID获取上链数据的更多相关文章
- C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据
我曾经在系列文章中的<C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍>中介绍了微信菜单里面的重定向操作,通过这个重定向操作,我们可以获取一个code值,然后获取用户的open ...
- jdbc java数据库连接 7)获取插入数据的自增长值
我们创建一个sql表,里面的数据往往都会有自增长值. 那么,我们用jdbc插入数据的时候,要想同时获得这个增长值. 代码: /** * * 这是插入一条数据的同时,获取该数据的则增长列的值(该例子的自 ...
- 室内定位系列(二)——仿真获取RSS数据
很多情况下大家都采用实际测量的数据进行定位算法的性能分析和验证,但是实际测量的工作量太大.数据不全面.灵活性较小,采用仿真的方法获取RSS数据是另一种可供选择的方式.本文介绍射线跟踪技术的基本原理,以 ...
- asp.net三层架构 及其中使用泛型获取实体数据介绍
asp.net中使用泛型获取实体数据可以发挥更高的效率,代码简洁方便,本例采用三层架构.首先在model层中定义StuInfo实体,然后在 DAL层的SQLHelper数据操作类中定义list< ...
- android 从服务器获取新闻数据并显示在客户端
新闻客户端案例 第一次进入新闻客户端需要请求服务器获取新闻数据,做listview的展示, 为了第二次再次打开新闻客户端时能快速显示新闻,需要将数据缓存到数据库中,下次打开可以直接去数据库中获取新闻直 ...
- 对 griview获取的数据添加方法 6月
<asp:TemplateField HeaderText="日期"> <HeaderStyle CssCl ...
- 速战速决 (6) - PHP: 获取 http 请求数据, 获取 get 数据 和 post 数据, json 字符串与对象之间的相互转换
[源码下载] 速战速决 (6) - PHP: 获取 http 请求数据, 获取 get 数据 和 post 数据, json 字符串与对象之间的相互转换 作者:webabcd 介绍速战速决 之 PHP ...
- 【Spring】获取资源文件+从File+从InputStream对象获取正文数据
1.获取资源文件或者获取文本文件等,可以通过Spring的Resource的方式获取 2.仅有File对象即可获取正文数据 3.仅有InputStream即可获取正文数据 package com.sx ...
- java URL实现调用其他系统发送报文并获取返回数据
模拟本系统通过Url方式发送报文到目标服务器,并获取返回数据:(实现类) import java.io.BufferedOutputStream; import java.io.BufferedRea ...
- ajax请求获取的数据无法赋值给全局变量问题总结
一.总结: 1.问题描述: 今天做项目遇到在用表单显示详细信息的过程中ajax请求获取的数据无法赋值给全局变量的情况,从列表页面进入详情页,在详情页面被渲染了之后就会调用js文件里的接口向服务器请求数 ...
随机推荐
- 从数据链路到神秘的MAC地址和ARP协议
引言 链路是指从一个结点到相邻结点的一段物理线路.数据链路是在链路的基础上增加了一些必要的硬件和软件.这些硬件包括网络适配器,而软件则包括协议的实现.在网络中,主机.路由器等设备都必须实现数据链路层. ...
- Grafana--变量(label_values)
grafana官方文档:https://grafana.com/docs/grafana/latest/ 版本:6.5.2 模板与变量(摘抄自官方文档): 变量是值的占位符.您可以在度量查询和面板标题 ...
- 使用nginx代理emqx的TCP、WS、WSS连接请求
项目代理关系: 注:主机上已存在名为:nginx-proxy 的一级 nginx 的代理,将监听了主机的 80.443端口 docker-compose.yml version: "3.7& ...
- Codeforces Round #704 (Div. 2) A~E
比赛链接:https://codeforces.com/contest/1492 1492A.Three swimmers 题意: 有三名游泳的人,他们分别需要 \(a,b,c\) 分钟才能在一个游泳 ...
- 【每日一题】28. 模拟战役 (模拟 + DFS/BFS/并查集)
补题链接:Here 本题属于一道模拟题 虽然这题介绍一大堆,总结起来就是几句话,给出地图n列,前4行是a的地盘,后四行是b的地盘,每个人地盘上面有星号代表大炮. 大炮会 3 * 3的波及周围,会一直传 ...
- 2017年第八届 蓝桥杯B组C/C++决赛题目
部分题目示意图来自网络,所以会带水印 最后编辑时间: 2021年5月12日 统一声明 如果不写默认带有常用头文件 如果不表明主函数默认表示在 void solve(){} 默认使用 using nam ...
- C#开源跨平台的多功能Steam工具箱&GitHub加速神器
前言 作为一个程序员你是否会经常会遇到GitHub无法访问(如下无法访问图片),或者是访问和下载源码时十分缓慢就像乌龟爬行一般.今天分享一款C#开源的.跨平台的多功能Steam工具箱和GitHub加速 ...
- C#多曲线数据分析
数据如下 统计效果图如下 程序初始化 private void Form1_Load(object sender, EventArgs e) { using (SqlConnection con = ...
- 机器学习-决策树系列-XGBoost算法-chentianqi大神-集成学习-31
目录
- 机器学习-线性回归-损失函数+正则化regularization-06
目录 1. 为什么要加上正则项 2 L1稀疏 L2平滑 3. 代码1--L2正则 4 代码2--L2正则2 5. 代码3--l1正则 6. ElasticNet 1. 为什么要加上正则项 防止模型的过 ...