返回
北京兄弟连IT
置顶
该校与厚学网暂未合作,平台不保证课程的真实有效性,如有侵权等争议,请及时与厚学网联系处理
招生热线:400-800-2181

学校地址:北京市昌平区回龙观文华西路育荣教育园区兄弟连IT教育

兄弟连区块链教程源代码Tx RWSet

325 2018-11-09 09:11:24

学习笔记

  兄弟连区块链教程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结构体:

 

```go

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结构体:

 

```go

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)

```go

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结构体定义:

 

```go

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

```

 

涉及方法如下:

 

```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。

 

```go

type MerkleTreeLevel uint32

type Hash []byte

const leafLevel = MerkleTreeLevel(1)

 

type merkleTree struct {

    tree      map[MerkleTreeLevel][]Hash

    maxLevel  MerkleTreeLevel //1

    maxDegree uint32 //单层zui个数

}

//代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go

```

 

涉及方法如下:

 

```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代码如下:

 

```go

//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 { //如果更高一层层高超过原定zui高度,则重置zui高度为更高一层层高

        m.maxLevel = nextLevel

    }

    currentLevel = nextLevel //更新当前层为更高一层

}

//代码在core/ledger/kvledger/txmgmt/rwsetutil/query_results_helper.go

```

 

func (m *merkleTree) done() error代码如下:

 

```go

currentLevel := leafLevel //从第-一层开始

var h Hash

var err error

for currentLevel < m.maxLevel { //循环至zui

    currentLevelHashes := m.tree[currentLevel]

    switch len(currentLevelHashes) {

    case 0: //当前层数量为0,进入更高一层

        currentLevel++

来源:北京兄弟连IT

热门课程 全部课程

热门动态

申请免费试听

只要一个电话

我们为您免费回电

立即申请
刷新
图形验证
关闭
>>
拖动左边滑块完成上方拼图