兄弟连区块链教程Fabric1.0源代码分析Tx RWSet(读写集)

栏目: 编程工具 · 发布时间: 7年前

内容简介:区块链教程Fabric1.0源代码分析Tx RWSet(读写集),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。在背书节点模拟Transaction期间,为交易准备了一个读写集合。 Read Set包含模拟Transaction读取的Key和版本的列表,Write Set包含Key、写入的新值、以及删除标记(是否删除Key)。RWSet相关代码分布在protos/ledge

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

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
感谢关注兄弟连区块链教程分享!

兄弟连区块链教程Fabric1.0源代码分析Tx RWSet(读写集) 兄弟连区块链教程Fabric1.0源代码分析Tx RWSet(读写集)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python 3面向对象编程

Python 3面向对象编程

[加]Dusty Phillips(达斯帝•菲利普斯) / 肖鹏、常贺、石琳 / 电子工业出版社 / 2015-6 / 79.00元

Python 是一种面向对象的解释型语言,面向对象是其非常重要的特性。《Python 3面向对象编程》通过Python 的数据结构、语法、设计模式,从简单到复杂,从初级到高级,一步步通过例子来展示了Python 中面向对象的概念和原则。 《Python 3面向对象编程》不是Python 的入门书籍,适合具有Python 基础经验的开发人员阅读。如果你拥有其他面向对象语言的经验,你会更容易理解......一起来看看 《Python 3面向对象编程》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具