Fabric 1.0原始碼分析(18) Ledger(賬本)
# Fabric 1.0原始碼筆記 之 Ledger(賬本)
## 1、Ledger概述
Ledger,即賬本資料庫。Fabric賬本中有四種資料庫,idStore(ledgerID資料庫)、blkstorage(block檔案儲存)、statedb(狀態資料庫)、historydb(歷史資料庫)。
其中idStore、historydb使用leveldb實現,statedb可選擇使用leveldb或couchDB。而blkstorage中index部分使用leveldb實現,實際區塊鏈資料儲存使用檔案實現。
* idStore,預設目錄/var/hyperledger/production/ledgersData/ledgerProvider,更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #idStore(ledgerID資料庫)](idstore.md)
* blkstorage,預設目錄/var/hyperledger/production/ledgersData/chains,更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #blkstorage(block檔案儲存)](blkstorage.md)
* statedb,預設目錄/var/hyperledger/production/ledgersData/stateLeveldb,更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #statedb(狀態資料庫)](statedb.md)
* historydb,預設目錄/var/hyperledger/production/ledgersData/historyLeveldb,更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #historydb(歷史資料庫)](historydb.md)
## 2、Ledger程式碼目錄結構
Ledger相關程式碼分佈在common/ledger、core/ledger和protos/ledger目錄下。目錄結構如下:
* common/ledger目錄
* ledger_interface.go,定義了通用介面Ledger、ResultsIterator、以及QueryResult和PrunePolicy(暫時均為空介面)。
* blkstorage目錄,**blkstorage相關介面及實現**。
* util/leveldbhelper目錄,LevelDB資料庫操作的封裝。
* core/ledger目錄
* ledger_interface.go,定義了核心介面PeerLedgerProvider、PeerLedger、ValidatedLedger(暫時未定義)、QueryExecutor、HistoryQueryExecutor和TxSimulator。
* kvledger目錄,目前PeerLedgerProvider、PeerLedger等介面僅有一種實現即:kvledger。
* kv_ledger_provider.go,實現PeerLedgerProvider介面,即Provider結構體及其方法,以及**idStore結構體及方法**。
* kv_ledger.go,實現PeerLedger介面,即kvLedger結構體及方法。
* txmgmt目錄,交易管理。
* statedb目錄,**statedb相關介面及實現**。
* history/historydb目錄,**historydb相關介面及實現**。
* ledgermgmt/ledger_mgmt.go,Ledger管理相關函式實現。
* ledgerconfig/ledger_config.go,Ledger配置相關函式實現。
* util目錄,Ledger工具相關函式實現。
## 3、核心介面定義
PeerLedgerProvider介面定義:提供PeerLedger例項handle。
```go
type PeerLedgerProvider interface {
Create(genesisBlock *common.Block) (PeerLedger, error) //用給定的創世紀塊建立Ledger
Open(ledgerID string) (PeerLedger, error) //開啟已建立的Ledger
Exists(ledgerID string) (bool, error) //按ledgerID查Ledger是否存在
List() ([]string, error) //列出現有的ledgerID
Close() //關閉 PeerLedgerProvider
}
//程式碼在core/ledger/ledger_interface.go
```
PeerLedger介面定義:
PeerLedger和OrdererLedger的不同之處在於PeerLedger本地維護位掩碼,用於區分有效交易和無效交易。
```go
type PeerLedger interface {
commonledger.Ledger //嵌入common/ledger/Ledger介面
GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) //按txID獲取交易
GetBlockByHash(blockHash []byte) (*common.Block, error) //按blockHash獲取Block
GetBlockByTxID(txID string) (*common.Block, error) //按txID獲取包含交易的Block
GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) //獲取交易記錄驗證的原因程式碼
NewTxSimulator() (TxSimulator, error) //建立交易模擬器,客戶端可以建立多個"TxSimulator"並行執行
NewQueryExecutor() (QueryExecutor, error) //建立查詢執行器,客戶端可以建立多個'QueryExecutor'並行執行
NewHistoryQueryExecutor() (HistoryQueryExecutor, error) //建立歷史記錄查詢執行器,客戶端可以建立多個'HistoryQueryExecutor'並行執行
Prune(policy commonledger.PrunePolicy) error //裁剪滿足給定策略的塊或交易
}
//程式碼在core/ledger/ledger_interface.go
```
補充PeerLedger介面嵌入的commonledger.Ledger介面定義如下:
```go
type Ledger interface {
GetBlockchainInfo() (*common.BlockchainInfo, error) //獲取blockchain基本資訊
GetBlockByNumber(blockNumber uint64) (*common.Block, error) //按給定高度獲取Block,給定math.MaxUint64將獲取最新Block
GetBlocksIterator(startBlockNumber uint64) (ResultsIterator, error) //獲取從startBlockNumber開始的迭代器(包含startBlockNumber),迭代器是阻塞迭代,直到ledger中下一個block可用
Close() //關閉ledger
Commit(block *common.Block) error //提交新block
}
//程式碼在common/ledger/ledger_interface.go
```
ValidatedLedger介面暫未定義方法,從PeerLedger篩選出無效交易後,ValidatedLedger表示最終賬本。暫時忽略。
QueryExecutor介面定義:用於執行查詢。
其中Get*方法用於支援KV-based資料模型,ExecuteQuery方法用於支援更豐富的資料和查詢支援。
```go
type QueryExecutor interface {
GetState(namespace string, key string) ([]byte, error) //按namespace和key獲取value,對於chaincode,chaincodeId即為namespace
GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) //一次呼叫獲取多個key的值
//獲取迭代器,返回包括startKey、但不包括endKeyd的之間所有值
GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)
ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) //執行查詢並返回迭代器,僅用於查詢statedb
Done() //釋放QueryExecutor佔用的資源
}
//程式碼在core/ledger/ledger_interface.go
```
HistoryQueryExecutor介面定義:執行歷史記錄查詢。
```go
type HistoryQueryExecutor interface {
GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) //按key查歷史記錄
}
//程式碼在core/ledger/ledger_interface.go
```
TxSimulator介面定義:在"儘可能"最新狀態的一致快照上模擬交易。
其中Set*方法用於支援KV-based資料模型,ExecuteUpdate方法用於支援更豐富的資料和查詢支援。
```go
type TxSimulator interface {
QueryExecutor //嵌入QueryExecutor介面
SetState(namespace string, key string, value []byte) error //按namespace和key寫入value
DeleteState(namespace string, key string) error //按namespace和key刪除
SetStateMultipleKeys(namespace string, kvs map[string][]byte) error //一次呼叫設定多個key的值
ExecuteUpdate(query string) error //ExecuteUpdate用於支援豐富的資料模型
GetTxSimulationResults() ([]byte, error) //獲取模擬交易的結果
}
//程式碼在core/ledger/ledger_interface.go
```
## 4、kvledger.kvLedger結構體及方法(實現PeerLedger介面)
kvLedger結構體定義:
```go
type kvLedger struct {
ledgerID string //ledgerID
blockStore blkstorage.BlockStore //blkstorage
txtmgmt txmgr.TxMgr //txmgr
historyDB historydb.HistoryDB //historyDB
}
//程式碼在core/ledger/kvledger/kv_ledger.go
```
涉及方法如下:
```go
//構造kvLedger
func newKVLedger(ledgerID string, blockStore blkstorage.BlockStore,versionedDB statedb.VersionedDB, historyDB historydb.HistoryDB) (*kvLedger, error)
//按最後一個有效塊恢復statedb和historydb
func (l *kvLedger) recoverDBs() error
//檢索指定範圍內的塊, 並將寫入集提交給狀態 db 或歷史資料庫, 或同時
func (l *kvLedger) recommitLostBlocks(firstBlockNum uint64, lastBlockNum uint64, recoverables ...recoverable) error
//按交易ID獲取交易
func (l *kvLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error)
//獲取BlockchainInfo
func (l *kvLedger) GetBlockchainInfo() (*common.BlockchainInfo, error)
//按區塊編號獲取塊
func (l *kvLedger) GetBlockByNumber(blockNumber uint64) (*common.Block, error)
//按起始塊獲取塊迭代器
func (l *kvLedger) GetBlocksIterator(startBlockNumber uint64) (commonledger.ResultsIterator, error)
//獲取塊雜湊
func (l *kvLedger) GetBlockByHash(blockHash []byte) (*common.Block, error)
//按交易ID獲取塊
func (l *kvLedger) GetBlockByTxID(txID string) (*common.Block, error)
//按交易ID獲取交易驗證程式碼
func (l *kvLedger) GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)
func (l *kvLedger) Prune(policy commonledger.PrunePolicy) error //暫未實現
//建立交易模擬器
func (l *kvLedger) NewTxSimulator() (ledger.TxSimulator, error)
//建立查詢執行器
func (l *kvLedger) NewQueryExecutor() (ledger.QueryExecutor, error)
func (l *kvLedger) NewHistoryQueryExecutor() (ledger.HistoryQueryExecutor, error)
//提交有效塊,塊寫入blkstorage,塊中寫集加入批處理並更新statedb,寫集本身入historyDB
func (l *kvLedger) Commit(block *common.Block) error
//建立歷史記錄查詢執行器
func (l *kvLedger) Close() //關閉
//程式碼在core/ledger/kvledger/kv_ledger.go
```
## 5、kvledger.Provider結構體及方法(實現PeerLedgerProvider介面)
Provider結構體定義:
```go
type Provider struct {
idStore *idStore //idStore
blockStoreProvider blkstorage.BlockStoreProvider //blkstorage
vdbProvider statedb.VersionedDBProvider //statedb
historydbProvider historydb.HistoryDBProvider //historydb
}
//程式碼在core/ledger/kvledger/kv_ledger_provider.go
```
* idStore更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #idStore(ledgerID資料庫)](idstore.md)
* blkstorage更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #blkstorage(block檔案儲存)](blkstorage.md)
* statedb更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #statedb(狀態資料庫)](statedb.md)
* historydb更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Ledger #historydb(歷史資料庫)](historydb.md)
涉及方法如下:
```go
//分別構造idStore、blockStoreProvider、vdbProvider和historydbProvider,並用於構造Provider,並恢復之前未完成建立的Ledger
func NewProvider() (ledger.PeerLedgerProvider, error)
//按創世區塊建立並開啟Ledger,提交創世區塊(塊入blkstorage,寫集更新statedb,寫集本身寫入historydb),建立ledgerID
func (provider *Provider) Create(genesisBlock *common.Block) (ledger.PeerLedger, error)
//呼叫provider.openInternal(ledgerID),開啟Ledger
func (provider *Provider) Open(ledgerID string) (ledger.PeerLedger, error)
//按ledgerID開啟blkstorage、statedb和historydb,並建立kvledger
func (provider *Provider) openInternal(ledgerID string) (ledger.PeerLedger, error)
//ledgerID是否存在
func (provider *Provider) Exists(ledgerID string) (bool, error)
//獲取ledgerID列表,調取provider.idStore.getAllLedgerIds()
func (provider *Provider) List() ([]string, error)
//關閉idStore、blkstorage、statedb、historydb
func (provider *Provider) Close()
//檢查是否有之前未完成建立的Ledger,並恢復
func (provider *Provider) recoverUnderConstructionLedger()
func (provider *Provider) runCleanup(ledgerID string) error //暫時沒有實現
func panicOnErr(err error, mgsFormat string, args ...interface{}) //panicOnErr
//程式碼在core/ledger/kvledger/kv_ledger_provider.go
```
## 6、ledgermgmt(Ledger管理函式)
全域性變數:
```go
var openedLedgers map[string]ledger.PeerLedger //Ledger map,Key為ChainID(即ChannelId或LedgerId)
var ledgerProvider ledger.PeerLedgerProvider //LedgerProvider
//程式碼在core/ledger/ledgermgmt/ledger_mgmt.go
```
Ledger管理函式:
```go
func Initialize() //Ledger初始化,呼叫initialize(),once.Do確保僅呼叫一次
func initialize() //Ledger初始化,包括初始化openedLedgers及ledgerProvider
//呼叫ledgerProvider.Create(genesisBlock)建立Ledger,並加入openedLedgers
func CreateLedger(genesisBlock *common.Block) (ledger.PeerLedger, error)
//按id取Ledger,並呼叫ledgerProvider.Open(id)開啟Ledger
func OpenLedger(id string) (ledger.PeerLedger, error)
//獲取ledgerID列表,調取ledgerProvider.List()
func GetLedgerIDs() ([]string, error)
//關閉ledgerProvider
func Close()
//構造closableLedger
func wrapLedger(id string, l ledger.PeerLedger) ledger.PeerLedger
//程式碼在core/ledger/ledgermgmt/ledger_mgmt.go
```
closableLedger:
```go
type closableLedger struct {
id string
ledger.PeerLedger
}
func (l *closableLedger) Close() //調取l.closeWithoutLock()
func (l *closableLedger) closeWithoutLock() //delete(openedLedgers, l.id)
//程式碼在core/ledger/ledgermgmt/ledger_mgmt.go
```
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)原始碼
- Fabric 1.0原始碼分析(20) Ledger #idStore(ledgerID資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(19) Ledger #statedb(狀態資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(21)Ledger #historydb(歷史資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(25) Orderer原始碼
- Fabric 1.0原始碼分析(31) Peer原始碼
- Fabric 1.0原始碼分析(3)Chaincode(鏈碼)原始碼AI
- Fabric 1.0原始碼分析(40) Proposal(提案)原始碼
- Fabric 1.0原始碼分析(14) flogging(Fabric日誌系統)原始碼
- Fabric 1.0原始碼分析(43) Tx(Transaction 交易)原始碼
- Fabric 1.0原始碼分析(47)Fabric 1.0.4 go程式碼量統計原始碼Go
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Fabric 1.0原始碼分析(13)events(事件服務)原始碼事件
- Fabric 1.0原始碼分析(39) policy(背書策略)原始碼
- Fabric 1.0原始碼分析(45)gRPC(Fabric中註冊的gRPC Service)原始碼RPC
- Fabric 1.0原始碼分析(10)consenter(共識外掛)原始碼
- Fabric 1.0原始碼分析(15)gossip(流言演算法)原始碼Go演算法
- Fabric 1.0原始碼分析(23)LevelDB(KV資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(44)Tx #RWSet(讀寫集)原始碼
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Fabric 1.0原始碼分析(6)configtx(配置交易) #ChannelConfig(通道配置)原始碼
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)原始碼ASTServer服務端
- Fabric 1.0原始碼分析(35)Peer #EndorserServer(Endorser服務端)原始碼Server服務端
- Fabric 1.0原始碼分析(36) Peer #EndorserClient(Endorser客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(37) Peer #DeliverClient(Deliver客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(38) Peer #BroadcastClient(Broadcast客戶端)原始碼ASTclient客戶端
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(7)configtx(配置交易) #configtxgen(生成通道配置)原始碼
- Fabric 1.0原始碼分析(9)configtx(配置交易)體系介紹原始碼
- Fabric 1.0原始碼分析(27) Orderer #configupdate(處理通道配置更新)原始碼
- Fabric 1.0原始碼分析(32) Peer #peer node start命令實現原始碼
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform
- Fabric 1.0原始碼分析(28) Orderer #localconfig(Orderer配置檔案定義)原始碼
- Fabric 1.0原始碼分析(11)consenter(共識外掛) #filter(過濾器)原始碼Filter過濾器