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