天天看點

區塊鍊教程Fabric1.0源代碼分析Ledger statedb(狀态資料庫)-兄弟連區塊鍊Fabric 1.0源代碼筆記 之 Ledger #statedb(狀态資料庫)

Fabric 1.0源代碼筆記 之 Ledger #statedb(狀态資料庫)

1、statedb概述

statedb,或VersionedDB,即狀态資料庫,存儲了交易(transaction)日志中所有鍵的最新值,也稱世界狀态(world state)。

可選擇基于leveldb或cauchdb實作。

statedb,代碼分布在core/ledger/kvledger/txmgmt/statedb目錄下,目錄結構如下:

  • statedb.go,定義了核心接口VersionedDBProvider、VersionedDB、ResultsIterator和QueryResult,以及UpdateBatch和nsIterator結構體及方法。
  • util.go,包括工具函數EncodeValue和DecodeValue的實作。
  • stateleveldb目錄,VersionedDBProvider和VersionedDB接口的leveldb版本實作,即stateleveldb.VersionedDBProvider和stateleveldb.versionedDB結構體及方法。
  • statecouchdb目錄,VersionedDBProvider和VersionedDB接口的couchdb版本實作,即statecouchdb.VersionedDBProvider和statecouchdb.VersionedDB結構體及方法。

2、核心接口定義

VersionedDBProvider接口定義:

type VersionedDBProvider interface {
    GetDBHandle(id string) (VersionedDB, error) //擷取VersionedDB句柄
    Close() //關閉所有 VersionedDB 執行個體
}
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

VersionedDB接口定義:

type VersionedDB interface {
    //擷取給定命名空間和鍵的值
    GetState(namespace string, key string) (*VersionedValue, error)
    //在單個調用中擷取多個鍵的值
    GetStateMultipleKeys(namespace string, keys []string) ([]*VersionedValue, error)
    //傳回一個疊代器, 其中包含給定鍵範圍之間的所有鍵值(包括startKey,不包括endKey)
    GetStateRangeScanIterator(namespace string, startKey string, endKey string) (ResultsIterator, error)
    //執行給定的查詢并傳回疊代器
    ExecuteQuery(namespace, query string) (ResultsIterator, error)
    //批處理應用
    ApplyUpdates(batch *UpdateBatch, height *version.Height) error
    //傳回statedb一緻的最高事務的高度
    GetLatestSavePoint() (*version.Height, error)
    //測試資料庫是否支援這個key(leveldb支援任何位元組, 而couchdb隻支援utf-8字元串)
    ValidateKey(key string) error
    //打開db
    Open() error
    //關閉db
    Close()
}
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

ResultsIterator和QueryResult接口定義:

type ResultsIterator interface {
    Next() (QueryResult, error)
    Close()
}

type QueryResult interface{}
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

補充CompositeKey、VersionedValue和VersionedKV結構體:

type CompositeKey struct {
    Namespace string //命名空間
    Key       string //Key
}

type VersionedValue struct {
    Value   []byte //Value
    Version *version.Height //版本
}

type VersionedKV struct {
    CompositeKey //嵌入CompositeKey
    VersionedValue //嵌入VersionedValue
}
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

nsUpdates結構體及方法:

type nsUpdates struct {
    m map[string]*VersionedValue //string為Key
}

func newNsUpdates() *nsUpdates//構造nsUpdates
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

UpdateBatch結構體及方法:

type UpdateBatch struct {
    updates map[string]*nsUpdates //string為Namespace
}

//構造UpdateBatch
func NewUpdateBatch() *UpdateBatch
//按namespace和key擷取Value
func (batch *UpdateBatch) Get(ns string, key string) *VersionedValue
//按namespace和key添加Value
func (batch *UpdateBatch) Put(ns string, key string, value []byte, version *version.Height)
//按namespace和key删除Value,即置為nil
func (batch *UpdateBatch) Delete(ns string, key string, version *version.Height)
//按namespace和key查找是否存在
func (batch *UpdateBatch) Exists(ns string, key string) bool
//擷取更新的namespace清單
func (batch *UpdateBatch) GetUpdatedNamespaces() []string
//按namespace擷取nsUpdates
func (batch *UpdateBatch) GetUpdates(ns string) map[string]*VersionedValue
//構造nsIterator
func (batch *UpdateBatch) GetRangeScanIterator(ns string, startKey string, endKey string) ResultsIterator
//按namespace擷取或建立nsUpdates
func (batch *UpdateBatch) getOrCreateNsUpdates(ns string) *nsUpdates
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

nsIterator結構體及方法:

type nsIterator struct {
    ns         string //namespace
    nsUpdates  *nsUpdates //batch.updates[ns]
    sortedKeys []string //nsUpdates.m中key排序
    nextIndex  int //startKey
    lastIndex  int //endKey
}

//構造nsIterator
func newNsIterator(ns string, startKey string, endKey string, batch *UpdateBatch) *nsIterator
func (itr *nsIterator) Next() (QueryResult, error) //按itr.nextIndex擷取VersionedKV
func (itr *nsIterator) Close() // do nothing
//代碼在core/ledger/kvledger/txmgmt/statedb/statedb.go           

3、statedb基于leveldb實作

3.1、VersionedDB接口實作

VersionedDB接口實作,即versionedDB結構體,定義如下:

type versionedDB struct {
    db     *leveldbhelper.DBHandle //leveldb
    dbName string //dbName
}
//代碼在core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go           

涉及方法如下:

//構造versionedDB
func newVersionedDB(db *leveldbhelper.DBHandle, dbName string) *versionedDB
func (vdb *versionedDB) Open() error // do nothing
func (vdb *versionedDB) Close() // do nothing
func (vdb *versionedDB) ValidateKey(key string) error // do nothing
//按namespace和key擷取Value
func (vdb *versionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error)
//在單個調用中擷取多個鍵的值
func (vdb *versionedDB) GetStateMultipleKeys(namespace string, keys []string) ([]*statedb.VersionedValue, error)
//傳回一個疊代器, 其中包含給定鍵範圍之間的所有鍵值(包括startKey,不包括endKey)
func (vdb *versionedDB) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (statedb.ResultsIterator, error)
//leveldb不支援ExecuteQuery方法
func (vdb *versionedDB) ExecuteQuery(namespace, query string) (statedb.ResultsIterator, error)
//批處理應用
func (vdb *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version.Height) error
//傳回statedb一緻的最高事務的高度
func (vdb *versionedDB) GetLatestSavePoint() (*version.Height, error)
//拼接ns和key,ns []byte{0x00} key
func constructCompositeKey(ns string, key string) []byte
//分割ns和key,分割符[]byte{0x00}
func splitCompositeKey(compositeKey []byte) (string, string)
//代碼在core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go           

func (vdb versionedDB) ApplyUpdates(batch statedb.UpdateBatch, height *version.Height) error代碼如下:

dbBatch := leveldbhelper.NewUpdateBatch()
namespaces := batch.GetUpdatedNamespaces() //擷取更新的namespace清單
for _, ns := range namespaces {
    updates := batch.GetUpdates(ns) //按namespace擷取nsUpdates
    for k, vv := range updates {
        compositeKey := constructCompositeKey(ns, k) //拼接ns和key
        if vv.Value == nil {
            dbBatch.Delete(compositeKey)
        } else {
            dbBatch.Put(compositeKey, statedb.EncodeValue(vv.Value, vv.Version))
        }
    }
}
//statedb一緻的最高事務的高度
dbBatch.Put(savePointKey, height.ToBytes()) //var savePointKey = []byte{0x00}
err := vdb.db.WriteBatch(dbBatch, true)
//代碼在core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go           

3.2、ResultsIterator接口實作

ResultsIterator接口實作,即kvScanner結構體及方法。

type kvScanner struct {
    namespace string
    dbItr     iterator.Iterator
}

//構造kvScanner
func newKVScanner(namespace string, dbItr iterator.Iterator) *kvScanner
//疊代擷取statedb.VersionedKV
func (scanner *kvScanner) Next() (statedb.QueryResult, error)
func (scanner *kvScanner) Close() //釋放疊代器
//代碼在core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go           

3.3、VersionedDBProvider接口實作

VersionedDBProvider接口實作,即VersionedDBProvider結構體及方法。

type VersionedDBProvider struct {
    dbProvider *leveldbhelper.Provider
}

func NewVersionedDBProvider() *VersionedDBProvider //構造VersionedDBProvider
//擷取statedb.VersionedDB
func (provider *VersionedDBProvider) GetDBHandle(dbName string) (statedb.VersionedDB, error)
func (provider *VersionedDBProvider) Close() //關閉statedb.VersionedDB
//代碼在core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go           

4、statedb基于cauchdb實作

暫略,待補充。