博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
区块链教程Fabric1.0源代码分析Tx RWSet(读写集)
阅读量:6385 次
发布时间:2019-06-23

本文共 7737 字,大约阅读时间需要 25 分钟。

  区块链教程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)

TxReadWriteSet结构体:

type TxReadWriteSet_DataModel int32const (    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)

type TxRwSet struct {    NsRwSets []*NsRwSet}type NsRwSet struct {    NameSpace string    KvRwSet   *kvrwset.KVRWSet}//按TxRwSet构造TxReadWriteSet并序列化func (txRwSet *TxRwSet) ToProtoBytes() ([]byte, error)//[]byte反序列化为TxReadWriteSet,按TxReadWriteSet构造TxRwSetfunc (txRwSet *TxRwSet) FromProtoBytes(protoBytes []byte) error//构造KVReadfunc NewKVRead(key string, version *version.Height) *kvrwset.KVRead//构造version.Heightfunc NewVersion(protoVersion *kvrwset.Version) *version.Height//构造Versionfunc newProtoVersion(height *version.Height) *kvrwset.Version//构造KVWritefunc 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

涉及方法如下:

//构造nsRWsfunc newNsRWs() *nsRWs//构造RWSetBuilderfunc NewRWSetBuilder() *RWSetBuilder//构造KVRead,并加入nsRWs.readMapfunc (rws *RWSetBuilder) AddToReadSet(ns string, key string, version *version.Height)//构造KVWrite,并加入nsRWs.writeMapfunc (rws *RWSetBuilder) AddToWriteSet(ns string, key string, value []byte)//用RangeQueryInfo构造rangeQueryKey,并将rangeQueryKey和RangeQueryInfo加入nsRWs.rangeQueriesKeys和nsRWs.rangeQueriesMapfunc (rws *RWSetBuilder) AddToRangeQuerySet(ns string, rqi *kvrwset.RangeQueryInfo)从RWSetBuilder构造TxRwSetfunc (rws *RWSetBuilder) GetTxReadWriteSet() *TxRwSet//获取或创建nsRWsfunc (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 uint32type Hash []byteconst leafLevel = MerkleTreeLevel(1)type merkleTree struct {    tree      map[MerkleTreeLevel][]Hash    maxLevel  MerkleTreeLevel //1    maxDegree uint32 //单层最大个数}//代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go

涉及方法如下:

//构造merkleTreefunc newMerkleTree(maxDegree uint32) (*merkleTree, error) //加入哈希,从第一层开始加,直至当前层哈希数量没有超过限额为止func (m *merkleTree) update(nextLeafLevelHash Hash) error func (m *merkleTree) done() error func (m *merkleTree) getSummery() *kvrwset.QueryReadsMerkleSummary //构造QueryReadsMerkleSummaryfunc (m *merkleTree) getMaxLevel() MerkleTreeLevel //获取maxLevelfunc (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转换为[][]bytefunc 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 := leafLevelfor {    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 Hashvar err errorfor 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,如果启用哈希将构造merkleTreefunc NewRangeQueryResultsHelper(enableHashing bool, maxDegree uint32) (*RangeQueryResultsHelper, error)//添加KVRead加入pendingResults,如果pendingResults数量超过限额,执行processPendingResultsfunc (helper *RangeQueryResultsHelper) AddResult(kvRead *kvrwset.KVRead) error//执行processPendingResults,并执行merkleTree.done()func (helper *RangeQueryResultsHelper) Done() ([]*kvrwset.KVRead, *kvrwset.QueryReadsMerkleSummary, error)//获取QueryReadsMerkleSummaryfunc (helper *RangeQueryResultsHelper) GetMerkleSummary() *kvrwset.QueryReadsMerkleSummary//pendingResults序列化并哈希后,加入merkleTree,并清空pendingResultsfunc (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

转载于:https://blog.51cto.com/14041296/2314540

你可能感兴趣的文章
java Calendar 日期的加减
查看>>
重写之后的脚本。希望还好
查看>>
简明解释算法中的大O符号
查看>>
环境搭建
查看>>
房间安排http://acm.nyist.net/JudgeOnline/problem.php?pid=168
查看>>
Effective Objective-C 2.0 — 第11条:理解 objc_msgSend 的作用
查看>>
模板:快速幂
查看>>
【Python第三篇】Python装饰器、生成器、迭代器
查看>>
JVM中的Stack和Frame
查看>>
java web项目(spring项目)中集成webservice ,实现对外开放接口
查看>>
关于robotframework,app,appium的xpath定位问题及常用方法
查看>>
IntersectionObserver
查看>>
.svn文件夹特别大
查看>>
div模块的隐藏与显示
查看>>
3.0、Android Studio构建和运行应用
查看>>
CentOS下用命令查看IP地址
查看>>
解决微信内置浏览器屏蔽下载链接问题
查看>>
分布式设计与开发(二)------几种必须了解的分布式算法
查看>>
Android显示gif格式图片
查看>>
PMP项目经理认证
查看>>