兄弟连区块链教程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
相关文章
|
7月前
|
存储 供应链 监控
区块链技术在供应链管理中的应用与前景分析
随着信息化时代的到来,供应链管理面临着越来越多的挑战和机遇。本文主要探讨了区块链技术在供应链管理中的应用,以及未来的发展前景。通过对区块链技术的特点和优势进行分析,结合实际案例和趋势展望,展示了区块链技术在提升供应链透明度、效率和安全性方面的潜力,以及未来发展的可能方向。
|
7月前
|
安全 区块链
区块链积分商城系统开发详细指南//需求功能/指南教程/源码流程
Developing a blockchain points mall system involves multiple aspects such as blockchain technology, smart contracts, front-end development, and business logic design. The following is the general process for developing a blockchain points mall system
|
7月前
|
存储 算法 API
面向企业的区块链教程(一)(2)
面向企业的区块链教程(一)
107 6
|
4月前
|
安全 区块链
Massa Layer 1区块链 POS 安全性分析
Massa Labs 回应 Certik 的挑战,通过严格的数学分析证明了其权益证明系统的安全性,抵抗了潜在攻击者试图操纵随机抽签的企图。
60 0
Massa Layer 1区块链 POS 安全性分析
|
7月前
|
存储 供应链 安全
基于区块链技术的智能合约安全性分析
【5月更文挑战第31天】本文深入探讨了区块链技术中智能合约的安全性问题,通过分析现有智能合约的安全漏洞和攻击手段,提出了一系列增强智能合约安全性的策略。文章首先介绍了区块链和智能合约的基本概念,随后详细讨论了智能合约面临的安全挑战,包括代码漏洞、重入攻击等问题,并对比分析了不同平台下智能合约的安全性差异。最后,文章提出了一系列提高智能合约安全性的建议,旨在为区块链应用的健康发展提供参考。
|
6月前
|
存储 安全 区块链
元宇宙与区块链技术的关系可以从多个角度进行阐述。以下是对这两者之间关系的详细分析
**元宇宙:虚拟世界融合现实元素,强调交互与沉浸;区块链:去中心化、安全的分布式账本。两者结合,区块链确保元宇宙中虚拟资产安全、支付高效、身份验证私密、治理透明,支撑其经济体系与用户信任,驱动未来发展。**
|
7月前
|
存储 算法 安全
区块链系统开发技术规则分析
区块链核心技术包括:1) 哈希算法,利用单向函数将任意数据转化为固定长度代码,确保安全验证;2) 非对称加密,使用公钥和私钥一对进行加密解密,保证信息安全;3) 共识机制,如PoW、PoS、DPoS等,实现快速交易验证和确认;4) 智能合约,自动执行的可信代码,一旦编写即不可更改,用于自动化交易;5) 分布式存储,将数据分散存储在网络各处,涵盖结构化、非结构化和半结构化数据。
|
6月前
|
区块链
近期区块链市场趋势分析
**区块链市场趋势摘要:** - 跨链技术成熟,提升互操作性,助力区块链网络融合。 - DeFi持续繁荣,智能合约与AMM创新活跃,市场竞争驱动市场壮大。 - NFT市场多样化,拓展至游戏、音乐等领域,实用性增强。 - 区块链寻求绿色转型,通过PoS共识与绿色能源减少能耗。 - 技术模块化、可组合性提升,降低成本,增强系统灵活性。 这些趋势展现区块链潜力,带来机遇与挑战,促进行业创新。
|
7月前
|
供应链 区块链 数据安全/隐私保护
探索区块链技术在金融领域的应用与前景分析
本文将深入探讨区块链技术在金融领域的具体应用场景,分析其优势与挑战,并展望未来发展趋势。通过案例分析和技术解析,揭示区块链技术在金融行业中的革新意义及前景。
1021 15
|
7月前
|
安全 区块链
区块链游戏系统开发步骤需求丨功能逻辑丨规则玩法丨指南教程丨源码详细
Developing blockchain game systems has been a highly anticipated field in recent years. By combining blockchain technology and game mechanics, players can enjoy a brand new gaming experience and higher game credibility.
下一篇
无影云桌面