Ledger (statedb) of Fabric 1.0 source code note
1. Overview of statedb
statedb, or VersionedDB, the state database, stores the latest values of all keys in the transaction log, also known as world state.
You can choose to implement it based on leveldb or cauchdb.
Statedb. The code is distributed in the core/ledger/kvledger/txmgmt/statedb directory. The directory structure is as follows:
- statedb.go, which defines the core interfaces VersionedDBProvider, VersionedDB, resultsinterator and QueryResult, as well as the UpdateBatch and nsIterator structures and methods.
- util.go, including the implementation of the utility functions EncodeValue and DecodeValue.
- The stateleveldb directory, the level dB version implementation of the VersionedDBProvider and VersionedDB interfaces, namely the stateleveldb.VersionedDBProvider and stateleveldb.versionedDB structures and methods.
- Statecouchdb directory, couchdb version implementation of VersionedDBProvider and VersionedDB interface, namely statecouchdb.VersionedDBProvider and statecouchdb.VersionedDB structure and method.
2. Definition of core interface
VersionedDBProvider interface definition:
type VersionedDBProvider interface { GetDBHandle(id string) (VersionedDB, error) //Get VersionedDB handle Close() //Close all VersionedDB instances } //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
VersionedDB interface definition:
type VersionedDB interface { //Gets the value of the given namespace and key GetState(namespace string, key string) (*VersionedValue, error) //Get the value of multiple keys in a single call GetStateMultipleKeys(namespace string, keys []string) ([]*VersionedValue, error) //Returns an iterator containing all key values (including startKey, excluding endKey) between the given key ranges GetStateRangeScanIterator(namespace string, startKey string, endKey string) (ResultsIterator, error) //Executes the given query and returns the iterator ExecuteQuery(namespace, query string) (ResultsIterator, error) //Batch application ApplyUpdates(batch *UpdateBatch, height *version.Height) error //Returns the height of the highest consistent transaction of statedb GetLatestSavePoint() (*version.Height, error) //Test whether the database supports this key (leveldb supports any bytes, while couchdb only supports utf-8 strings) ValidateKey(key string) error //Open db Open() error //Close db Close() } //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
ResultsIterator and QueryResult interface definitions:
type ResultsIterator interface { Next() (QueryResult, error) Close() } type QueryResult interface{} //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
Supplement CompositeKey, VersionedValue and VersionedKV structures:
type CompositeKey struct { Namespace string //Namespace Key string //Key } type VersionedValue struct { Value []byte //Value Version *version.Height //Edition } type VersionedKV struct { CompositeKey //Embed CompositeKey VersionedValue //Embedded VersionedValue } //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
nsUpdates structure and method:
type nsUpdates struct { m map[string]*VersionedValue //string is Key } func newNsUpdates() *nsUpdates//Construct nsUpdates //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
UpdateBatch structure and method:
type UpdateBatch struct { updates map[string]*nsUpdates //string is Namespace } //Construct UpdateBatch func NewUpdateBatch() *UpdateBatch //Press namespace and key to get Value func (batch *UpdateBatch) Get(ns string, key string) *VersionedValue //Press namespace and key to add Value func (batch *UpdateBatch) Put(ns string, key string, value []byte, version *version.Height) //Press namespace and key to delete the Value, which is set to nil func (batch *UpdateBatch) Delete(ns string, key string, version *version.Height) //Press namespace and key to find if it exists func (batch *UpdateBatch) Exists(ns string, key string) bool //Get updated namespace list func (batch *UpdateBatch) GetUpdatedNamespaces() []string //Press namespace to get nsUpdates func (batch *UpdateBatch) GetUpdates(ns string) map[string]*VersionedValue //Construct nsIterator func (batch *UpdateBatch) GetRangeScanIterator(ns string, startKey string, endKey string) ResultsIterator //Get or create nsUpdates by namespace func (batch *UpdateBatch) getOrCreateNsUpdates(ns string) *nsUpdates //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
Nstiterator structure and method:
type nsIterator struct { ns string //namespace nsUpdates *nsUpdates //batch.updates[ns] sortedKeys []string //key sorting in nsUpdates.m nextIndex int //startKey lastIndex int //endKey } //Construct nsIterator func newNsIterator(ns string, startKey string, endKey string, batch *UpdateBatch) *nsIterator func (itr *nsIterator) Next() (QueryResult, error) //Press itr.nextIndex to get VersionedKV func (itr *nsIterator) Close() // do nothing //The code is in core/ledger/kvledger/txmgmt/statedb/statedb.go
3. statedb based on leveldb
3.1 implementation of VersionedDB interface
The versioneddb interface implementation, that is, the versioneddb structure, is defined as follows:
type versionedDB struct { db *leveldbhelper.DBHandle //leveldb dbName string //dbName } //The code is in core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
The methods involved are as follows:
//Construct 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 //Press namespace and key to get Value func (vdb *versionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error) //Get the value of multiple keys in a single call func (vdb *versionedDB) GetStateMultipleKeys(namespace string, keys []string) ([]*statedb.VersionedValue, error) //Returns an iterator containing all key values (including startKey, excluding endKey) between the given key ranges func (vdb *versionedDB) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (statedb.ResultsIterator, error) //leveldb does not support the ExecuteQuery method func (vdb *versionedDB) ExecuteQuery(namespace, query string) (statedb.ResultsIterator, error) //Batch application func (vdb *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version.Height) error //Returns the height of the highest consistent transaction of statedb func (vdb *versionedDB) GetLatestSavePoint() (*version.Height, error) //Splice ns and key, ns []byte{0x00} key func constructCompositeKey(ns string, key string) []byte //Split ns and key, separator [] byte{0x00} func splitCompositeKey(compositeKey []byte) (string, string) //The code is in core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
func (vdb *versionedDB) ApplyUpdates(batch *statedb.UpdateBatch, height *version.Height) error code is as follows:
dbBatch := leveldbhelper.NewUpdateBatch() namespaces := batch.GetUpdatedNamespaces() //Get updated namespace list for _, ns := range namespaces { updates := batch.GetUpdates(ns) //Press namespace to get nsUpdates for k, vv := range updates { compositeKey := constructCompositeKey(ns, k) //Splicing ns and key if vv.Value == nil { dbBatch.Delete(compositeKey) } else { dbBatch.Put(compositeKey, statedb.EncodeValue(vv.Value, vv.Version)) } } } //statedb the height of the highest consistent transaction dbBatch.Put(savePointKey, height.ToBytes()) //var savePointKey = []byte{0x00} err := vdb.db.WriteBatch(dbBatch, true) //The code is in core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
3.2. Implementation of ResultsIterator interface
The results iterator interface implementation is kvScanner structure and method.
type kvScanner struct { namespace string dbItr iterator.Iterator } //Construct kvScanner func newKVScanner(namespace string, dbItr iterator.Iterator) *kvScanner //Get statedb.VersionedKV iteratively func (scanner *kvScanner) Next() (statedb.QueryResult, error) func (scanner *kvScanner) Close() //Release iterator //The code is in core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
3.3 implementation of VersionedDBProvider interface
VersionedDBProvider interface implementation, that is, VersionedDBProvider structure and method.
type VersionedDBProvider struct { dbProvider *leveldbhelper.Provider } func NewVersionedDBProvider() *VersionedDBProvider //Construct VersionedDBProvider //Get statedb.VersionedDB func (provider *VersionedDBProvider) GetDBHandle(dbName string) (statedb.VersionedDB, error) func (provider *VersionedDBProvider) Close() //Close statedb.VersionedDB //The code is in core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
4. statedb based on cauchdb
Temporarily omitted, to be added. Welcome to continue to follow brotherhood blockchain tutorial sharing!