Blockchain tutorial Fabric1.0 source code analysis Ledger II

Posted by zwiebelspaetzle on Thu, 12 Dec 2019 16:39:15 +0100

Blockchain tutorial's Fabric1.0 source code analysis Ledger II.

Ledger of Fabric 1.0 source code Notes

Supplement the definition of commonledger.Ledger interface embedded in PeerLedger interface as follows:

type Ledger interface {
    GetBlockchainInfo() (*common.BlockchainInfo, error) //Get the basic information of blockchain
    GetBlockByNumber(blockNumber uint64) (*common.Block, error) //Get the Block according to the given height, and get the latest Block according to the given math.MaxUint64
    GetBlocksIterator(startBlockNumber uint64) (ResultsIterator, error) //Gets the iterator (including startBlockNumber) starting from startBlockNumber, which is a blocking iteration until the next block in ledger is available
    Close() //Close ledger
    Commit(block *common.Block) error //Submit new block
}
//The code is in common/ledger/ledger_interface.go

The ValidatedLedger interface has no method defined yet. After filtering out invalid transactions from PeerLedger, ValidatedLedger represents the final ledger. Ignored for now.

Queryexecutior interface definition: used to execute queries.
The Get * method is used to support kV based data model, and the ExecuteQuery method is used to support richer data and query support.

type QueryExecutor interface {
    GetState(namespace string, key string) ([]byte, error) //Press namespace and key to get value. For chaincode, chaincode ID is namespace
    GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) //Get the value of multiple key s in one call
    //Gets the iterator and returns all values including startKey but excluding endKeyd
    GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)
    ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error) //Execute the query and return the iterator for querying statedb only
    Done() //Release the resources occupied by queryexecutior
}
//The code is in core / ledger / ledger? Interface.go

Historyqueryexecutior interface definition: execute history query.

type HistoryQueryExecutor interface {
    GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) //Press key to check the history
}
//The code is in core / ledger / ledger? Interface.go

TxSimulator interface definition: simulate a transaction on a consistent snapshot of the latest status as far as possible.
Among them, Set * method is used to support kV based data model, and ExecuteUpdate method is used to support richer data and query support.

type TxSimulator interface {
    QueryExecutor //Embed queryexecutior interface
    SetState(namespace string, key string, value []byte) error //Write value by namespace and key
    DeleteState(namespace string, key string) error //Press namespace and key to delete
    SetStateMultipleKeys(namespace string, kvs map[string][]byte) error //Setting the value of multiple key s in one call
    ExecuteUpdate(query string) error //ExecuteUpdate is used to support rich data models
    GetTxSimulationResults() ([]byte, error) //Get results of simulated transactions
}
//The code is in core / ledger / ledger? Interface.go

4. kvledger.kvLedger structure and method (implement PeerLedger interface)

kvLedger structure definition:

type kvLedger struct {
    ledgerID   string //ledgerID
    blockStore blkstorage.BlockStore //blkstorage
    txtmgmt    txmgr.TxMgr //txmgr
    historyDB  historydb.HistoryDB //historyDB
}
//The code is in core/ledger/kvledger/kv_ledger.go

The methods involved are as follows:

//Construct kvLedger
func newKVLedger(ledgerID string, blockStore blkstorage.BlockStore,versionedDB statedb.VersionedDB, historyDB historydb.HistoryDB) (*kvLedger, error)
//Restore statedb and historydb by the last valid block
func (l *kvLedger) recoverDBs() error
//Retrieve the block in the specified range and submit the write set to the state db or history database, or both
func (l *kvLedger) recommitLostBlocks(firstBlockNum uint64, lastBlockNum uint64, recoverables ...recoverable) error
//Get transaction by transaction ID
func (l *kvLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error)
//Get BlockchainInfo
func (l *kvLedger) GetBlockchainInfo() (*common.BlockchainInfo, error)
//Get blocks by block number
func (l *kvLedger) GetBlockByNumber(blockNumber uint64) (*common.Block, error)
//Get block iterator by starting block
func (l *kvLedger) GetBlocksIterator(startBlockNumber uint64) (commonledger.ResultsIterator, error)
//Get block hash
func (l *kvLedger) GetBlockByHash(blockHash []byte) (*common.Block, error)
//Get block by transaction ID
func (l *kvLedger) GetBlockByTxID(txID string) (*common.Block, error)
//Get transaction verification code by transaction ID
func (l *kvLedger) GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)
func (l *kvLedger) Prune(policy commonledger.PrunePolicy) error //Not yet realized
//Create transaction simulator
func (l *kvLedger) NewTxSimulator() (ledger.TxSimulator, error)
//Create query executor
func (l *kvLedger) NewQueryExecutor() (ledger.QueryExecutor, error)
func (l *kvLedger) NewHistoryQueryExecutor() (ledger.HistoryQueryExecutor, error)
//Submit valid block, write block to blkstorage, add write set in block to batch and update statedb, write set itself to historyDB
func (l *kvLedger) Commit(block *common.Block) error
//Create history query executor
func (l *kvLedger) Close() //Close
//The code is in core/ledger/kvledger/kv_ledger.go

5. kvledger.Provider structure and method (implementation of PeerLedgerProvider interface)

Provider structure definition:

type Provider struct {
    idStore            *idStore //idStore
    blockStoreProvider blkstorage.BlockStoreProvider //blkstorage
    vdbProvider        statedb.VersionedDBProvider //statedb
    historydbProvider  historydb.HistoryDBProvider //historydb
}
//The code is in core / ledger / kvledger / kV? Ledger? Provider.go
  • For more details of idStore, please refer to ledger idStore (ledgerID database) of Fabric 1.0 source code notes
  • For more details on blkstorage, refer to: ledger blkstorage (block file storage) of Fabric 1.0 source code notes
  • For more details on statedb, refer to ledger (statedb) of Fabric 1.0 source code note
  • For more details of historydb, refer to ledger (historical database) of Fabric 1.0 source code notes

The methods involved are as follows:

//Construct idStore, blockStoreProvider, vdbProvider and historydbProvider respectively, and use them to construct Provider, and recover the previously created Ledger
func NewProvider() (ledger.PeerLedgerProvider, error)
//Create and open Ledger according to creation block, submit creation block (block into blkstorage, write set update statedb, write set itself into historydb), and create Ledger ID
func (provider *Provider) Create(genesisBlock *common.Block) (ledger.PeerLedger, error)
//Call provider.openinternal (Ledger ID) to open Ledger
func (provider *Provider) Open(ledgerID string) (ledger.PeerLedger, error)
//Press ledgerID to open blkstorage, statedb, and historydb, and create a kvledger
func (provider *Provider) openInternal(ledgerID string) (ledger.PeerLedger, error)
//Whether ledger ID exists
func (provider *Provider) Exists(ledgerID string) (bool, error)
//Get the list of ledgerID, call provider.idStore.getAllLedgerIds()
func (provider *Provider) List() ([]string, error)
//Close idStore, blkstorage, statedb and historydb
func (provider *Provider) Close()
//Check if there are any previously created ledgers, and restore
func (provider *Provider) recoverUnderConstructionLedger()
func (provider *Provider) runCleanup(ledgerID string) error //Not implemented yet
func panicOnErr(err error, mgsFormat string, args ...interface{}) //panicOnErr
//The code is in core / ledger / kvledger / kV? Ledger? Provider.go

6. Ledger mgmt (ledger management function)

Global variable:

var openedLedgers map[string]ledger.PeerLedger //Ledger map, Key is ChainID (i.e. ChannelId or LedgerId)
var ledgerProvider ledger.PeerLedgerProvider //LedgerProvider
//The code is in core / ledger / ledger MGMT / ledger_mgmt.go

Ledger management function:

func Initialize() //Ledger initialization, call initialize(), once.Do to make sure it is only called once
func initialize() //Ledger initialization, including initializing openedLedgers and ledgerProvider
//Call ledgerprovider.create (Genesis block) to create a Ledger and add openedLedgers
func CreateLedger(genesisBlock *common.Block) (ledger.PeerLedger, error) 
//Take Ledger by id and call ledgerProvider.Open(id) to open Ledger
func OpenLedger(id string) (ledger.PeerLedger, error) 
//Get the list of ledgerID and call ledgerProvider.List()
func GetLedgerIDs() ([]string, error)
//Close ledger provider
func Close()
//Construct a closeableledger
func wrapLedger(id string, l ledger.PeerLedger) ledger.PeerLedger
//The code is in core / ledger / ledger MGMT / ledger_mgmt.go

closableLedger:

type closableLedger struct {
    id string
    ledger.PeerLedger
}

func (l *closableLedger) Close() //Call l.closeWithoutLock()
func (l *closableLedger) closeWithoutLock() //delete(openedLedgers, l.id)
//The code is in core / ledger / ledger MGMT / ledger_mgmt.go

Topics: Go Database Blockchain snapshot simulator