兄弟连区块链教程Fabric1.0源代码分析Tx RWSet(读写集)
兄弟连区块链教程Fabric1.0源代码分析Tx RWSet(读写集),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
Fabric 1.0源代码笔记 之 Tx #RWSet(读写集)
1、RWSet概述
在背书节点模拟Transaction期间,为交易准备了一个读写集合。
Read Set包含模拟Transaction读取的Key和版本的列表,Write Set包含Key、写入的新值、以及删除标记(是否删除Key)。
RWSet相关代码分布在protos/ledger/rwset、core/ledger/kvledger/txmgmt/rwsetutil目录下。目录结构如下:
- protos/ledger/rwset目录:
* rwset.pb.go,TxReadWriteSet和NsReadWriteSet结构体定义。
* kv_rwset.pb.go,KVRWSet、KVRead、KVWrite、Version、RangeQueryInfo结构体定义,以及isRangeQueryInfo_ReadsInfo接口定义。
- core/ledger/kvledger/txmgmt/rwsetutil目录:
* rwset_proto_util.go,TxRwSet和NsRwSet结构体及方法。
* rwset_builder.go,RWSetBuilder结构体及方法。
* query_results_helper.go,RangeQueryResultsHelper结构体及方法。
2、TxReadWriteSet结构体(protos)
有个图5
TxReadWriteSet结构体:
type TxReadWriteSet_DataModel int32 const ( TxReadWriteSet_KV TxReadWriteSet_DataModel = 0 ) type TxReadWriteSet struct { DataModel TxReadWriteSet_DataModel NsRwset []*NsReadWriteSet } type NsReadWriteSet struct { Namespace string Rwset []byte //KVRWSet 序列化 } //代码在protos/ledger/rwset/rwset.pb.go
KVRWSet结构体:
type KVRWSet struct { Reads []*KVRead RangeQueriesInfo []*RangeQueryInfo Writes []*KVWrite } type KVRead struct { Key string Version *Version } type KVWrite struct { Key string IsDelete bool Value []byte } type Version struct { BlockNum uint64 TxNum uint64 } type RangeQueryInfo struct { StartKey string EndKey string ItrExhausted bool ReadsInfo isRangeQueryInfo_ReadsInfo } 代码在protos/ledger/rwset/kvrwset/kv_rwset.pb.go
3、TxRwSet结构体及方法(core)
有个图6
type TxRwSet struct { NsRwSets []*NsRwSet } type NsRwSet struct { NameSpace string KvRwSet *kvrwset.KVRWSet } //按TxRwSet构造TxReadWriteSet并序列化 func (txRwSet *TxRwSet) ToProtoBytes() ([]byte, error) //[]byte反序列化为TxReadWriteSet,按TxReadWriteSet构造TxRwSet func (txRwSet *TxRwSet) FromProtoBytes(protoBytes []byte) error //构造KVRead func NewKVRead(key string, version *version.Height) *kvrwset.KVRead //构造version.Height func NewVersion(protoVersion *kvrwset.Version) *version.Height //构造Version func newProtoVersion(height *version.Height) *kvrwset.Version //构造KVWrite func newKVWrite(key string, value []byte) *kvrwset.KVWrite //代码在core/ledger/kvledger/txmgmt/rwsetutil/rwset_proto_util.go
4、RWSetBuilder结构体及方法
RWSetBuilder结构体定义:
type RWSetBuilder struct { rwMap map[string]*nsRWs //Namespace } type nsRWs struct { readMap map[string]*kvrwset.KVRead //KVRead map writeMap map[string]*kvrwset.KVWrite //KVWrite map rangeQueriesMap map[rangeQueryKey]*kvrwset.RangeQueryInfo //RangeQueryInfo map rangeQueriesKeys []rangeQueryKey //rangeQueryKey数组 } type rangeQueryKey struct { startKey string endKey string itrExhausted bool //迭代器是否用尽 } //代码在core/ledger/kvledger/txmgmt/rwsetutil/rwset_builder.go
涉及方法如下:
//构造nsRWs func newNsRWs() *nsRWs //构造RWSetBuilder func NewRWSetBuilder() *RWSetBuilder //构造KVRead,并加入nsRWs.readMap func (rws *RWSetBuilder) AddToReadSet(ns string, key string, version *version.Height) //构造KVWrite,并加入nsRWs.writeMap func (rws *RWSetBuilder) AddToWriteSet(ns string, key string, value []byte) //用RangeQueryInfo构造rangeQueryKey,并将rangeQueryKey和RangeQueryInfo加入nsRWs.rangeQueriesKeys和nsRWs.rangeQueriesMap func (rws *RWSetBuilder) AddToRangeQuerySet(ns string, rqi *kvrwset.RangeQueryInfo) 从RWSetBuilder构造TxRwSet func (rws *RWSetBuilder) GetTxReadWriteSet() *TxRwSet //获取或创建nsRWs func (rws *RWSetBuilder) getOrCreateNsRW(ns string) *nsRWs //代码在core/ledger/kvledger/txmgmt/rwsetutil/rwset_builder.go
5、RangeQueryResultsHelper结构体及方法(什么用途呢???)
5.1、merkleTree(默克尔树)
Merkle Tree,也称Hash Tree,即存储hash值的一棵树。
Merkle树的叶子是数据块的hash值,非叶节点是其对应子节点串联字符串的hash。
type MerkleTreeLevel uint32 type Hash []byte const leafLevel = MerkleTreeLevel(1) type merkleTree struct { tree map[MerkleTreeLevel][]Hash maxLevel MerkleTreeLevel //1 maxDegree uint32 //单层最大个数 } //代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go
涉及方法如下:
//构造merkleTree func newMerkleTree(maxDegree uint32) (*merkleTree, error) //加入哈希,从第一层开始加,直至当前层哈希数量没有超过限额为止 func (m *merkleTree) update(nextLeafLevelHash Hash) error func (m *merkleTree) done() error func (m *merkleTree) getSummery() *kvrwset.QueryReadsMerkleSummary //构造QueryReadsMerkleSummary func (m *merkleTree) getMaxLevel() MerkleTreeLevel //获取maxLevel func (m *merkleTree) getMaxLevelHashes() []Hash //maxLevel层哈希数组 func (m *merkleTree) isEmpty() bool //maxLevel为1且第1层哈希数组为空 func (m *merkleTree) String() string //String //计算哈希数组合并后哈希 func computeCombinedHash(hashes []Hash) (Hash, error) //[]Hash转换为[][]byte func hashesToBytes(hashes []Hash) [][]byte //代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go
func (m *merkleTree) update(nextLeafLevelHash Hash) error代码如下:
//const leafLevel = MerkleTreeLevel(1) m.tree[leafLevel] = append(m.tree[leafLevel], nextLeafLevelHash) //先加入第一层 currentLevel := leafLevel for { currentLevelHashes := m.tree[currentLevel] //如果当前层数量没有超过限额,则返回,即Hash加到没有数量超出限额的层为止 if uint32(len(currentLevelHashes)) <= m.maxDegree { return nil } //如果当前层数量超过限额 nextLevelHash, err := computeCombinedHash(currentLevelHashes) //计算当前层合并哈希 delete(m.tree, currentLevel) //删除当前层 nextLevel := currentLevel + 1 //进入更高一层 m.tree[nextLevel] = append(m.tree[nextLevel], nextLevelHash) //合并哈希加入更高一层 if nextLevel > m.maxLevel { //如果更高一层层高超过原定最大高度,则重置最大高度为更高一层层高 m.maxLevel = nextLevel } currentLevel = nextLevel //更新当前层为更高一层 } //代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go
func (m *merkleTree) done() error代码如下:
currentLevel := leafLevel //从第一层开始 var h Hash var err error for currentLevel < m.maxLevel { //循环至最高层 currentLevelHashes := m.tree[currentLevel] switch len(currentLevelHashes) { case 0: //当前层数量为0,进入更高一层 currentLevel++ continue case 1: //当前层数量为1,获取当前值 h = currentLevelHashes[0] default: //当前层数量1个,计算合并哈希 h, err = computeCombinedHash(currentLevelHashes) } delete(m.tree, currentLevel) //删除当前层 currentLevel++ //进入更高一层 m.tree[currentLevel] = append(m.tree[currentLevel], h) //前一层合并哈希加入本层 } finalHashes := m.tree[m.maxLevel] //最高一层 if uint32(len(finalHashes)) > m.maxDegree { //如果最高一层超出限额 delete(m.tree, m.maxLevel) //删除本层 m.maxLevel++ //进入更高一层 combinedHash, err := computeCombinedHash(finalHashes) //计算合并哈希 m.tree[m.maxLevel] = []Hash{combinedHash} //哈并哈希加入新的最高层 } return nil //代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go
5.2 RangeQueryResultsHelper
RangeQueryResultsHelper定义:
type RangeQueryResultsHelper struct { pendingResults []*kvrwset.KVRead mt *merkleTree //merkleTree maxDegree uint32 hashingEnabled bool } //代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go
涉及方法如下:
//构造RangeQueryResultsHelper,如果启用哈希将构造merkleTree func NewRangeQueryResultsHelper(enableHashing bool, maxDegree uint32) (*RangeQueryResultsHelper, error) //添加KVRead加入pendingResults,如果pendingResults数量超过限额,执行processPendingResults func (helper *RangeQueryResultsHelper) AddResult(kvRead *kvrwset.KVRead) error //执行processPendingResults,并执行merkleTree.done() func (helper *RangeQueryResultsHelper) Done() ([]*kvrwset.KVRead, *kvrwset.QueryReadsMerkleSummary, error) //获取QueryReadsMerkleSummary func (helper *RangeQueryResultsHelper) GetMerkleSummary() *kvrwset.QueryReadsMerkleSummary //pendingResults序列化并哈希后,加入merkleTree,并清空pendingResults func (helper *RangeQueryResultsHelper) processPendingResults() error //KVRead序列化 func serializeKVReads(kvReads []*kvrwset.KVRead) ([]byte, error)
补充 QueryReadsMerkleSummary:
type QueryReadsMerkleSummary struct { MaxDegree uint32 MaxLevel uint32 MaxLevelHashes [][]byte } //代码在protos/ledger/rwset/kvrwset/kv_rwset.pb.go
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
10行代码识别二维码
二维码现在已深入到我们生活的方方面面了,手机支付、微信加好友、app下载、电子票务等方方面面都有它的身影。最近坐地铁又推出了扫二维码进出站。 最近一段时间,上海的很多地铁检票机器都装上了像下面这样的二维码扫描器 只需打开手机app上的二维码,对准扫描窗口扫一扫,就可以进站,到站后再扫一扫,就可以出站并自动扣款。 今天我们就来用Python实现一个简单的识别二维码的程序。 准备工作 识别二维码需要用到zbar,首先安装libzbar0,以Ubuntu为例 sudo apt-get install libzbar0 接着安装pyzbar和opencv pip install pyzbar pip install opencv-python 代码实现 接下来是我们的代码实现部分了,可以看到代码非常简单。 # -*- coding: utf-8 -*-# fi
- 下一篇
这门编程语言被误解18年,出生就遭鄙视,原因是“国产货”?
世界上有据可考的编程语言,一共不下600多种,它们的写法可以说是千奇百怪,有用英语作为媒介的,也有用符号编程的,甚至有模仿牛的叫声进行编程的。在众多编程语言中,一门语言被称作“国人骄傲”,只是自打它出生之后,特别是专业人士,对其评价都极低,甚至引来各方嘲讽,它就是易语言。 易语言的发明者是吴涛,2000年伊始,从事长期开发的吴涛,编写了70多万行源代码,发明了E语言,后来改称“易语言”,这是一个完全使用中文编程的语言,目的是降低编程门槛,让不懂英语的中国人,也可以学会编程,顺利迈过不会英语的门槛。 因为易语言的发明,吴涛被《程序员》杂志评为“影响中国软件开发的20人”之一。易语言汉语编程环境获中国十大自主创新软件产品奖。 一切是那么的美好,中国人终于拥有了自己的编程语言。可让吴涛没想到的是,易语言却成为了众矢之的,受到了很多程序员的批评。 最大的原因在于,易语言解决了一个不存在的痛点,即完全不会英语的程序员极少。具备英文能力的程序员从来不缺,将来更不可缺。 的确,虽然现实中,有很多程序员英语水平极差,除了常用的英文外,几乎看不懂其他,更别说阅读英文文档。一门编程语言,常用的英语词汇不过...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作