github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/iavl/iavl_store.go (about)

     1  package iavl
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/cachekv"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/flatkv"
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/tracekv"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
    14  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    15  	"github.com/fibonacci-chain/fbc/libs/iavl"
    16  	iavlconfig "github.com/fibonacci-chain/fbc/libs/iavl/config"
    17  	"github.com/fibonacci-chain/fbc/libs/system/trace/persist"
    18  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    19  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/merkle"
    20  	tmkv "github.com/fibonacci-chain/fbc/libs/tendermint/libs/kv"
    21  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    22  	dbm "github.com/fibonacci-chain/fbc/libs/tm-db"
    23  )
    24  
    25  var (
    26  	FlagIavlCacheSize = "iavl-cache-size"
    27  
    28  	IavlCacheSize = 1000000
    29  )
    30  
    31  var (
    32  	_ types.KVStore       = (*Store)(nil)
    33  	_ types.CommitStore   = (*Store)(nil)
    34  	_ types.CommitKVStore = (*Store)(nil)
    35  	_ types.Queryable     = (*Store)(nil)
    36  )
    37  
    38  // Store Implements types.KVStore and CommitKVStore.
    39  type Store struct {
    40  	tree        Tree
    41  	flatKVStore *flatkv.Store
    42  	//for upgrade
    43  	upgradeVersion int64
    44  	//for time statistics
    45  	beginTime time.Time
    46  }
    47  
    48  func (st *Store) CurrentVersion() int64 {
    49  	tr := st.tree.(*iavl.MutableTree)
    50  	return tr.Version()
    51  }
    52  func (st *Store) StopStoreWithVersion(version int64) {
    53  	tr := st.tree.(*iavl.MutableTree)
    54  	tr.StopTree()
    55  }
    56  func (st *Store) StopStore() {
    57  	tr := st.tree.(*iavl.MutableTree)
    58  	tr.StopTree()
    59  }
    60  
    61  func (st *Store) GetHeights() map[int64][]byte {
    62  	return st.tree.GetPersistedRoots()
    63  }
    64  
    65  // LoadStore returns an IAVL Store as a CommitKVStore. Internally, it will load the
    66  // store's version (id) from the provided DB. An error is returned if the version
    67  // fails to load.
    68  func LoadStore(db dbm.DB, flatKVDB dbm.DB, id types.CommitID, lazyLoading bool, startVersion int64) (types.CommitKVStore, error) {
    69  	return LoadStoreWithInitialVersion(db, flatKVDB, id, lazyLoading, uint64(startVersion), uint64(0))
    70  }
    71  
    72  // LoadStoreWithInitialVersion returns an IAVL Store as a CommitKVStore setting its initialVersion
    73  // to the one given. Internally, it will load the store's version (id) from the
    74  // provided DB. An error is returned if the version fails to load.
    75  func LoadStoreWithInitialVersion(db dbm.DB, flatKVDB dbm.DB, id types.CommitID, lazyLoading bool, initialVersion uint64, upgradeVersion uint64) (types.CommitKVStore, error) {
    76  	tree, err := iavl.NewMutableTreeWithOpts(db, iavlconfig.DynamicConfig.GetIavlCacheSize(), &iavl.Options{InitialVersion: initialVersion, UpgradeVersion: upgradeVersion})
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	if lazyLoading {
    81  		_, err = tree.LazyLoadVersion(id.Version)
    82  	} else {
    83  		_, err = tree.LoadVersion(id.Version)
    84  	}
    85  
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	st := &Store{
    91  		tree:           tree,
    92  		flatKVStore:    flatkv.NewStore(flatKVDB),
    93  		upgradeVersion: -1,
    94  	}
    95  
    96  	if err = st.ValidateFlatVersion(); err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	return st, nil
   101  }
   102  func HasVersion(db dbm.DB, version int64) (bool, error) {
   103  	tree, err := iavl.NewMutableTreeWithOpts(db, iavlconfig.DynamicConfig.GetIavlCacheSize(), &iavl.Options{InitialVersion: 0})
   104  	if err != nil {
   105  		return false, err
   106  	}
   107  	return tree.VersionExistsInDb(version), nil
   108  }
   109  func GetCommitVersions(db dbm.DB) ([]int64, error) {
   110  	tree, err := iavl.NewMutableTreeWithOpts(db, iavlconfig.DynamicConfig.GetIavlCacheSize(), &iavl.Options{InitialVersion: 0})
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	return tree.GetVersions()
   115  }
   116  
   117  // UnsafeNewStore returns a reference to a new IAVL Store with a given mutable
   118  // IAVL tree reference. It should only be used for testing purposes.
   119  //
   120  // CONTRACT: The IAVL tree should be fully loaded.
   121  // CONTRACT: PruningOptions passed in as argument must be the same as pruning options
   122  // passed into iavl.MutableTree
   123  func UnsafeNewStore(tree *iavl.MutableTree) *Store {
   124  	return &Store{
   125  		tree:           tree,
   126  		upgradeVersion: -1,
   127  	}
   128  }
   129  
   130  // GetImmutable returns a reference to a new store backed by an immutable IAVL
   131  // tree at a specific version (height) without any pruning options. This should
   132  // be used for querying and iteration only. If the version does not exist or has
   133  // been pruned, an empty immutable IAVL tree will be used.
   134  // Any mutable operations executed will result in a panic.
   135  func (st *Store) GetImmutable(version int64) (*Store, error) {
   136  	var iTree *iavl.ImmutableTree
   137  	var err error
   138  	if !abci.GetDisableABCIQueryMutex() {
   139  		if !st.VersionExists(version) {
   140  			return nil, iavl.ErrVersionDoesNotExist
   141  		}
   142  
   143  		iTree, err = st.tree.GetImmutable(version)
   144  		if err != nil {
   145  			return nil, err
   146  		}
   147  	} else {
   148  		iTree, err = st.tree.GetImmutable(version)
   149  		if err != nil {
   150  			return nil, iavl.ErrVersionDoesNotExist
   151  		}
   152  	}
   153  	return &Store{
   154  		tree: &immutableTree{iTree},
   155  	}, nil
   156  }
   157  
   158  // GetEmptyImmutable returns an empty immutable IAVL tree
   159  func (st *Store) GetEmptyImmutable() *Store {
   160  	return &Store{tree: &immutableTree{&iavl.ImmutableTree{}}}
   161  }
   162  
   163  func (st *Store) CommitterCommit(inputDelta *iavl.TreeDelta) (types.CommitID, *iavl.TreeDelta) { // CommitterCommit
   164  	flag := false
   165  	if inputDelta != nil {
   166  		flag = true
   167  		st.tree.SetDelta(inputDelta)
   168  	}
   169  	ver := st.GetUpgradeVersion()
   170  	if ver != -1 {
   171  		st.tree.SetUpgradeVersion(ver)
   172  		st.SetUpgradeVersion(-1)
   173  	}
   174  	hash, version, outputDelta, err := st.tree.SaveVersion(flag)
   175  	if err != nil {
   176  		panic(err)
   177  	}
   178  
   179  	// commit to flat kv db
   180  	st.commitFlatKV(version)
   181  
   182  	return types.CommitID{
   183  		Version: version,
   184  		Hash:    hash,
   185  	}, &outputDelta
   186  }
   187  
   188  // Implements Committer.
   189  func (st *Store) LastCommitID() types.CommitID {
   190  	return types.CommitID{
   191  		Version: st.tree.Version(),
   192  		Hash:    st.tree.Hash(),
   193  	}
   194  }
   195  
   196  func (st *Store) LastCommitVersion() int64 {
   197  	return st.tree.Version()
   198  }
   199  
   200  // SetPruning panics as pruning options should be provided at initialization
   201  // since IAVl accepts pruning options directly.
   202  func (st *Store) SetPruning(_ types.PruningOptions) {
   203  	panic("cannot set pruning options on an initialized IAVL store")
   204  }
   205  
   206  // VersionExists returns whether or not a given version is stored.
   207  func (st *Store) VersionExists(version int64) bool {
   208  	return st.tree.VersionExists(version)
   209  }
   210  
   211  // Implements Store.
   212  func (st *Store) GetStoreType() types.StoreType {
   213  	return types.StoreTypeIAVL
   214  }
   215  
   216  // Implements Store.
   217  func (st *Store) CacheWrap() types.CacheWrap {
   218  	stores := cachekv.NewStoreWithPreChangeHandler(st, st.tree.PreChanges)
   219  	stores.StatisticsCell = st
   220  
   221  	return stores
   222  }
   223  
   224  // CacheWrapWithTrace implements the Store interface.
   225  func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap {
   226  	return cachekv.NewStore(tracekv.NewStore(st, w, tc))
   227  }
   228  
   229  // Implements types.KVStore.
   230  func (st *Store) Set(key, value []byte) {
   231  	types.AssertValidValue(value)
   232  	st.tree.Set(key, value)
   233  	st.setFlatKV(key, value)
   234  }
   235  
   236  // Implements types.KVStore.
   237  func (st *Store) Get(key []byte) []byte {
   238  	value := st.getFlatKV(key)
   239  	if value != nil {
   240  		return value
   241  	}
   242  	value = st.tree.Get(key)
   243  	if value != nil {
   244  		st.setFlatKV(key, value)
   245  	}
   246  
   247  	return value
   248  }
   249  
   250  // Implements types.KVStore.
   251  func (st *Store) Has(key []byte) (exists bool) {
   252  	if st.hasFlatKV(key) {
   253  		return true
   254  	}
   255  	return st.tree.Has(key)
   256  }
   257  
   258  // Implements types.KVStore.
   259  func (st *Store) Delete(key []byte) {
   260  	st.tree.Remove(key)
   261  	st.deleteFlatKV(key)
   262  }
   263  
   264  // DeleteVersions deletes a series of versions from the MutableTree. An error
   265  // is returned if any single version is invalid or the delete fails. All writes
   266  // happen in a single batch with a single commit.
   267  func (st *Store) DeleteVersions(versions ...int64) error {
   268  	return st.tree.DeleteVersions(versions...)
   269  }
   270  
   271  // Implements types.KVStore.
   272  func (st *Store) Iterator(start, end []byte) types.Iterator {
   273  	var iTree *iavl.ImmutableTree
   274  
   275  	switch tree := st.tree.(type) {
   276  	case *immutableTree:
   277  		iTree = tree.ImmutableTree
   278  	case *iavl.MutableTree:
   279  		iTree = tree.ImmutableTree
   280  	}
   281  
   282  	return newIAVLIterator(iTree, start, end, true)
   283  }
   284  
   285  // Implements types.KVStore.
   286  func (st *Store) ReverseIterator(start, end []byte) types.Iterator {
   287  	var iTree *iavl.ImmutableTree
   288  
   289  	switch tree := st.tree.(type) {
   290  	case *immutableTree:
   291  		iTree = tree.ImmutableTree
   292  	case *iavl.MutableTree:
   293  		iTree = tree.ImmutableTree
   294  	}
   295  
   296  	return newIAVLIterator(iTree, start, end, false)
   297  }
   298  
   299  // Handle gatest the latest height, if height is 0
   300  func getHeight(tree Tree, req abci.RequestQuery) int64 {
   301  	height := req.Height
   302  	if height == 0 {
   303  		latest := tree.Version()
   304  		_, err := tree.GetImmutable(latest - 1)
   305  		if err == nil {
   306  			height = latest - 1
   307  		} else {
   308  			height = latest
   309  		}
   310  	}
   311  	return height
   312  }
   313  
   314  // Query implements ABCI interface, allows queries
   315  //
   316  // by default we will return from (latest height -1),
   317  // as we will have merkle proofs immediately (header height = data height + 1)
   318  // If latest-1 is not present, use latest (which must be present)
   319  // if you care to have the latest data to see a tx results, you must
   320  // explicitly set the height you want to see
   321  func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
   322  	if tmtypes.HigherThanVenus1(req.Height) {
   323  		return st.queryWithCM40(req)
   324  	}
   325  	if len(req.Data) == 0 {
   326  		return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrTxDecode, "query cannot be zero length"))
   327  	}
   328  
   329  	// store the height we chose in the response, with 0 being changed to the
   330  	// latest height
   331  	res.Height = getHeight(st.tree, req)
   332  
   333  	switch req.Path {
   334  	case "/key": // get by key
   335  		key := req.Data // data holds the key bytes
   336  		res.Key = key
   337  
   338  		tree, err := st.tree.GetImmutable(res.Height)
   339  		if err != nil {
   340  			return sdkerrors.QueryResult(sdkerrors.Wrapf(iavl.ErrVersionDoesNotExist, "request height %d", req.Height))
   341  		}
   342  
   343  		if req.Prove {
   344  			value, proof, err := tree.GetWithProof(key)
   345  			if err != nil {
   346  				res.Log = err.Error()
   347  				break
   348  			}
   349  			if proof == nil {
   350  				// Proof == nil implies that the store is empty.
   351  				if value != nil {
   352  					panic("unexpected value for an empty proof")
   353  				}
   354  			}
   355  			if value != nil {
   356  				// value was found
   357  				res.Value = value
   358  				res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewValueOp(key, proof).ProofOp()}}
   359  			} else {
   360  				// value wasn't found
   361  				res.Value = nil
   362  				res.Proof = &merkle.Proof{Ops: []merkle.ProofOp{iavl.NewAbsenceOp(key, proof).ProofOp()}}
   363  			}
   364  		} else {
   365  			_, res.Value = tree.GetWithIndex(key)
   366  		}
   367  
   368  	case "/subspace":
   369  		var KVs []types.KVPair
   370  
   371  		subspace := req.Data
   372  		res.Key = subspace
   373  
   374  		iterator := types.KVStorePrefixIterator(st, subspace)
   375  		for ; iterator.Valid(); iterator.Next() {
   376  			KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()})
   377  		}
   378  
   379  		iterator.Close()
   380  		res.Value = cdc.MustMarshalBinaryLengthPrefixed(KVs)
   381  
   382  	default:
   383  		return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unexpected query path: %v", req.Path))
   384  	}
   385  
   386  	return res
   387  }
   388  
   389  func (st *Store) GetDBReadTime() int {
   390  	return st.tree.GetDBReadTime()
   391  }
   392  
   393  func (st *Store) GetDBWriteCount() int {
   394  	return st.tree.GetDBWriteCount()
   395  }
   396  
   397  func (st *Store) GetDBReadCount() int {
   398  	return st.tree.GetDBReadCount()
   399  }
   400  
   401  func (st *Store) GetNodeReadCount() int {
   402  	return st.tree.GetNodeReadCount()
   403  }
   404  
   405  func (st *Store) ResetCount() {
   406  	st.tree.ResetCount()
   407  	st.resetFlatKVCount()
   408  }
   409  
   410  func (st *Store) StartTiming() {
   411  	st.beginTime = time.Now()
   412  }
   413  
   414  func (st *Store) EndTiming(tag string) {
   415  	persist.GetStatistics().Accumulate(tag, st.beginTime)
   416  }
   417  
   418  //----------------------------------------
   419  
   420  // Implements types.Iterator.
   421  type iavlIterator struct {
   422  	// Domain
   423  	start, end []byte
   424  
   425  	key   []byte // The current key (mutable)
   426  	value []byte // The current value (mutable)
   427  
   428  	// Underlying store
   429  	tree *iavl.ImmutableTree
   430  
   431  	// Channel to push iteration values.
   432  	iterCh chan tmkv.Pair
   433  
   434  	// Close this to release goroutine.
   435  	quitCh chan struct{}
   436  
   437  	// Close this to signal that state is initialized.
   438  	initCh chan struct{}
   439  
   440  	mtx sync.Mutex
   441  
   442  	ascending bool // Iteration order
   443  
   444  	invalid bool // True once, true forever (mutable)
   445  }
   446  
   447  var _ types.Iterator = (*iavlIterator)(nil)
   448  
   449  // newIAVLIterator will create a new iavlIterator.
   450  // CONTRACT: Caller must release the iavlIterator, as each one creates a new
   451  // goroutine.
   452  func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator {
   453  	iter := &iavlIterator{
   454  		tree:      tree,
   455  		start:     types.Cp(start),
   456  		end:       types.Cp(end),
   457  		ascending: ascending,
   458  		iterCh:    make(chan tmkv.Pair), // Set capacity > 0?
   459  		quitCh:    make(chan struct{}),
   460  		initCh:    make(chan struct{}),
   461  	}
   462  	go iter.iterateRoutine()
   463  	go iter.initRoutine()
   464  	return iter
   465  }
   466  
   467  // Run this to funnel items from the tree to iterCh.
   468  func (iter *iavlIterator) iterateRoutine() {
   469  	iter.tree.IterateRange(
   470  		iter.start, iter.end, iter.ascending,
   471  		func(key, value []byte) bool {
   472  			select {
   473  			case <-iter.quitCh:
   474  				return true // done with iteration.
   475  			case iter.iterCh <- tmkv.Pair{Key: key, Value: value}:
   476  				return false // yay.
   477  			}
   478  		},
   479  	)
   480  	close(iter.iterCh) // done.
   481  }
   482  
   483  // Run this to fetch the first item.
   484  func (iter *iavlIterator) initRoutine() {
   485  	iter.receiveNext()
   486  	close(iter.initCh)
   487  }
   488  
   489  // Implements types.Iterator.
   490  func (iter *iavlIterator) Domain() (start, end []byte) {
   491  	return iter.start, iter.end
   492  }
   493  
   494  // Implements types.Iterator.
   495  func (iter *iavlIterator) Valid() bool {
   496  	iter.waitInit()
   497  	iter.mtx.Lock()
   498  
   499  	validity := !iter.invalid
   500  	iter.mtx.Unlock()
   501  	return validity
   502  }
   503  
   504  // Implements types.Iterator.
   505  func (iter *iavlIterator) Next() {
   506  	iter.waitInit()
   507  	iter.mtx.Lock()
   508  	iter.assertIsValid(true)
   509  
   510  	iter.receiveNext()
   511  	iter.mtx.Unlock()
   512  }
   513  
   514  // Implements types.Iterator.
   515  func (iter *iavlIterator) Key() []byte {
   516  	iter.waitInit()
   517  	iter.mtx.Lock()
   518  	iter.assertIsValid(true)
   519  
   520  	key := iter.key
   521  	iter.mtx.Unlock()
   522  	return key
   523  }
   524  
   525  // Implements types.Iterator.
   526  func (iter *iavlIterator) Value() []byte {
   527  	iter.waitInit()
   528  	iter.mtx.Lock()
   529  	iter.assertIsValid(true)
   530  
   531  	val := iter.value
   532  	iter.mtx.Unlock()
   533  	return val
   534  }
   535  
   536  // Close closes the IAVL iterator by closing the quit channel and waiting for
   537  // the iterCh to finish/close.
   538  func (iter *iavlIterator) Close() {
   539  	close(iter.quitCh)
   540  	// wait iterCh to close
   541  	for range iter.iterCh {
   542  	}
   543  }
   544  
   545  // Error performs a no-op.
   546  func (iter *iavlIterator) Error() error {
   547  	return nil
   548  }
   549  
   550  //----------------------------------------
   551  
   552  func (iter *iavlIterator) setNext(key, value []byte) {
   553  	iter.assertIsValid(false)
   554  
   555  	iter.key = key
   556  	iter.value = value
   557  }
   558  
   559  func (iter *iavlIterator) setInvalid() {
   560  	iter.assertIsValid(false)
   561  
   562  	iter.invalid = true
   563  }
   564  
   565  func (iter *iavlIterator) waitInit() {
   566  	<-iter.initCh
   567  }
   568  
   569  func (iter *iavlIterator) receiveNext() {
   570  	kvPair, ok := <-iter.iterCh
   571  	if ok {
   572  		iter.setNext(kvPair.Key, kvPair.Value)
   573  	} else {
   574  		iter.setInvalid()
   575  	}
   576  }
   577  
   578  // assertIsValid panics if the iterator is invalid. If unlockMutex is true,
   579  // it also unlocks the mutex before panicing, to prevent deadlocks in code that
   580  // recovers from panics
   581  func (iter *iavlIterator) assertIsValid(unlockMutex bool) {
   582  	if iter.invalid {
   583  		if unlockMutex {
   584  			iter.mtx.Unlock()
   585  		}
   586  		panic("invalid iterator")
   587  	}
   588  }
   589  
   590  // SetInitialVersion sets the initial version of the IAVL tree. It is used when
   591  // starting a new chain at an arbitrary height.
   592  func (st *Store) SetInitialVersion(version int64) {
   593  	st.tree.SetInitialVersion(uint64(version))
   594  }
   595  
   596  // Exports the IAVL store at the given version, returning an iavl.Exporter for the tree.
   597  func (st *Store) Export(version int64) (*iavl.Exporter, error) {
   598  	istore, err := st.GetImmutable(version)
   599  	if err != nil {
   600  		return nil, fmt.Errorf("iavl export failed for version %v: %w", version, err)
   601  	}
   602  	tree, ok := istore.tree.(*immutableTree)
   603  	if !ok || tree == nil {
   604  		return nil, fmt.Errorf("iavl export failed: unable to fetch tree for version %v", version)
   605  	}
   606  	return tree.Export(), nil
   607  }
   608  
   609  // Import imports an IAVL tree at the given version, returning an iavl.Importer for importing.
   610  func (st *Store) Import(version int64) (*iavl.Importer, error) {
   611  	tree, ok := st.tree.(*iavl.MutableTree)
   612  	if !ok {
   613  		return nil, errors.New("iavl import failed: unable to find mutable tree")
   614  	}
   615  	return tree.Import(version)
   616  }
   617  
   618  func (st *Store) SetUpgradeVersion(version int64) {
   619  	st.upgradeVersion = version
   620  }
   621  
   622  func (st *Store) GetUpgradeVersion() int64 {
   623  	return st.upgradeVersion
   624  }