区块链教程Fabric1.0源代码分析Ledger historydb历史数据库

1、historydb概述

historydb,用于存储所有块读写集中写集的内容。
代码分布在core/ledger/kvledger/history/historydb目录下,目录结构如下:

  • historydb.go,定义核心接口HistoryDBProvider和HistoryDB。
  • histmgr_helper.go,historydb工具函数。
  • historyleveldb目录,historydb基于leveldb的实现。
    ???? historyleveldb.go,HistoryDBProvider和HistoryDB接口实现,即historyleveldb.HistoryDBProvider和historyleveldb.historyDB结构体及方法。
    ????
    historyleveldb_query_executer.go,定义LevelHistoryDBQueryExecutor和historyScanner结构体及方法。

2、核心接口定义

HistoryDBProvider接口定义:

type HistoryDBProvider interface {
????GetDBHandle(id string) (HistoryDB, error) //获取HistoryDB
????Close() //关闭所有HistoryDB
}
//代码在core/ledger/kvledger/history/historydb/historydb.go

HistoryDB接口定义:

type HistoryDB interface {
????//构造 LevelHistoryDBQueryExecutor
????NewHistoryQueryExecutor(blockStore blkstorage.BlockStore) (ledger.HistoryQueryExecutor, error)
????//提交Block入historyDB
????Commit(block *common.Block) error
????//获取savePointKey,即version.Height
????GetLastSavepoint() (*version.Height, error)
????//是否应该恢复,比较lastAvailableBlock和Savepoint
????ShouldRecover(lastAvailableBlock uint64) (bool, uint64, error)
????//提交丢失的块
????CommitLostBlock(block *common.Block) error
}
//代码在core/ledger/kvledger/history/historydb/historydb.go

补充ledger.HistoryQueryExecutor接口定义:执行历史记录查询。

type HistoryQueryExecutor interface {
????GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) //按key查历史记录
}
//代码在core/ledger/ledger_interface.go

3、historydb工具函数

//构造复合HistoryKey,ns 0x00 key 0x00 blocknum trannum
func ConstructCompositeHistoryKey(ns string, key string, blocknum uint64, trannum uint64) []byte
//构造部分复合HistoryKey,ns 0x00 key 0x00 0xff
func ConstructPartialCompositeHistoryKey(ns string, key string, endkey bool) []byte
//按分隔符separator,分割bytesToSplit
func SplitCompositeHistoryKey(bytesToSplit []byte, separator []byte) ([]byte, []byte)
//代码在core/ledger/kvledger/history/historydb/histmgr_helper.go

4、HistoryDB接口实现

HistoryDB接口实现,即historyleveldb.historyDB结构体及方法。historyDB结构体定义如下:

type historyDB struct {
????db     *leveldbhelper.DBHandle //leveldb
????dbName string //dbName
}
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go

涉及方法如下:

//构造historyDB
func newHistoryDB(db *leveldbhelper.DBHandle, dbName string) *historyDB
//do nothing
func (historyDB *historyDB) Open() error
//do nothing
func (historyDB *historyDB) Close()
//提交Block入historyDB,将读写集中写集入库,并更新savePointKey
func (historyDB *historyDB) Commit(block *common.Block) error
//构造 LevelHistoryDBQueryExecutor
func (historyDB *historyDB) NewHistoryQueryExecutor(blockStore blkstorage.BlockStore) (ledger.HistoryQueryExecutor, error)
获取savePointKey,即version.Height
func (historyDB *historyDB) GetLastSavepoint() (*version.Height, error)
//是否应该恢复,比较lastAvailableBlock和Savepoint
func (historyDB *historyDB) ShouldRecover(lastAvailableBlock uint64) (bool, uint64, error)
//提交丢失的块,即调用historyDB.Commit(block)
func (historyDB *historyDB) CommitLostBlock(block *common.Block) error
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go

func (historyDB historyDB) Commit(block common.Block) error代码如下:

blockNo := block.Header.Number //区块编号
var tranNo uint64 //交易编号,初始化值为0
dbBatch := leveldbhelper.NewUpdateBatch() //leveldb批量更新

//交易验证代码,type TxValidationFlags []uint8
//交易筛选器
txsFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
if len(txsFilter) == 0 {
????txsFilter = util.NewTxValidationFlags(len(block.Data.Data))
????block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
}
for _, envBytes := range block.Data.Data {
????if txsFilter.IsInvalid(int(tranNo)) { //检查指定的交易是否有效
????????tranNo++
????????continue
????}
????//[]byte反序列化为Envelope
????env, err := putils.GetEnvelopeFromBlock(envBytes)
????payload, err := putils.GetPayload(env) //e.Payload反序列化为Payload
????//[]byte反序列化为ChannelHeader
????chdr, err := putils.UnmarshalChannelHeader(payload.Header.ChannelHeader)

????if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION { //背书交易,type HeaderType int32
????????respPayload, err := putils.GetActionFromEnvelope(envBytes) //获取ChaincodeAction
????????txRWSet := &rwsetutil.TxRwSet{}
????????err = txRWSet.FromProtoBytes(respPayload.Results) //[]byte反序列化后构造NsRwSet,加入txRWSet.NsRwSets
????????for _, nsRWSet := range txRWSet.NsRwSets {
????????????ns := nsRWSet.NameSpace
????????????for _, kvWrite := range nsRWSet.KvRwSet.Writes {
????????????????writeKey := kvWrite.Key
????????????????//txRWSet中写集入库
????????????????compositeHistoryKey := historydb.ConstructCompositeHistoryKey(ns, writeKey, blockNo, tranNo)
????????????????dbBatch.Put(compositeHistoryKey, emptyValue)
????????????}
????????}
????} else {
????????logger.Debugf("Skipping transaction [%d] since it is not an endorsement transaction\n", tranNo)
????}
????tranNo++
}

height := version.NewHeight(blockNo, tranNo)
dbBatch.Put(savePointKey, height.ToBytes())
err := historyDB.db.WriteBatch(dbBatch, true)
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go

Tx(Transaction 交易)相关更详细内容,参考:Fabric 1.0源代码笔记 之 Tx(Transaction 交易)

5、HistoryDBProvider接口实现

HistoryDBProvider接口实现,即historyleveldb.HistoryDBProvider结构体和方法。

type HistoryDBProvider struct {
????dbProvider *leveldbhelper.Provider
}

//构造HistoryDBProvider
func NewHistoryDBProvider() *HistoryDBProvider
//获取HistoryDB
func (provider *HistoryDBProvider) GetDBHandle(dbName string) (historydb.HistoryDB, error)
//关闭所有HistoryDB句柄,调取provider.dbProvider.Close()
func (provider *HistoryDBProvider) Close()
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go

6、LevelHistoryDBQueryExecutor和historyScanner结构体及方法

LevelHistoryDBQueryExecutor结构体及方法:实现ledger.HistoryQueryExecutor接口。

type LevelHistoryDBQueryExecutor struct {
????historyDB  *historyDB
????blockStore blkstorage.BlockStore //用于传递给historyScanner
}
//按key查historyDB,调用q.historyDB.db.GetIterator(compositeStartKey, compositeEndKey)
func (q *LevelHistoryDBQueryExecutor) GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error)
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go

historyScanner结构体及方法:实现ledger.ResultsIterator接口。

type historyScanner struct {
????compositePartialKey []byte //ns 0x00 key 0x00
????namespace           string
????key                 string
????dbItr               iterator.Iterator //leveldb迭代器
????blockStore          blkstorage.BlockStore
}

//构造historyScanner
func newHistoryScanner(compositePartialKey []byte, namespace string, key string, dbItr iterator.Iterator, blockStore blkstorage.BlockStore) *historyScanner
//按迭代器中key取blockNum和tranNum,再按blockNum和tranNum从blockStore中取Envelope,然后从Envelope的txRWSet.NsRwSets中按key查找并构造queryresult.KeyModification
func (scanner *historyScanner) Next() (commonledger.QueryResult, error)
func (scanner *historyScanner) Close() //scanner.dbItr.Release()
从Envelope的txRWSet.NsRwSets中按key查找并构造queryresult.KeyModification
func getKeyModificationFromTran(tranEnvelope *common.Envelope, namespace string, key string) (commonledger.QueryResult, error)
//代码在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go

补充queryresult.KeyModification:

type KeyModification struct {
????TxId      string //交易ID,ChannelHeader.TxId
????Value     []byte //读写集中Value,KVWrite.Value
????Timestamp *google_protobuf.Timestamp //ChannelHeader.Timestamp
????IsDelete  bool //KVWrite.IsDelete
}
//代码在protos/ledger/queryresult/kv_query_result.pb.go

原文地址:http://blog.51cto.com/14041296/2311757

时间: 2024-10-28 20:28:50

区块链教程Fabric1.0源代码分析Ledger historydb历史数据库的相关文章

区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令二

区块链教程Fabric1.0源代码分析Peer peer根命令入口及加载子命令二.flogging,即:fabric logging,为Fabric基于第三方包go-logging封装的日志包,go-logging使用方法参考:github.com/op/go-logging如下代码为flogging包的初始化函数: func init() { ????logger = logging.MustGetLogger(pkgLogID) //创建仅在flogging包内代码使用的logging.Lo

兄弟连区块链教程Fabric1.0源代码分析ledgerID数据

1.idStore概述 Fabric支持创建多个Ledger,不同Ledger以ledgerID区分. 多个ledgerID及其创世区块存储在idStore数据库中,idStore数据库基于leveldb实现. idStore默认使用路径:/var/hyperledger/production/ledgersData/ledgerProvider/. idStore库中特殊key "underConstructionLedgerKey",用于标志最新在建的ledgerID,ledger

区块链教程以太源码分析accounts账户管理分析

区块链教程以太源码分析accounts账户管理分析. 数据结构分析 ETH的账户管理定义在accounts/manager.go中,其数据结构为: // Manager is an overarching account manager that can communicate with various // backends for signing transactions. type Manager struct { backends map[reflect.Type][]Backend /

区块链教程以太源码分析accounts包简介

accounts包实现了eth客户端的钱包和账户管理.账号的数据结构:typeAccount struct { Address common.Address json:"address" // Ethereum account addressderived from the key URLURL json:"url" // Optional resource locator within a backend }钱包interface,是指包含了一个或多个账户的软件钱

兄弟连区块链教程open-ethereum-pool矿池源码分析unlocker模块

兄弟连区块链教程open-ethereum-pool以太坊矿池源码分析unlocker模块open-ethereum-pool以太坊矿池-unlocker模块 unlocker模块配置 json"unlocker": {????"enabled": false,????"poolFee": 1.0,????"poolFeeAddress": "",????"donate": true,?

区块链教程open-ethereum-pool矿池源码分析main入口

兄弟连区块链教程open-ethereum-pool矿池源码分析main入口,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁.回归理性,表面上看相关人才需求与身价似乎正在回落.但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上. open-ethereum-pool以太坊矿池-main入口 命令行启动 ./build/bin/open-ethereum-pool config.json config.json配置文件 { ????"threads": 2,

区块链教程btcpool矿池源码分析StratumServer模块解析

兄弟连区块链教程btcpool矿池源码分析StratumServer模块解析 核心机制总结 接收的job延迟超过60秒将丢弃 如果job中prevHash与本地job中prevHash不同,即为已产生新块,job中isClean状态将置为true????* true即要求矿机立即切换job 三种情况下将向矿机下发新job:???? 收到新高度的job???? 过去一个job为新高度且为空块job,且最新job为非空块job????* 达到预定的时间间隔30秒 最近一次下发job的时间将写入文件(

区块链教程以太坊源码分析core-state-process源码分析(二)

兄弟连区块链教程以太坊源码分析core-state-process源码分析(二):关于g0的计算,在黄皮书上由详细的介绍和黄皮书有一定出入的部分在于if contractCreation && homestead {igas.SetUint64(params.TxGasContractCreation) 这是因为 Gtxcreate+Gtransaction = TxGasContractCreation func IntrinsicGas(data []byte, contractCre

{区块链教程}以太坊源码分析fast sync算法二

{区块链教程}以太坊源码分析fast sync算法二:上面的表格应该这样解释:如果我们每隔K个区块头验证一次区块头,在N个区块头之后,伪造的概率小于***者产生SHA3冲突的概率.这也意味着,如果确实发现了伪造,那么最后的N个头部应该被丢弃,因为不够安全.可以从上表中选择任何{N,K}对,为了选择一个看起来好看点的数字,我们选择N = 2048,K = 100.后续可能会根据网络带宽/延迟影响以及可能在一些CPU性能比较受限的设备上运行的情况来进行调整. Using this caveat ho