本文共 7737 字,大约阅读时间需要 25 分钟。
区块链教程Fabric1.0源代码分析Tx RWSet(读写集),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。
在背书节点模拟Transaction期间,为交易准备了一个读写集合。
Read Set包含模拟Transaction读取的Key和版本的列表,Write Set包含Key、写入的新值、以及删除标记(是否删除Key)。RWSet相关代码分布在protos/ledger/rwset、core/ledger/kvledger/txmgmt/rwsetutil目录下。目录结构如下:
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
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
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
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
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