From d58db5dcb5ed74531e1e04bfdaebb8f1d30845d8 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 29 May 2025 10:56:22 +0200 Subject: [PATCH 01/23] define StorageProvider interface --- internal/client/api/backend.go | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index 99e7cf0bfe..7539fbf8fc 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -13,6 +13,7 @@ import ( statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" "github.com/ChainSafe/gossamer/internal/primitives/state-machine/overlayedchanges" "github.com/ChainSafe/gossamer/internal/primitives/storage" + "github.com/ChainSafe/gossamer/pkg/trie/triedb" ) // ImportNotificationAction describes which block import notification stream should be notified. @@ -352,3 +353,51 @@ type Backend[ // TODO: implement UsageInfo if we require it // UsageInfo() *UsageInfo } + +// StorageProvider provides access to storage primitives +type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { + // Storage returns the value under the key in that block, given a blocks hash and a key. + Storage(hash H, key statemachine.StorageKey) (statemachine.StorageValue, error) + + // StorageHash returns the value under the hash in that block, given a blocks hash and a key. + StorageHash(hash H, key statemachine.StorageKey) (*H, error) + + // StorageKeys returns a [statemachine.KeysIter] that iterates over matching storage keys in that block + // given a blocks hash and a key prefix. + StorageKeys(hash H, prefix, startKey statemachine.StorageKey) (statemachine.KeysIter[H, Hasher], error) + + // StoragePairs returns an iterator over the storage keys and values in that block, + // given the blocks hash and a key prefix. + StoragePairs(hash H, prefix, startKey statemachine.StorageKey) (statemachine.PairsIter[H, Hasher], error) + + // ChildStorage returns the value under the key in that block, given a blocks hash, + // a key and a child storage key. + ChildStorage( + hash H, + childInfo storage.ChildInfo, + key statemachine.StorageKey, + ) (statemachine.StorageValue, error) + + // ChildStorageKeys returns a [statemachine.KeysIter] that iterates matching storage keys in that block, + // given a blocks hash, an optional key prefix and an optional child storage key. + ChildStorageKeys( + hash H, + childInfo storage.ChildInfo, + prefix statemachine.StorageKey, + startKey statemachine.StorageKey, + ) (statemachine.KeysIter[H, Hasher], error) + + // ChildStorageHash returns the hash under the key in a block, given its hash, + // a key and a child storage key. + ChildStorageHash(hash H, childInfo storage.ChildInfo, key statemachine.StorageKey) (*H, error) + + // ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. + ClosestMerkleValue(hash H, key statemachine.StorageKey) (triedb.MerkleValue[H], error) + + // ChildClosestMerkleValue returns the closest merkle value, given a blocks hash, a key and a child storage key. + ChildClosestMerkleValue( + hash H, + childInfo storage.ChildInfo, + key statemachine.StorageKey, + ) (triedb.MerkleValue[H], error) +} From 8738a48bba864e95efd68f37bd235a9000dcc928 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 29 May 2025 10:58:01 +0200 Subject: [PATCH 02/23] implement StorageProvider on ClientAdapter --- internal/client/adapter/client_adapter.go | 136 ++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index d764cf7720..8d1d607f26 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -12,11 +12,14 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/runtime" + statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" + "github.com/ChainSafe/gossamer/internal/primitives/storage" "github.com/ChainSafe/gossamer/lib/blocktree" "github.com/ChainSafe/gossamer/lib/common" rt "github.com/ChainSafe/gossamer/lib/runtime" rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage" "github.com/ChainSafe/gossamer/pkg/trie" + "github.com/ChainSafe/gossamer/pkg/trie/triedb" ) type ClientAdapterDB interface { @@ -36,6 +39,7 @@ type Client[ blockchain.Backend[H, N, Header, E] CompareAndSetBlockData(bd *types.BlockData) error + StateAt(hash H) (statemachine.Backend[H, Hasher], error) } type ClientAdapter[ @@ -556,6 +560,138 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetBlockTree(blocktree *blockt panic("unimplemented") } +// StorageProvider impl + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) Storage( + hash H, + key statemachine.StorageKey, +) (statemachine.StorageValue, error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return nil, err + } + + return stateAt.Storage(key) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageHash( + hash H, + key statemachine.StorageKey, +) (*H, error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return nil, err + } + + return stateAt.StorageHash(key) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( + hash H, + prefix, + startKey statemachine.StorageKey, +) (statemachine.KeysIter[H, Hasher], error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return statemachine.KeysIter[H, Hasher]{}, err + } + + return stateAt.Keys(statemachine.IterArgs{ + Prefix: prefix, + StartAt: startKey, + StartAtExclusive: false, // TODO: check that this is correct + }) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( + hash H, + prefix, + startKey statemachine.StorageKey, +) (statemachine.PairsIter[H, Hasher], error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return statemachine.PairsIter[H, Hasher]{}, err + } + + return stateAt.Pairs(statemachine.IterArgs{ + Prefix: prefix, + StartAt: startKey, + StartAtExclusive: false, // TODO: check that this is correct + }) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorage( + hash H, + childInfo storage.ChildInfo, + key statemachine.StorageKey, +) (statemachine.StorageValue, error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return statemachine.StorageValue{}, err + } + + return stateAt.ChildStorage(childInfo, key) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( + hash H, + childInfo storage.ChildInfo, + prefix statemachine.StorageKey, + startKey statemachine.StorageKey, +) (statemachine.KeysIter[H, Hasher], error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return statemachine.KeysIter[H, Hasher]{}, err + } + + return stateAt.Keys(statemachine.IterArgs{ + Prefix: prefix, + StartAt: startKey, + StartAtExclusive: false, // TODO: check that this is correct + ChildInfo: childInfo, + }) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageHash( + hash H, + childInfo storage.ChildInfo, + key statemachine.StorageKey, +) (*H, error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return nil, err + } + + return stateAt.ChildStorageHash(childInfo, key) +} + +// ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. +func (ca *ClientAdapter[H, Hasher, N, E, Header]) ClosestMerkleValue( + hash H, + key statemachine.StorageKey, +) (triedb.MerkleValue[H], error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return triedb.NodeMerkleValue{}, err + } + + return stateAt.ClosestMerkleValue(key) +} + +// ChildClosestMerkleValue returns the closest merkle value, given a blocks hash, a key and a child storage key. +func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildClosestMerkleValue( + hash H, + childInfo storage.ChildInfo, + key statemachine.StorageKey, +) (triedb.MerkleValue[H], error) { + stateAt, err := ca.client.StateAt(hash) + if err != nil { + return triedb.NodeMerkleValue{}, err + } + + return stateAt.ChildClosestMerkleValue(childInfo, key) +} + func prefixKey(hash common.Hash, prefix []byte) []byte { return append(prefix, hash.ToBytes()...) } From 0adb5c98e0bd782e2967fd2a15b56a7df1adae53 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 29 May 2025 10:58:24 +0200 Subject: [PATCH 03/23] implement read-only StorageState methods on ClientAdapter --- dot/state/block.go | 6 +- dot/state/storage_state.go | 2 +- internal/client/adapter/client_adapter.go | 244 ++++- .../client/adapter/client_adapter_test.go | 385 ++++++- internal/client/adapter/mocks/client.go | 60 ++ .../adapter/mocks/statemachine_backend.go | 979 ++++++++++++++++++ .../client/adapter/mocks_generate_test.go | 1 + 7 files changed, 1647 insertions(+), 30 deletions(-) create mode 100644 internal/client/adapter/mocks/statemachine_backend.go diff --git a/dot/state/block.go b/dot/state/block.go index 26ffddd681..8fee5e9866 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -36,7 +36,7 @@ var ( ReceiptPrefix = []byte("rcp") // ReceiptPrefix + hash -> receipt MessageQueuePrefix = []byte("mqp") // MessageQueuePrefix + hash -> message queue JustificationPrefix = []byte("jcp") // JustificationPrefix + hash -> justification - firstSlotNumberKey = []byte("fsn") // firstSlotNumberKey -> First slot number + FirstSlotNumberKey = []byte("fsn") // FirstSlotNumberKey -> First slot number errNilBlockTree = errors.New("blocktree is nil") errNilBlockBody = errors.New("block body is nil") @@ -580,12 +580,12 @@ func (bs *DefaultBlockState) SetBlockBody(hash common.Hash, body *types.Body) er func (bs *DefaultBlockState) SetFirstNonOriginSlotNumber(slotNumber uint64) error { buf := make([]byte, 8) binary.LittleEndian.PutUint64(buf, slotNumber) - return bs.db.Put(firstSlotNumberKey, buf) + return bs.db.Put(FirstSlotNumberKey, buf) } // GetFirstNonOriginSlotNumber returns the slot number of the first non origin block func (s *DefaultBlockState) GetFirstNonOriginSlotNumber() (uint64, error) { - slotVal, err := s.db.Get(firstSlotNumberKey) + slotVal, err := s.db.Get(FirstSlotNumberKey) if err != nil { if errors.Is(err, database.ErrNotFound) { return 0, nil diff --git a/dot/state/storage_state.go b/dot/state/storage_state.go index 59b044b698..702a818283 100644 --- a/dot/state/storage_state.go +++ b/dot/state/storage_state.go @@ -20,7 +20,7 @@ type StorageState interface { GenerateTrieProof(stateRoot common.Hash, keys [][]byte) ([][]byte, error) GetStorage(root *common.Hash, key []byte) ([]byte, error) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) - StorageRoot() (common.Hash, error) // best block state root, use HeaderBackend + StorageRoot() (common.Hash, error) Entries(root *common.Hash) (map[string][]byte, error) // should be overhauled to iterate GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 8d1d607f26..de608cef2c 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -4,12 +4,15 @@ package adapter import ( + "bytes" "encoding/binary" + "errors" "fmt" "time" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/runtime" statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" @@ -19,6 +22,8 @@ import ( rt "github.com/ChainSafe/gossamer/lib/runtime" rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage" "github.com/ChainSafe/gossamer/pkg/trie" + "github.com/ChainSafe/gossamer/pkg/trie/db" + "github.com/ChainSafe/gossamer/pkg/trie/inmemory" "github.com/ChainSafe/gossamer/pkg/trie/triedb" ) @@ -173,10 +178,15 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetBlockByNumber(blockNumber u return types.NewBlockFromGeneric(signedBlock.Block) } -// GetFinalisedHeader is unimplemented +// GetFinalisedHeader returns the finalised block header by round and setID // TODO: remove from BlockState interface since it is only use by RPC and is not part of the standard func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetFinalisedHeader(round, setID uint64) (*types.Header, error) { - panic("unimplemented") + rawHash, err := ca.db.Get(state.FinalisedHashKey(round, setID)) + if err != nil { + return nil, err + } + + return ca.GetHeader(common.NewHash(rawHash)) } // GetHashesByNumber returns all block hashes at the given height. @@ -269,6 +279,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetHighestFinalisedHash() (com return common.NewHashFromGeneric(ca.client.Info().FinalizedHash), nil } +// GetHighestRoundAndSetID gets the highest round and setID that have been finalised func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetHighestRoundAndSetID() (uint64, uint64, error) { b, err := ca.db.Get(state.HighestRoundAndSetIDKey) if err != nil { @@ -280,39 +291,69 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetHighestRoundAndSetID() (uin return round, setID, nil } +// GetJustification retrieves a Justification from the database func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetJustification(bhash common.Hash) ([]byte, error) { - data, err := ca.db.Get(prefixKey(bhash, state.JustificationPrefix)) - if err != nil { - return nil, err - } - - return data, nil + return ca.db.Get(prefixKey(bhash, state.JustificationPrefix)) } +// GetFirstNonOriginSlotNumber returns the slot number of the first non origin block func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetFirstNonOriginSlotNumber() (uint64, error) { - panic("unimplemented") + rawVal, err := ca.db.Get(state.FirstSlotNumberKey) + if err != nil { + if errors.Is(err, database.ErrNotFound) { + return 0, nil + } + return 0, err + } + + val := binary.LittleEndian.Uint64(rawVal) + return val, nil } +// GetReceipt retrieves a Receipt from the database func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetReceipt(hash common.Hash) ([]byte, error) { - panic("unimplemented") + return ca.db.Get(prefixKey(hash, state.ReceiptPrefix)) } +// GetMessageQueue retrieves a MessageQueue from the database func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetMessageQueue(hash common.Hash) ([]byte, error) { - panic("unimplemented") + return ca.db.Get(prefixKey(hash, state.MessageQueuePrefix)) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetTries() *state.Tries { panic("unimplemented") } +// GetBlockHashesBySlot gets all block hashes that were produced in the given slot. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - panic("unimplemented") + children, err := ca.client.Children(ca.client.Info().FinalizedHash) + if err != nil { + return nil, err + } + + var blockHashes []common.Hash + for _, child := range children { + hash := common.NewHashFromGeneric(child) + + slot, err := ca.GetSlotForBlock(hash) + if err != nil { + return nil, fmt.Errorf("getting slot for block %s: %w", child.String(), err) + } + + if slot == slotNum { + blockHashes = append(blockHashes, hash) + } + } + + return blockHashes, nil } +// GetAllBlocksAtNumber returns all unfinalised blocks with the given number func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetAllBlocksAtNumber(num uint) ([]common.Hash, error) { - panic("unimplemented") + return ca.GetHashesByNumber(num) } +// GetNonFinalisedBlocks get all the blocks in the blocktree func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetNonFinalisedBlocks() []common.Hash { lastFinalized := ca.client.Info().FinalizedHash @@ -374,7 +415,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) HasHeaderInDatabase(hash commo } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetLastFinalized() common.Hash { - panic("unimplemented") + return common.NewHashFromGeneric(ca.client.Info().FinalizedHash) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetFirstNonOriginSlotNumber(slotNumber uint64) error { @@ -402,8 +443,10 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetHighestRoundAndSetID(round, panic("unimplemented") } +// GetRoundAndSetID returns the finalised round and setID func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetRoundAndSetID() (uint64, uint64) { - panic("unimplemented") + round, setID, _ := ca.GetHighestRoundAndSetID() // TODO check this is correct + return round, setID } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetRuntime(blockHash common.Hash) (instance rt.Instance, err error) { @@ -499,8 +542,27 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoreTrie(*rtstorage.TrieState panic("unimplemented") } +// GetStateRootFromBlock returns the state root of the block with the given hash. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - panic("unimplemented") + var hash H + + if bhash == nil { + hash = ca.client.Info().BestHash + } else { + hasher := *new(Hasher) + hash = hasher.NewHash(bhash.ToBytes()) + } + + header, err := ca.client.Header(hash) + if err != nil { + return nil, err + } + if header == nil { + return nil, database.ErrNotFound + } + + h := common.NewHashFromGeneric((*header).StateRoot()) + return &h, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GenerateTrieProof(stateRoot common.Hash, keys [][]byte) ( @@ -508,44 +570,176 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GenerateTrieProof(stateRoot co panic("unimplemented") } +// GetStorage queries the state that corresponds to the given state root hash for the data at the given key. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorage(root *common.Hash, key []byte) ([]byte, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + return stateAt.Storage(key) } +const maxSearchDepth = 1000 + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) getStateByStateRoot( + root *common.Hash, +) (statemachine.Backend[H, Hasher], error) { + currentHash := ca.client.Info().BestHash + + if root == nil { + return ca.client.StateAt(currentHash) + } + + targetRoot := (*new(Hasher)).NewHash(root.ToBytes()) + + for i := 0; i < maxSearchDepth; i++ { + header, err := ca.client.Header(currentHash) + if err != nil { + return nil, err + } + if header == nil { + return nil, fmt.Errorf("no block header found for hash %s", currentHash.String()) + } + + if (*header).StateRoot() == targetRoot { + return ca.client.StateAt(currentHash) + } + + currentHash = (*header).ParentHash() + } + + return nil, fmt.Errorf("max search depth exceeded without finding storage root %s", targetRoot.String()) +} + +// GetStorageByBlockHash queries the state that at the given block hash for the data at the given key. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageByBlockHash(bhash *common.Hash, key []byte) ( []byte, error) { - panic("unimplemented") + var hash H + if bhash == nil { + hash = ca.client.Info().BestHash + } else { + hasher := *new(Hasher) + hash = hasher.NewHash(bhash.ToBytes()) + } + + return ca.Storage(hash, key) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageRoot() (common.Hash, error) { - panic("unimplemented") + header, err := ca.client.Header(ca.client.Info().BestHash) + if err != nil { + return common.Hash{}, err + } + + return common.NewHashFromGeneric((*header).StateRoot()), nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) Entries(root *common.Hash) (map[string][]byte, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + entries := make(map[string][]byte) + iter, err := stateAt.Pairs(statemachine.IterArgs{}) + if err != nil { + return nil, err + } + + for kv, err := range iter.All() { + if err != nil { + return nil, err + } + entries[string(kv.StorageKey)] = kv.StorageValue + } + + return entries, nil } +// GetKeysWithPrefix returns all keys with the given prefix from the state +// that corresponds to the given state root hash. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetKeysWithPrefix(root *common.Hash, prefix []byte) ( [][]byte, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + keys, err := stateAt.Keys(statemachine.IterArgs{Prefix: prefix}) + if err != nil { + return nil, err + } + + var res [][]byte + for key, err := range keys.All() { + if err != nil { + return nil, err + } + + res = append(res, bytes.Clone(key)) + } + return res, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageChild(root *common.Hash, keyToChild []byte) ( trie.Trie, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + memDB := db.NewEmptyMemoryDB() + storageTrie := inmemory.NewTrie(nil, memDB) + + iterArgs := statemachine.IterArgs{ + ChildInfo: storage.NewDefaultChildInfo(keyToChild), + } + + iter, err := stateAt.Pairs(iterArgs) + if err != nil { + return nil, err + } + + for kv, err := range iter.All() { + if err != nil { + return nil, err + } + + err = storageTrie.Put(kv.StorageKey, kv.StorageValue) + if err != nil { + return nil, err + } + } + return storageTrie, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ( []byte, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + info := storage.NewDefaultChildInfo(keyToChild) + return stateAt.ChildStorage(info, key) } +// LoadCode returns the runtime blob for the given block hash. func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCode(hash *common.Hash) ([]byte, error) { - panic("unimplemented") + // InmemoryStorageState.LoadCode() calls GetStorage() but I'm pretty sure `hash` is meant to be a block hash, + // not a state root hash. 🤔 + return ca.GetStorageByBlockHash(hash, common.CodeKey) } +// LoadCodeHash returns the hash of the runtime blob for the given block hash. func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCodeHash(hash *common.Hash) (common.Hash, error) { - panic("unimplemented") + code, err := ca.LoadCode(hash) + if err != nil { + return common.Hash{}, err + } + + return common.Blake2bHash(code) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) RegisterStorageObserver(o state.Observer) { diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index e10e0e1003..1c87738b8f 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -5,16 +5,22 @@ package adapter import ( "errors" + "fmt" "testing" "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/client/adapter/mocks" + "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/core/hash" "github.com/ChainSafe/gossamer/internal/primitives/runtime" "github.com/ChainSafe/gossamer/internal/primitives/runtime/generic" + statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" + "github.com/ChainSafe/gossamer/internal/primitives/storage" + "github.com/ChainSafe/gossamer/internal/primitives/trie" "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/pkg/trie/triedb" "github.com/stretchr/testify/require" ) @@ -245,7 +251,7 @@ func TestBlockOps(t *testing.T) { }) } -func TestGestJustification(t *testing.T) { +func TestGetJustification(t *testing.T) { hash := common.Hash{0x01, 0x02, 0x03} t.Run("ok", func(t *testing.T) { @@ -638,6 +644,8 @@ func TestNumberIsFinalised(t *testing.T) { func TestHasHeader(t *testing.T) { t.Run("header_is_not_finalized", func(t *testing.T) { + t.Parallel() + client, _, adapter := setupTest(t) children := []Hash{ @@ -711,3 +719,378 @@ func TestHasJustification(t *testing.T) { require.True(t, has) }) } + +func TestGetStateRootFromBlock(t *testing.T) { + t.Run("error", func(t *testing.T) { + client, _, adapter := setupTest(t) + + expectedError := errors.New("error") + client.EXPECT().Header(blockchainInfo.FinalizedHash).Return(nil, expectedError) + + bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) + + root, err := adapter.GetStateRootFromBlock(&bhash) + require.Error(t, err, expectedError) + require.Nil(t, root) + }) + + t.Run("block_not_found", func(t *testing.T) { + client, _, adapter := setupTest(t) + + client.EXPECT().Header(blockchainInfo.FinalizedHash).Return(nil, nil) + + bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) + + root, err := adapter.GetStateRootFromBlock(&bhash) + require.ErrorIs(t, err, database.ErrNotFound) + require.Nil(t, root) + }) + + t.Run("ok", func(t *testing.T) { + client, _, adapter := setupTest(t) + + client.EXPECT().Header(blockchainInfo.FinalizedHash).Return(&header, nil) + + expectedRoot := common.NewHashFromGeneric(header.StateRoot()) + bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) + + root, err := adapter.GetStateRootFromBlock(&bhash) + require.NoError(t, err) + require.Equal(t, &expectedRoot, root) + }) + + t.Run("bhash_nil", func(t *testing.T) { + client, _, adapter := setupTest(t) + + client.EXPECT().Info().Return(blockchainInfo) + client.EXPECT().Header(blockchainInfo.BestHash).Return(&header, nil) + + expectedRoot := common.NewHashFromGeneric(header.StateRoot()) + + root, err := adapter.GetStateRootFromBlock(nil) + + require.NoError(t, err) + require.Equal(t, &expectedRoot, root) + }) +} + +func TestGetStorage(t *testing.T) { + t.Run("error", func(t *testing.T) { + client, _, adapter := setupTest(t) + + expectedError := errors.New("kaput") + client.EXPECT().StateAt(header.Hash()).Return(nil, expectedError) + client.EXPECT().Info().Return(blockchainInfo) + client.EXPECT().Header(header.Hash()).Return(&header, nil) + + root := common.NewHashFromGeneric(header.StateRoot()) + + value, err := adapter.GetStorage(&root, []byte("key")) + require.ErrorIs(t, err, expectedError) + require.Nil(t, value) + }) + t.Run("ok", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + + client.EXPECT().StateAt(header.Hash()).Return(backend, nil) + client.EXPECT().Info().Return(blockchainInfo) + client.EXPECT().Header(header.Hash()).Return(&header, nil) + + root := common.NewHashFromGeneric(header.StateRoot()) + + value, err := adapter.GetStorage(&root, []byte("key")) + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) + t.Run("root_nil", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + + client.EXPECT().StateAt(blockchainInfo.BestHash).Return(backend, nil) + client.EXPECT().Info().Return(blockchainInfo) + + value, err := adapter.GetStorage(nil, []byte("key")) + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) + t.Run("search_succeeds", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + + length := uint16(min(maxSearchDepth-1, 10)) + _, genesisHeader := makeHeaderChain(t, client, length) + client.EXPECT().StateAt(genesisHeader.Hash()).Return(backend, nil) + + root := common.NewHashFromGeneric(genesisHeader.StateRoot()) + + value, err := adapter.GetStorage(&root, []byte("key")) + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) + t.Run("search_fails", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + + backend.EXPECT(). + Storage([]byte("key")). + Maybe(). + Return([]byte("value"), nil) + + _, genesisHeader := makeHeaderChain(t, client, maxSearchDepth+1) + client.EXPECT().StateAt(genesisHeader.Hash()).Maybe().Return(backend, nil) + + root := common.NewHashFromGeneric(genesisHeader.StateRoot()) + + value, err := adapter.GetStorage(&root, []byte("key")) + require.Error(t, err) + require.Nil(t, value) + }) +} + +// makeHeaderChain creates a chain of headers with the given header as the genesis block, +// at chain[0] and the best & finalized block at the end of the slice. +// The given client is configured to return them from Header() by their hash and to return +// [blockchain.Info] with appropriate values from Info(). +func makeHeaderChain( + t *testing.T, + client *mocks.Client[Hash, Hasher, Number, Extrinsic, Header], + length uint16, +) (chain []Header, genesisHeader Header) { + t.Helper() + + genesisHeader = header.Clone().(Header) + genesisHeader.SetNumber(Number(0)) + client.EXPECT().Header(genesisHeader.Hash()).Maybe().Return(&genesisHeader, nil) + chain = make([]Header, length) + chain[0] = genesisHeader + hasher := new(Hasher) + + for i := 1; i < int(length); i++ { + h := generic.NewHeader[Number, Hash, Hasher]( + Number(i), + hash.NewRandomH256(), + hasher.Hash([]byte(fmt.Sprintf("header%d", i))), + chain[i-1].Hash(), + runtime.Digest{}, + ) + + chain[i] = h + client.EXPECT().Header(h.Hash()).Maybe().Return(&h, nil) + } + + info := blockchain.Info[Hash, Number]{ + GenesisHash: genesisHeader.Hash(), + BestHash: chain[length-1].Hash(), + BestNumber: chain[length-1].Number(), + FinalizedHash: chain[length-1].Hash(), + FinalizedNumber: chain[length-1].Number(), + } + + client.EXPECT().Info().Return(info) + + return +} + +func TestGetStorageByBlockHash(t *testing.T) { + t.Run("error", func(t *testing.T) { + client, _, adapter := setupTest(t) + + expectedError := errors.New("kaput") + client.EXPECT().StateAt(blockchainInfo.FinalizedHash).Return(nil, expectedError) + + bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) + + value, err := adapter.GetStorageByBlockHash(&bhash, []byte("key")) + require.ErrorIs(t, err, expectedError) + require.Nil(t, value) + }) + t.Run("ok", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + + client.EXPECT().StateAt(blockchainInfo.FinalizedHash).Return(backend, nil) + + bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) + + value, err := adapter.GetStorageByBlockHash(&bhash, []byte("key")) + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) + t.Run("bhash_nil", func(t *testing.T) { + client, _, adapter := setupTest(t) + + backend := mocks.NewStatemachineBackend[Hash, Hasher](t) + backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + + client.EXPECT().StateAt(blockchainInfo.BestHash).Return(backend, nil) + client.EXPECT().Info().Return(blockchainInfo) + + value, err := adapter.GetStorageByBlockHash(nil, []byte("key")) + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) +} + +func Test_GetKeysWithPrefix_Entries(t *testing.T) { + client, _, adapter := setupTest(t) + + entries := map[string][]byte{ + "": {}, + "key1": []byte("value1"), + "key2": []byte("value2"), + "xyzKey1": []byte("xyzValue1"), + "long": []byte("newvaluewithmorethan32byteslength"), + } + + backend := statemachine.NewMemoryDBTrieBackendFromMap[Hash, Hasher](entries, storage.StateVersionV1) + client.EXPECT().Header(header.Hash()).Return(&header, nil) + client.EXPECT().StateAt(header.Hash()).Return(backend, nil) + client.EXPECT().Info().Return(blockchainInfo) + + root := common.NewHashFromGeneric(header.StateRoot()) + + t.Run("GetKeysWithPrefix", func(t *testing.T) { + keys, err := adapter.GetKeysWithPrefix(&root, []byte("ke")) + + require.NoError(t, err) + require.Len(t, keys, 2) + require.Contains(t, keys, []byte("key1")) + require.Contains(t, keys, []byte("key2")) + }) + + t.Run("GetKeysWithPrefix", func(t *testing.T) { + result, err := adapter.Entries(&root) + + require.NoError(t, err) + require.Equal(t, entries, result) + }) +} + +func TestGetFinalisedHeader(t *testing.T) { + t.Run("error", func(t *testing.T) { + _, db, adapter := setupTest(t) + + db.EXPECT().Get(state.FinalisedHashKey(23, 5)).Return(nil, database.ErrNotFound) + + finalisedHeader, err := adapter.GetFinalisedHeader(23, 5) + + require.ErrorIs(t, err, database.ErrNotFound) + require.Nil(t, finalisedHeader) + }) + t.Run("ok", func(t *testing.T) { + client, db, adapter := setupTest(t) + + client.EXPECT().Block(blockHash).Return(signedBlock, nil) + + expectedHeader, err := types.NewHeaderFromGeneric(header) + require.NoError(t, err) + + db.EXPECT().Get(state.FinalisedHashKey(23, 5)).Return(blockHash.Bytes(), nil) + + finalisedHeader, err := adapter.GetFinalisedHeader(23, 5) + + require.NoError(t, err) + require.Equal(t, expectedHeader, finalisedHeader) + }) +} + +func TestGetFirstNonOriginSlotNumber(t *testing.T) { + t.Run("not_found", func(t *testing.T) { + _, db, adapter := setupTest(t) + + db.EXPECT().Get(state.FirstSlotNumberKey).Return(nil, database.ErrNotFound) + + num, err := adapter.GetFirstNonOriginSlotNumber() + + require.NoError(t, err) + require.Equal(t, uint64(0), num) + }) + t.Run("other_error", func(t *testing.T) { + _, db, adapter := setupTest(t) + + db.EXPECT().Get(state.FirstSlotNumberKey).Return(nil, errors.New("kaput")) + + num, err := adapter.GetFirstNonOriginSlotNumber() + + require.Error(t, err) + require.Equal(t, uint64(0), num) + }) + t.Run("ok", func(t *testing.T) { + _, db, adapter := setupTest(t) + + fiveEncoded := []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + db.EXPECT().Get(state.FirstSlotNumberKey).Return(fiveEncoded[:], nil) + + num, err := adapter.GetFirstNonOriginSlotNumber() + + require.NoError(t, err) + require.Equal(t, uint64(5), num) + }) +} + +func Test_GetStorageFromChild_GetStorageChild(t *testing.T) { + client, _, adapter := setupTest(t) + + childInfo := storage.NewDefaultChildInfo([]byte("child1")) + mdb := trie.NewPrefixedMemoryDB[Hash, Hasher]() + + ksdb := trie.NewKeyspacedDB(mdb, childInfo.Keyspace()) + childTrie := triedb.NewEmptyTrieDB[Hash, Hasher](ksdb) + childTrie.SetVersion(storage.DefaultStateVersion.TrieLayout()) + require.NoError(t, childTrie.Set([]byte("key"), []byte("value"))) + require.NoError(t, childTrie.Set([]byte("anotherkey"), []byte("anothervalue"))) + + parentTrie := triedb.NewEmptyTrieDB[Hash, Hasher](mdb) + require.NoError(t, parentTrie.Set(childInfo.PrefixedStorageKey(), childTrie.MustHash().Bytes())) + require.NoError(t, parentTrie.Set([]byte("key"), []byte("value2"))) + require.NoError(t, parentTrie.Set([]byte(":code"), []byte("return 42"))) + parentTrie.SetVersion(storage.DefaultStateVersion.TrieLayout()) + + header := header.Clone().(Header) + header.SetStateRoot(parentTrie.MustHash()) + + info := blockchainInfo + info.BestHash = header.Hash() + client.EXPECT().Info().Return(info) + + backend := statemachine.NewTrieBackend[Hash, Hasher]( + statemachine.HashDBTrieBackendStorage[Hash]{mdb}, + parentTrie.MustHash(), + nil, + nil, + ) + client.EXPECT().StateAt(header.Hash()).Return(backend, nil) + + t.Run("GetStorageFromChild", func(t *testing.T) { + value, err := adapter.GetStorageFromChild(nil, []byte("child1"), []byte("key")) + + require.NoError(t, err) + require.Equal(t, []byte("value"), value) + }) + + t.Run("GetStorageChild", func(t *testing.T) { + storageChild, err := adapter.GetStorageChild(nil, []byte("child1")) + + require.NoError(t, err) + + require.Equal( + t, + map[string][]byte{ + "key": []byte("value"), + "anotherkey": []byte("anothervalue"), + }, + storageChild.Entries(), + ) + }) +} diff --git a/internal/client/adapter/mocks/client.go b/internal/client/adapter/mocks/client.go index f405ebe281..8f63c8f59f 100644 --- a/internal/client/adapter/mocks/client.go +++ b/internal/client/adapter/mocks/client.go @@ -12,6 +12,8 @@ import ( runtime "github.com/ChainSafe/gossamer/internal/primitives/runtime" + statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" + sync "sync" types "github.com/ChainSafe/gossamer/dot/types" @@ -1385,6 +1387,64 @@ func (_c *Client_RequiresFullSync_Call[H, Hasher, N, E, Header]) RunAndReturn(ru return _c } +// StateAt provides a mock function with given fields: hash +func (_m *Client[H, Hasher, N, E, Header]) StateAt(hash H) (statemachine.Backend[H, Hasher], error) { + ret := _m.Called(hash) + + if len(ret) == 0 { + panic("no return value specified for StateAt") + } + + var r0 statemachine.Backend[H, Hasher] + var r1 error + if rf, ok := ret.Get(0).(func(H) (statemachine.Backend[H, Hasher], error)); ok { + return rf(hash) + } + if rf, ok := ret.Get(0).(func(H) statemachine.Backend[H, Hasher]); ok { + r0 = rf(hash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.Backend[H, Hasher]) + } + } + + if rf, ok := ret.Get(1).(func(H) error); ok { + r1 = rf(hash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_StateAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StateAt' +type Client_StateAt_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// StateAt is a helper method to define mock.On call +// - hash H +func (_e *Client_Expecter[H, Hasher, N, E, Header]) StateAt(hash interface{}) *Client_StateAt_Call[H, Hasher, N, E, Header] { + return &Client_StateAt_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("StateAt", hash)} +} + +func (_c *Client_StateAt_Call[H, Hasher, N, E, Header]) Run(run func(hash H)) *Client_StateAt_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H)) + }) + return _c +} + +func (_c *Client_StateAt_Call[H, Hasher, N, E, Header]) Return(_a0 statemachine.Backend[H, Hasher], _a1 error) *Client_StateAt_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_StateAt_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H) (statemachine.Backend[H, Hasher], error)) *Client_StateAt_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + // Status provides a mock function with given fields: hash func (_m *Client[H, Hasher, N, E, Header]) Status(hash H) (blockchain.BlockStatus, error) { ret := _m.Called(hash) diff --git a/internal/client/adapter/mocks/statemachine_backend.go b/internal/client/adapter/mocks/statemachine_backend.go new file mode 100644 index 0000000000..15dadc3ead --- /dev/null +++ b/internal/client/adapter/mocks/statemachine_backend.go @@ -0,0 +1,979 @@ +// Code generated by mockery v2.53.3. DO NOT EDIT. + +package mocks + +import ( + runtime "github.com/ChainSafe/gossamer/internal/primitives/runtime" + statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" + mock "github.com/stretchr/testify/mock" + + storage "github.com/ChainSafe/gossamer/internal/primitives/storage" + + trie "github.com/ChainSafe/gossamer/internal/primitives/trie" + + triedb "github.com/ChainSafe/gossamer/pkg/trie/triedb" +) + +// StatemachineBackend is an autogenerated mock type for the Backend type +type StatemachineBackend[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + mock.Mock +} + +type StatemachineBackend_Expecter[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + mock *mock.Mock +} + +func (_m *StatemachineBackend[Hash, H]) EXPECT() *StatemachineBackend_Expecter[Hash, H] { + return &StatemachineBackend_Expecter[Hash, H]{mock: &_m.Mock} +} + +// ChildClosestMerkleValue provides a mock function with given fields: childInfo, key +func (_m *StatemachineBackend[Hash, H]) ChildClosestMerkleValue(childInfo storage.ChildInfo, key []byte) (triedb.MerkleValue[Hash], error) { + ret := _m.Called(childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildClosestMerkleValue") + } + + var r0 triedb.MerkleValue[Hash] + var r1 error + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) (triedb.MerkleValue[Hash], error)); ok { + return rf(childInfo, key) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) triedb.MerkleValue[Hash]); ok { + r0 = rf(childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(triedb.MerkleValue[Hash]) + } + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []byte) error); ok { + r1 = rf(childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ChildClosestMerkleValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildClosestMerkleValue' +type StatemachineBackend_ChildClosestMerkleValue_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ChildClosestMerkleValue is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ChildClosestMerkleValue(childInfo interface{}, key interface{}) *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H] { + return &StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H]{Call: _e.mock.On("ChildClosestMerkleValue", childInfo, key)} +} + +func (_c *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, key []byte)) *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H]) Return(_a0 triedb.MerkleValue[Hash], _a1 error) *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []byte) (triedb.MerkleValue[Hash], error)) *StatemachineBackend_ChildClosestMerkleValue_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ChildStorage provides a mock function with given fields: childInfo, key +func (_m *StatemachineBackend[Hash, H]) ChildStorage(childInfo storage.ChildInfo, key []byte) (statemachine.StorageValue, error) { + ret := _m.Called(childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildStorage") + } + + var r0 statemachine.StorageValue + var r1 error + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) (statemachine.StorageValue, error)); ok { + return rf(childInfo, key) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) statemachine.StorageValue); ok { + r0 = rf(childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.StorageValue) + } + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []byte) error); ok { + r1 = rf(childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ChildStorage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorage' +type StatemachineBackend_ChildStorage_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ChildStorage is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ChildStorage(childInfo interface{}, key interface{}) *StatemachineBackend_ChildStorage_Call[Hash, H] { + return &StatemachineBackend_ChildStorage_Call[Hash, H]{Call: _e.mock.On("ChildStorage", childInfo, key)} +} + +func (_c *StatemachineBackend_ChildStorage_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, key []byte)) *StatemachineBackend_ChildStorage_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ChildStorage_Call[Hash, H]) Return(_a0 statemachine.StorageValue, _a1 error) *StatemachineBackend_ChildStorage_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ChildStorage_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []byte) (statemachine.StorageValue, error)) *StatemachineBackend_ChildStorage_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ChildStorageHash provides a mock function with given fields: childInfo, key +func (_m *StatemachineBackend[Hash, H]) ChildStorageHash(childInfo storage.ChildInfo, key []byte) (*Hash, error) { + ret := _m.Called(childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildStorageHash") + } + + var r0 *Hash + var r1 error + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) (*Hash, error)); ok { + return rf(childInfo, key) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) *Hash); ok { + r0 = rf(childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*Hash) + } + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []byte) error); ok { + r1 = rf(childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ChildStorageHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorageHash' +type StatemachineBackend_ChildStorageHash_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ChildStorageHash is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ChildStorageHash(childInfo interface{}, key interface{}) *StatemachineBackend_ChildStorageHash_Call[Hash, H] { + return &StatemachineBackend_ChildStorageHash_Call[Hash, H]{Call: _e.mock.On("ChildStorageHash", childInfo, key)} +} + +func (_c *StatemachineBackend_ChildStorageHash_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, key []byte)) *StatemachineBackend_ChildStorageHash_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ChildStorageHash_Call[Hash, H]) Return(_a0 *Hash, _a1 error) *StatemachineBackend_ChildStorageHash_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ChildStorageHash_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []byte) (*Hash, error)) *StatemachineBackend_ChildStorageHash_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ChildStorageRoot provides a mock function with given fields: childInfo, delta, stateVersion +func (_m *StatemachineBackend[Hash, H]) ChildStorageRoot(childInfo storage.ChildInfo, delta []trie.KeyValue, stateVersion storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H]) { + ret := _m.Called(childInfo, delta, stateVersion) + + if len(ret) == 0 { + panic("no return value specified for ChildStorageRoot") + } + + var r0 Hash + var r1 bool + var r2 statemachine.BackendTransaction[Hash, H] + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])); ok { + return rf(childInfo, delta, stateVersion) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) Hash); ok { + r0 = rf(childInfo, delta, stateVersion) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(Hash) + } + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) bool); ok { + r1 = rf(childInfo, delta, stateVersion) + } else { + r1 = ret.Get(1).(bool) + } + + if rf, ok := ret.Get(2).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + r2 = rf(childInfo, delta, stateVersion) + } else { + r2 = ret.Get(2).(statemachine.BackendTransaction[Hash, H]) + } + + return r0, r1, r2 +} + +// StatemachineBackend_ChildStorageRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorageRoot' +type StatemachineBackend_ChildStorageRoot_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ChildStorageRoot is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - delta []trie.KeyValue +// - stateVersion storage.StateVersion +func (_e *StatemachineBackend_Expecter[Hash, H]) ChildStorageRoot(childInfo interface{}, delta interface{}, stateVersion interface{}) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { + return &StatemachineBackend_ChildStorageRoot_Call[Hash, H]{Call: _e.mock.On("ChildStorageRoot", childInfo, delta, stateVersion)} +} + +func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, delta []trie.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]trie.KeyValue), args[2].(storage.StateVersion)) + }) + return _c +} + +func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) Return(_a0 Hash, _a1 bool, _a2 statemachine.BackendTransaction[Hash, H]) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ClosestMerkleValue provides a mock function with given fields: key +func (_m *StatemachineBackend[Hash, H]) ClosestMerkleValue(key []byte) (triedb.MerkleValue[Hash], error) { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for ClosestMerkleValue") + } + + var r0 triedb.MerkleValue[Hash] + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (triedb.MerkleValue[Hash], error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func([]byte) triedb.MerkleValue[Hash]); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(triedb.MerkleValue[Hash]) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ClosestMerkleValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClosestMerkleValue' +type StatemachineBackend_ClosestMerkleValue_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ClosestMerkleValue is a helper method to define mock.On call +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ClosestMerkleValue(key interface{}) *StatemachineBackend_ClosestMerkleValue_Call[Hash, H] { + return &StatemachineBackend_ClosestMerkleValue_Call[Hash, H]{Call: _e.mock.On("ClosestMerkleValue", key)} +} + +func (_c *StatemachineBackend_ClosestMerkleValue_Call[Hash, H]) Run(run func(key []byte)) *StatemachineBackend_ClosestMerkleValue_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ClosestMerkleValue_Call[Hash, H]) Return(_a0 triedb.MerkleValue[Hash], _a1 error) *StatemachineBackend_ClosestMerkleValue_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ClosestMerkleValue_Call[Hash, H]) RunAndReturn(run func([]byte) (triedb.MerkleValue[Hash], error)) *StatemachineBackend_ClosestMerkleValue_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ExistsChildStorage provides a mock function with given fields: childInfo, key +func (_m *StatemachineBackend[Hash, H]) ExistsChildStorage(childInfo storage.ChildInfo, key []byte) (bool, error) { + ret := _m.Called(childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ExistsChildStorage") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) (bool, error)); ok { + return rf(childInfo, key) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) bool); ok { + r0 = rf(childInfo, key) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []byte) error); ok { + r1 = rf(childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ExistsChildStorage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExistsChildStorage' +type StatemachineBackend_ExistsChildStorage_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ExistsChildStorage is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ExistsChildStorage(childInfo interface{}, key interface{}) *StatemachineBackend_ExistsChildStorage_Call[Hash, H] { + return &StatemachineBackend_ExistsChildStorage_Call[Hash, H]{Call: _e.mock.On("ExistsChildStorage", childInfo, key)} +} + +func (_c *StatemachineBackend_ExistsChildStorage_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, key []byte)) *StatemachineBackend_ExistsChildStorage_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ExistsChildStorage_Call[Hash, H]) Return(_a0 bool, _a1 error) *StatemachineBackend_ExistsChildStorage_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ExistsChildStorage_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []byte) (bool, error)) *StatemachineBackend_ExistsChildStorage_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// ExistsStorage provides a mock function with given fields: key +func (_m *StatemachineBackend[Hash, H]) ExistsStorage(key []byte) (bool, error) { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for ExistsStorage") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (bool, error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func([]byte) bool); ok { + r0 = rf(key) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_ExistsStorage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExistsStorage' +type StatemachineBackend_ExistsStorage_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// ExistsStorage is a helper method to define mock.On call +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) ExistsStorage(key interface{}) *StatemachineBackend_ExistsStorage_Call[Hash, H] { + return &StatemachineBackend_ExistsStorage_Call[Hash, H]{Call: _e.mock.On("ExistsStorage", key)} +} + +func (_c *StatemachineBackend_ExistsStorage_Call[Hash, H]) Run(run func(key []byte)) *StatemachineBackend_ExistsStorage_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_ExistsStorage_Call[Hash, H]) Return(_a0 bool, _a1 error) *StatemachineBackend_ExistsStorage_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_ExistsStorage_Call[Hash, H]) RunAndReturn(run func([]byte) (bool, error)) *StatemachineBackend_ExistsStorage_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// FullStorageRoot provides a mock function with given fields: delta, childDeltas, stateVersion +func (_m *StatemachineBackend[Hash, H]) FullStorageRoot(delta []trie.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { + ret := _m.Called(delta, childDeltas, stateVersion) + + if len(ret) == 0 { + panic("no return value specified for FullStorageRoot") + } + + var r0 Hash + var r1 statemachine.BackendTransaction[Hash, H] + if rf, ok := ret.Get(0).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { + return rf(delta, childDeltas, stateVersion) + } + if rf, ok := ret.Get(0).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) Hash); ok { + r0 = rf(delta, childDeltas, stateVersion) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(Hash) + } + } + + if rf, ok := ret.Get(1).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + r1 = rf(delta, childDeltas, stateVersion) + } else { + r1 = ret.Get(1).(statemachine.BackendTransaction[Hash, H]) + } + + return r0, r1 +} + +// StatemachineBackend_FullStorageRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FullStorageRoot' +type StatemachineBackend_FullStorageRoot_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// FullStorageRoot is a helper method to define mock.On call +// - delta []trie.KeyValue +// - childDeltas []statemachine.ChildDelta +// - stateVersion storage.StateVersion +func (_e *StatemachineBackend_Expecter[Hash, H]) FullStorageRoot(delta interface{}, childDeltas interface{}, stateVersion interface{}) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { + return &StatemachineBackend_FullStorageRoot_Call[Hash, H]{Call: _e.mock.On("FullStorageRoot", delta, childDeltas, stateVersion)} +} + +func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) Run(run func(delta []trie.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion)) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]trie.KeyValue), args[1].([]statemachine.ChildDelta), args[2].(storage.StateVersion)) + }) + return _c +} + +func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) Return(_a0 Hash, _a1 statemachine.BackendTransaction[Hash, H]) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) RunAndReturn(run func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// Keys provides a mock function with given fields: args +func (_m *StatemachineBackend[Hash, H]) Keys(args statemachine.IterArgs) (statemachine.KeysIter[Hash, H], error) { + ret := _m.Called(args) + + if len(ret) == 0 { + panic("no return value specified for Keys") + } + + var r0 statemachine.KeysIter[Hash, H] + var r1 error + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) (statemachine.KeysIter[Hash, H], error)); ok { + return rf(args) + } + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) statemachine.KeysIter[Hash, H]); ok { + r0 = rf(args) + } else { + r0 = ret.Get(0).(statemachine.KeysIter[Hash, H]) + } + + if rf, ok := ret.Get(1).(func(statemachine.IterArgs) error); ok { + r1 = rf(args) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_Keys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Keys' +type StatemachineBackend_Keys_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// Keys is a helper method to define mock.On call +// - args statemachine.IterArgs +func (_e *StatemachineBackend_Expecter[Hash, H]) Keys(args interface{}) *StatemachineBackend_Keys_Call[Hash, H] { + return &StatemachineBackend_Keys_Call[Hash, H]{Call: _e.mock.On("Keys", args)} +} + +func (_c *StatemachineBackend_Keys_Call[Hash, H]) Run(run func(args statemachine.IterArgs)) *StatemachineBackend_Keys_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(statemachine.IterArgs)) + }) + return _c +} + +func (_c *StatemachineBackend_Keys_Call[Hash, H]) Return(_a0 statemachine.KeysIter[Hash, H], _a1 error) *StatemachineBackend_Keys_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_Keys_Call[Hash, H]) RunAndReturn(run func(statemachine.IterArgs) (statemachine.KeysIter[Hash, H], error)) *StatemachineBackend_Keys_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// NextChildStorageKey provides a mock function with given fields: childInfo, key +func (_m *StatemachineBackend[Hash, H]) NextChildStorageKey(childInfo storage.ChildInfo, key []byte) (statemachine.StorageKey, error) { + ret := _m.Called(childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for NextChildStorageKey") + } + + var r0 statemachine.StorageKey + var r1 error + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) (statemachine.StorageKey, error)); ok { + return rf(childInfo, key) + } + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []byte) statemachine.StorageKey); ok { + r0 = rf(childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.StorageKey) + } + } + + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []byte) error); ok { + r1 = rf(childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_NextChildStorageKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NextChildStorageKey' +type StatemachineBackend_NextChildStorageKey_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// NextChildStorageKey is a helper method to define mock.On call +// - childInfo storage.ChildInfo +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) NextChildStorageKey(childInfo interface{}, key interface{}) *StatemachineBackend_NextChildStorageKey_Call[Hash, H] { + return &StatemachineBackend_NextChildStorageKey_Call[Hash, H]{Call: _e.mock.On("NextChildStorageKey", childInfo, key)} +} + +func (_c *StatemachineBackend_NextChildStorageKey_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, key []byte)) *StatemachineBackend_NextChildStorageKey_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(storage.ChildInfo), args[1].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_NextChildStorageKey_Call[Hash, H]) Return(_a0 statemachine.StorageKey, _a1 error) *StatemachineBackend_NextChildStorageKey_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_NextChildStorageKey_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []byte) (statemachine.StorageKey, error)) *StatemachineBackend_NextChildStorageKey_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// NextStorageKey provides a mock function with given fields: key +func (_m *StatemachineBackend[Hash, H]) NextStorageKey(key []byte) (statemachine.StorageKey, error) { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for NextStorageKey") + } + + var r0 statemachine.StorageKey + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (statemachine.StorageKey, error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func([]byte) statemachine.StorageKey); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.StorageKey) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_NextStorageKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NextStorageKey' +type StatemachineBackend_NextStorageKey_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// NextStorageKey is a helper method to define mock.On call +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) NextStorageKey(key interface{}) *StatemachineBackend_NextStorageKey_Call[Hash, H] { + return &StatemachineBackend_NextStorageKey_Call[Hash, H]{Call: _e.mock.On("NextStorageKey", key)} +} + +func (_c *StatemachineBackend_NextStorageKey_Call[Hash, H]) Run(run func(key []byte)) *StatemachineBackend_NextStorageKey_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_NextStorageKey_Call[Hash, H]) Return(_a0 statemachine.StorageKey, _a1 error) *StatemachineBackend_NextStorageKey_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_NextStorageKey_Call[Hash, H]) RunAndReturn(run func([]byte) (statemachine.StorageKey, error)) *StatemachineBackend_NextStorageKey_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// Pairs provides a mock function with given fields: args +func (_m *StatemachineBackend[Hash, H]) Pairs(args statemachine.IterArgs) (statemachine.PairsIter[Hash, H], error) { + ret := _m.Called(args) + + if len(ret) == 0 { + panic("no return value specified for Pairs") + } + + var r0 statemachine.PairsIter[Hash, H] + var r1 error + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) (statemachine.PairsIter[Hash, H], error)); ok { + return rf(args) + } + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) statemachine.PairsIter[Hash, H]); ok { + r0 = rf(args) + } else { + r0 = ret.Get(0).(statemachine.PairsIter[Hash, H]) + } + + if rf, ok := ret.Get(1).(func(statemachine.IterArgs) error); ok { + r1 = rf(args) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_Pairs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Pairs' +type StatemachineBackend_Pairs_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// Pairs is a helper method to define mock.On call +// - args statemachine.IterArgs +func (_e *StatemachineBackend_Expecter[Hash, H]) Pairs(args interface{}) *StatemachineBackend_Pairs_Call[Hash, H] { + return &StatemachineBackend_Pairs_Call[Hash, H]{Call: _e.mock.On("Pairs", args)} +} + +func (_c *StatemachineBackend_Pairs_Call[Hash, H]) Run(run func(args statemachine.IterArgs)) *StatemachineBackend_Pairs_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(statemachine.IterArgs)) + }) + return _c +} + +func (_c *StatemachineBackend_Pairs_Call[Hash, H]) Return(_a0 statemachine.PairsIter[Hash, H], _a1 error) *StatemachineBackend_Pairs_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_Pairs_Call[Hash, H]) RunAndReturn(run func(statemachine.IterArgs) (statemachine.PairsIter[Hash, H], error)) *StatemachineBackend_Pairs_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// RawIter provides a mock function with given fields: args +func (_m *StatemachineBackend[Hash, H]) RawIter(args statemachine.IterArgs) (statemachine.StorageIterator[Hash, H], error) { + ret := _m.Called(args) + + if len(ret) == 0 { + panic("no return value specified for RawIter") + } + + var r0 statemachine.StorageIterator[Hash, H] + var r1 error + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) (statemachine.StorageIterator[Hash, H], error)); ok { + return rf(args) + } + if rf, ok := ret.Get(0).(func(statemachine.IterArgs) statemachine.StorageIterator[Hash, H]); ok { + r0 = rf(args) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.StorageIterator[Hash, H]) + } + } + + if rf, ok := ret.Get(1).(func(statemachine.IterArgs) error); ok { + r1 = rf(args) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_RawIter_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RawIter' +type StatemachineBackend_RawIter_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// RawIter is a helper method to define mock.On call +// - args statemachine.IterArgs +func (_e *StatemachineBackend_Expecter[Hash, H]) RawIter(args interface{}) *StatemachineBackend_RawIter_Call[Hash, H] { + return &StatemachineBackend_RawIter_Call[Hash, H]{Call: _e.mock.On("RawIter", args)} +} + +func (_c *StatemachineBackend_RawIter_Call[Hash, H]) Run(run func(args statemachine.IterArgs)) *StatemachineBackend_RawIter_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(statemachine.IterArgs)) + }) + return _c +} + +func (_c *StatemachineBackend_RawIter_Call[Hash, H]) Return(_a0 statemachine.StorageIterator[Hash, H], _a1 error) *StatemachineBackend_RawIter_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_RawIter_Call[Hash, H]) RunAndReturn(run func(statemachine.IterArgs) (statemachine.StorageIterator[Hash, H], error)) *StatemachineBackend_RawIter_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// Storage provides a mock function with given fields: key +func (_m *StatemachineBackend[Hash, H]) Storage(key []byte) (statemachine.StorageValue, error) { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for Storage") + } + + var r0 statemachine.StorageValue + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (statemachine.StorageValue, error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func([]byte) statemachine.StorageValue); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(statemachine.StorageValue) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_Storage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Storage' +type StatemachineBackend_Storage_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// Storage is a helper method to define mock.On call +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) Storage(key interface{}) *StatemachineBackend_Storage_Call[Hash, H] { + return &StatemachineBackend_Storage_Call[Hash, H]{Call: _e.mock.On("Storage", key)} +} + +func (_c *StatemachineBackend_Storage_Call[Hash, H]) Run(run func(key []byte)) *StatemachineBackend_Storage_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_Storage_Call[Hash, H]) Return(_a0 statemachine.StorageValue, _a1 error) *StatemachineBackend_Storage_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_Storage_Call[Hash, H]) RunAndReturn(run func([]byte) (statemachine.StorageValue, error)) *StatemachineBackend_Storage_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// StorageHash provides a mock function with given fields: key +func (_m *StatemachineBackend[Hash, H]) StorageHash(key []byte) (*Hash, error) { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for StorageHash") + } + + var r0 *Hash + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (*Hash, error)); ok { + return rf(key) + } + if rf, ok := ret.Get(0).(func([]byte) *Hash); ok { + r0 = rf(key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*Hash) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StatemachineBackend_StorageHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StorageHash' +type StatemachineBackend_StorageHash_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// StorageHash is a helper method to define mock.On call +// - key []byte +func (_e *StatemachineBackend_Expecter[Hash, H]) StorageHash(key interface{}) *StatemachineBackend_StorageHash_Call[Hash, H] { + return &StatemachineBackend_StorageHash_Call[Hash, H]{Call: _e.mock.On("StorageHash", key)} +} + +func (_c *StatemachineBackend_StorageHash_Call[Hash, H]) Run(run func(key []byte)) *StatemachineBackend_StorageHash_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *StatemachineBackend_StorageHash_Call[Hash, H]) Return(_a0 *Hash, _a1 error) *StatemachineBackend_StorageHash_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_StorageHash_Call[Hash, H]) RunAndReturn(run func([]byte) (*Hash, error)) *StatemachineBackend_StorageHash_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// StorageRoot provides a mock function with given fields: delta, stateVersion +func (_m *StatemachineBackend[Hash, H]) StorageRoot(delta []trie.KeyValue, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { + ret := _m.Called(delta, stateVersion) + + if len(ret) == 0 { + panic("no return value specified for StorageRoot") + } + + var r0 Hash + var r1 statemachine.BackendTransaction[Hash, H] + if rf, ok := ret.Get(0).(func([]trie.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { + return rf(delta, stateVersion) + } + if rf, ok := ret.Get(0).(func([]trie.KeyValue, storage.StateVersion) Hash); ok { + r0 = rf(delta, stateVersion) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(Hash) + } + } + + if rf, ok := ret.Get(1).(func([]trie.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + r1 = rf(delta, stateVersion) + } else { + r1 = ret.Get(1).(statemachine.BackendTransaction[Hash, H]) + } + + return r0, r1 +} + +// StatemachineBackend_StorageRoot_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StorageRoot' +type StatemachineBackend_StorageRoot_Call[Hash runtime.Hash, H runtime.Hasher[Hash]] struct { + *mock.Call +} + +// StorageRoot is a helper method to define mock.On call +// - delta []trie.KeyValue +// - stateVersion storage.StateVersion +func (_e *StatemachineBackend_Expecter[Hash, H]) StorageRoot(delta interface{}, stateVersion interface{}) *StatemachineBackend_StorageRoot_Call[Hash, H] { + return &StatemachineBackend_StorageRoot_Call[Hash, H]{Call: _e.mock.On("StorageRoot", delta, stateVersion)} +} + +func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) Run(run func(delta []trie.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_StorageRoot_Call[Hash, H] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]trie.KeyValue), args[1].(storage.StateVersion)) + }) + return _c +} + +func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) Return(_a0 Hash, _a1 statemachine.BackendTransaction[Hash, H]) *StatemachineBackend_StorageRoot_Call[Hash, H] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) RunAndReturn(run func([]trie.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_StorageRoot_Call[Hash, H] { + _c.Call.Return(run) + return _c +} + +// NewStatemachineBackend creates a new instance of StatemachineBackend. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStatemachineBackend[Hash runtime.Hash, H runtime.Hasher[Hash]](t interface { + mock.TestingT + Cleanup(func()) +}) *StatemachineBackend[Hash, H] { + mock := &StatemachineBackend[Hash, H]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/client/adapter/mocks_generate_test.go b/internal/client/adapter/mocks_generate_test.go index 5f3f5dcb44..2e50128d6a 100644 --- a/internal/client/adapter/mocks_generate_test.go +++ b/internal/client/adapter/mocks_generate_test.go @@ -5,3 +5,4 @@ package adapter //go:generate mockery --name=Client --case=snake --with-expecter=true //go:generate mockery --name=ClientAdapterDB --case=snake --with-expecter=true +//go:generate mockery --srcpkg=github.com/ChainSafe/gossamer/internal/primitives/state-machine --name=Backend --case=snake --structname=StatemachineBackend --filename=statemachine_backend.go --with-expecter=true From 9dda3ce72e10e27f10f594126fcbd84a15e7b26c Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 12 Jun 2025 21:42:25 +0700 Subject: [PATCH 04/23] lint --- .../client/adapter/client_adapter_test.go | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index 1c87738b8f..334c7fa2ce 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -643,6 +643,8 @@ func TestNumberIsFinalised(t *testing.T) { } func TestHasHeader(t *testing.T) { + t.Parallel() + t.Run("header_is_not_finalized", func(t *testing.T) { t.Parallel() @@ -660,6 +662,8 @@ func TestHasHeader(t *testing.T) { require.True(t, has) }) t.Run("header_is_finalized", func(t *testing.T) { + t.Parallel() + client, _, adapter := setupTest(t) client.EXPECT().Info().Return(blockchainInfo) @@ -672,6 +676,8 @@ func TestHasHeader(t *testing.T) { }) t.Run("not_has_header", func(t *testing.T) { + t.Parallel() + client, _, adapter := setupTest(t) client.EXPECT().Info().Return(blockchainInfo) @@ -824,8 +830,8 @@ func TestGetStorage(t *testing.T) { backend := mocks.NewStatemachineBackend[Hash, Hasher](t) backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) - length := uint16(min(maxSearchDepth-1, 10)) - _, genesisHeader := makeHeaderChain(t, client, length) + length := min(maxSearchDepth-1, 10) + genesisHeader := makeHeaderChain(t, client, uint16(length)) client.EXPECT().StateAt(genesisHeader.Hash()).Return(backend, nil) root := common.NewHashFromGeneric(genesisHeader.StateRoot()) @@ -844,7 +850,7 @@ func TestGetStorage(t *testing.T) { Maybe(). Return([]byte("value"), nil) - _, genesisHeader := makeHeaderChain(t, client, maxSearchDepth+1) + genesisHeader := makeHeaderChain(t, client, maxSearchDepth+1) client.EXPECT().StateAt(genesisHeader.Hash()).Maybe().Return(backend, nil) root := common.NewHashFromGeneric(genesisHeader.StateRoot()) @@ -855,21 +861,21 @@ func TestGetStorage(t *testing.T) { }) } -// makeHeaderChain creates a chain of headers with the given header as the genesis block, -// at chain[0] and the best & finalized block at the end of the slice. +// makeHeaderChain creates a chain of headers and returns the header of the genesis block. +// // The given client is configured to return them from Header() by their hash and to return // [blockchain.Info] with appropriate values from Info(). func makeHeaderChain( t *testing.T, client *mocks.Client[Hash, Hasher, Number, Extrinsic, Header], length uint16, -) (chain []Header, genesisHeader Header) { +) (genesisHeader Header) { t.Helper() genesisHeader = header.Clone().(Header) genesisHeader.SetNumber(Number(0)) client.EXPECT().Header(genesisHeader.Hash()).Maybe().Return(&genesisHeader, nil) - chain = make([]Header, length) + chain := make([]Header, length) chain[0] = genesisHeader hasher := new(Hasher) @@ -1065,7 +1071,7 @@ func Test_GetStorageFromChild_GetStorageChild(t *testing.T) { client.EXPECT().Info().Return(info) backend := statemachine.NewTrieBackend[Hash, Hasher]( - statemachine.HashDBTrieBackendStorage[Hash]{mdb}, + statemachine.HashDBTrieBackendStorage[Hash]{HashDB: mdb}, parentTrie.MustHash(), nil, nil, From ad9e0657201a7cfeff861d958a98748498edf0d6 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Wed, 18 Jun 2025 15:39:44 +0700 Subject: [PATCH 05/23] address some review feedback --- internal/client/adapter/client_adapter.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index b27481a857..ede314349c 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -445,7 +445,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetHighestRoundAndSetID(round, // GetRoundAndSetID returns the finalised round and setID func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetRoundAndSetID() (uint64, uint64) { - round, setID, _ := ca.GetHighestRoundAndSetID() // TODO check this is correct + round, setID, _ := ca.GetHighestRoundAndSetID() return round, setID } @@ -543,6 +543,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoreTrie(rtstorage.TrieState, } // GetStateRootFromBlock returns the state root of the block with the given hash. +// Uses the best block hash when called with `nil`. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { var hash H @@ -739,7 +740,10 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCodeHash(hash *common.Hash return common.Hash{}, err } - return common.Blake2bHash(code) + hasher := *new(Hasher) + codeHash := hasher.NewHash(code) + + return common.NewHashFromGeneric(codeHash), nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) RegisterStorageObserver(o state.Observer) { From 80028fa6908fc8699af4baf93d2722e6b90870ca Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Wed, 18 Jun 2025 20:51:52 +0700 Subject: [PATCH 06/23] correctly set IterArgs.StartAtExclusive --- internal/client/adapter/client_adapter.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index ede314349c..bb946a4908 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -797,7 +797,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( return stateAt.Keys(statemachine.IterArgs{ Prefix: prefix, StartAt: startKey, - StartAtExclusive: false, // TODO: check that this is correct + StartAtExclusive: true, }) } @@ -814,7 +814,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( return stateAt.Pairs(statemachine.IterArgs{ Prefix: prefix, StartAt: startKey, - StartAtExclusive: false, // TODO: check that this is correct + StartAtExclusive: true, }) } @@ -845,7 +845,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( return stateAt.Keys(statemachine.IterArgs{ Prefix: prefix, StartAt: startKey, - StartAtExclusive: false, // TODO: check that this is correct + StartAtExclusive: true, ChildInfo: childInfo, }) } From c3e7a71736ca786020570d36cd598745c240c511 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Fri, 20 Jun 2025 13:39:43 +0700 Subject: [PATCH 07/23] use updated TrieLayout types/API --- internal/client/adapter/client_adapter_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index d9e3a50727..01c799fb3e 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -1052,16 +1052,14 @@ func Test_GetStorageFromChild_GetStorageChild(t *testing.T) { mdb := trie.NewPrefixedMemoryDB[Hash, Hasher]() ksdb := trie.NewKeyspacedDB(mdb, childInfo.Keyspace()) - childTrie := triedb.NewEmptyTrieDB[Hash, Hasher](ksdb) - childTrie.SetVersion(storage.DefaultStateVersion.TrieLayout()) + childTrie := triedb.NewEmptyTrieDB[Hash, Hasher](ksdb, trie.LayoutV1[Hasher, Hash]{}) require.NoError(t, childTrie.Set([]byte("key"), []byte("value"))) require.NoError(t, childTrie.Set([]byte("anotherkey"), []byte("anothervalue"))) - parentTrie := triedb.NewEmptyTrieDB[Hash, Hasher](mdb) + parentTrie := triedb.NewEmptyTrieDB[Hash, Hasher](mdb, trie.LayoutV1[Hasher, Hash]{}) require.NoError(t, parentTrie.Set(childInfo.PrefixedStorageKey(), childTrie.MustHash().Bytes())) require.NoError(t, parentTrie.Set([]byte("key"), []byte("value2"))) require.NoError(t, parentTrie.Set([]byte(":code"), []byte("return 42"))) - parentTrie.SetVersion(storage.DefaultStateVersion.TrieLayout()) header := header.Clone().(Header) header.SetStateRoot(parentTrie.MustHash()) From 2cd321d87f492ed6c9fdc1f24c049181433a4076 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Fri, 20 Jun 2025 14:11:56 +0700 Subject: [PATCH 08/23] use storage.StorageKey instead of statemachine.StorageKey in StorageProvider --- internal/client/adapter/client_adapter.go | 32 ++++++++++++----------- internal/client/api/backend.go | 22 ++++++++-------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index bb946a4908..7d8bb38de2 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -762,19 +762,20 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetBlockTree(blocktree *blockt func (ca *ClientAdapter[H, Hasher, N, E, Header]) Storage( hash H, - key statemachine.StorageKey, -) (statemachine.StorageValue, error) { + key storage.StorageKey, +) (storage.StorageData, error) { stateAt, err := ca.client.StateAt(hash) if err != nil { return nil, err } - return stateAt.Storage(key) + data, err := stateAt.Storage(key) + return storage.StorageData(data), err } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageHash( hash H, - key statemachine.StorageKey, + key storage.StorageKey, ) (*H, error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -787,7 +788,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageHash( func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( hash H, prefix, - startKey statemachine.StorageKey, + startKey storage.StorageKey, ) (statemachine.KeysIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -804,7 +805,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( hash H, prefix, - startKey statemachine.StorageKey, + startKey storage.StorageKey, ) (statemachine.PairsIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -821,21 +822,22 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorage( hash H, childInfo storage.ChildInfo, - key statemachine.StorageKey, -) (statemachine.StorageValue, error) { + key storage.StorageKey, +) (storage.StorageData, error) { stateAt, err := ca.client.StateAt(hash) if err != nil { - return statemachine.StorageValue{}, err + return storage.StorageData{}, err } - return stateAt.ChildStorage(childInfo, key) + data, err := stateAt.ChildStorage(childInfo, key) + return storage.StorageData(data), err } func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( hash H, childInfo storage.ChildInfo, - prefix statemachine.StorageKey, - startKey statemachine.StorageKey, + prefix storage.StorageKey, + startKey storage.StorageKey, ) (statemachine.KeysIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -853,7 +855,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageHash( hash H, childInfo storage.ChildInfo, - key statemachine.StorageKey, + key storage.StorageKey, ) (*H, error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -866,7 +868,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageHash( // ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. func (ca *ClientAdapter[H, Hasher, N, E, Header]) ClosestMerkleValue( hash H, - key statemachine.StorageKey, + key storage.StorageKey, ) (triedb.MerkleValue[H], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { @@ -880,7 +882,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) ClosestMerkleValue( func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildClosestMerkleValue( hash H, childInfo storage.ChildInfo, - key statemachine.StorageKey, + key storage.StorageKey, ) (triedb.MerkleValue[H], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index e98aeb84df..217d31c61f 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -355,47 +355,47 @@ type Backend[ // StorageProvider provides access to storage primitives type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { // Storage returns the value under the key in that block, given a blocks hash and a key. - Storage(hash H, key statemachine.StorageKey) (statemachine.StorageValue, error) + Storage(hash H, key storage.StorageKey) (storage.StorageData, error) // StorageHash returns the value under the hash in that block, given a blocks hash and a key. - StorageHash(hash H, key statemachine.StorageKey) (*H, error) + StorageHash(hash H, key storage.StorageKey) (*H, error) // StorageKeys returns a [statemachine.KeysIter] that iterates over matching storage keys in that block // given a blocks hash and a key prefix. - StorageKeys(hash H, prefix, startKey statemachine.StorageKey) (statemachine.KeysIter[H, Hasher], error) + StorageKeys(hash H, prefix, startKey storage.StorageKey) (statemachine.KeysIter[H, Hasher], error) // StoragePairs returns an iterator over the storage keys and values in that block, // given the blocks hash and a key prefix. - StoragePairs(hash H, prefix, startKey statemachine.StorageKey) (statemachine.PairsIter[H, Hasher], error) + StoragePairs(hash H, prefix, startKey storage.StorageKey) (statemachine.PairsIter[H, Hasher], error) // ChildStorage returns the value under the key in that block, given a blocks hash, // a key and a child storage key. ChildStorage( hash H, childInfo storage.ChildInfo, - key statemachine.StorageKey, - ) (statemachine.StorageValue, error) + key storage.StorageKey, + ) (storage.StorageData, error) // ChildStorageKeys returns a [statemachine.KeysIter] that iterates matching storage keys in that block, // given a blocks hash, an optional key prefix and an optional child storage key. ChildStorageKeys( hash H, childInfo storage.ChildInfo, - prefix statemachine.StorageKey, - startKey statemachine.StorageKey, + prefix storage.StorageKey, + startKey storage.StorageKey, ) (statemachine.KeysIter[H, Hasher], error) // ChildStorageHash returns the hash under the key in a block, given its hash, // a key and a child storage key. - ChildStorageHash(hash H, childInfo storage.ChildInfo, key statemachine.StorageKey) (*H, error) + ChildStorageHash(hash H, childInfo storage.ChildInfo, key storage.StorageKey) (*H, error) // ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. - ClosestMerkleValue(hash H, key statemachine.StorageKey) (triedb.MerkleValue[H], error) + ClosestMerkleValue(hash H, key storage.StorageKey) (triedb.MerkleValue[H], error) // ChildClosestMerkleValue returns the closest merkle value, given a blocks hash, a key and a child storage key. ChildClosestMerkleValue( hash H, childInfo storage.ChildInfo, - key statemachine.StorageKey, + key storage.StorageKey, ) (triedb.MerkleValue[H], error) } From 37dd38d6340348582553d65235baaba0318e6c9a Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Fri, 20 Jun 2025 15:39:44 +0700 Subject: [PATCH 09/23] use local KeysIter/PairsIter in StorageProvider --- internal/client/adapter/client_adapter.go | 68 ++++--- .../client/adapter/client_adapter_test.go | 5 + internal/client/api/backend.go | 186 +++++++++++++++++- 3 files changed, 232 insertions(+), 27 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 7d8bb38de2..74a60ffd93 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -12,6 +12,7 @@ import ( "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/internal/client/api" "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/runtime" @@ -789,34 +790,50 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( hash H, prefix, startKey storage.StorageKey, -) (statemachine.KeysIter[H, Hasher], error) { +) (api.KeysIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { - return statemachine.KeysIter[H, Hasher]{}, err + return api.KeysIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.KeysIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewKeysIter(backend, &prefix, &startKey) + if err != nil { + return api.KeysIter[H, Hasher]{}, err } - return stateAt.Keys(statemachine.IterArgs{ - Prefix: prefix, - StartAt: startKey, - StartAtExclusive: true, - }) + return *iter, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( hash H, prefix, startKey storage.StorageKey, -) (statemachine.PairsIter[H, Hasher], error) { +) (api.PairsIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { - return statemachine.PairsIter[H, Hasher]{}, err + return api.PairsIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.PairsIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewPairsIter(backend, &prefix, &startKey) + if err != nil { + return api.PairsIter[H, Hasher]{}, err } - return stateAt.Pairs(statemachine.IterArgs{ - Prefix: prefix, - StartAt: startKey, - StartAtExclusive: true, - }) + return *iter, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorage( @@ -838,18 +855,25 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey, -) (statemachine.KeysIter[H, Hasher], error) { +) (api.KeysIter[H, Hasher], error) { stateAt, err := ca.client.StateAt(hash) if err != nil { - return statemachine.KeysIter[H, Hasher]{}, err + return api.KeysIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.KeysIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewChildKeysIter(backend, childInfo, &prefix, &startKey) + if err != nil { + return api.KeysIter[H, Hasher]{}, err } - return stateAt.Keys(statemachine.IterArgs{ - Prefix: prefix, - StartAt: startKey, - StartAtExclusive: true, - ChildInfo: childInfo, - }) + return *iter, nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageHash( diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index 01c799fb3e..c8edb75034 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -11,6 +11,7 @@ import ( "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/client/adapter/mocks" + "github.com/ChainSafe/gossamer/internal/client/api" "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/core/hash" @@ -59,6 +60,10 @@ var blockchainInfo = blockchain.Info[Hash, Number]{ FinalizedNumber: blockNumber, } +func TestStorageProviderImplemented(t *testing.T) { + var _ api.StorageProvider[Hash, Hasher] = &ClientAdapter[Hash, Hasher, Number, Extrinsic, Header]{} +} + func TestBlockStateImplemented(t *testing.T) { var _ state.BlockState = &ClientAdapter[Hash, Hasher, Number, Extrinsic, Header]{} } diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index 217d31c61f..e3465989b4 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -4,6 +4,7 @@ package api import ( + "iter" "sync" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" @@ -352,6 +353,181 @@ type Backend[ // UsageInfo() *UsageInfo } +// KeysIter is an iterator over storage keys. +type KeysIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { + backend *statemachine.TrieBackend[H, Hasher] + rawIter statemachine.StorageIterator[H, Hasher] +} + +func NewKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *statemachine.TrieBackend[H, Hasher], + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*KeysIter[H, Hasher], error) { + args := statemachine.IterArgs{ + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &KeysIter[H, Hasher]{backend, rawIter}, nil +} + +func NewChildKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *statemachine.TrieBackend[H, Hasher], + childInfo storage.ChildInfo, + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*KeysIter[H, Hasher], error) { + args := statemachine.IterArgs{ + ChildInfo: childInfo, + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &KeysIter[H, Hasher]{backend, rawIter}, nil +} + +func (ki *KeysIter[H, Hasher]) Next() (storage.StorageKey, error) { + key, err := ki.rawIter.NextKey(ki.backend) + return storage.StorageKey(key), err +} + +func (ki *KeysIter[H, Hasher]) All() iter.Seq2[storage.StorageKey, error] { + return func(yield func(storage.StorageKey, error) bool) { + for { + item, err := ki.Next() + if err != nil { + return + } + if item == nil { + return + } + if !yield(item, err) { + return + } + } + } +} + +// StorageKeyData is a storage key/value pair. +type StorageKeyData struct { + storage.StorageKey + storage.StorageData +} + +// PairsIter is an iterator over storage key/value pairs. +type PairsIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { + backend *statemachine.TrieBackend[H, Hasher] + rawIter statemachine.StorageIterator[H, Hasher] +} + +func NewPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *statemachine.TrieBackend[H, Hasher], + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*PairsIter[H, Hasher], error) { + args := statemachine.IterArgs{ + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &PairsIter[H, Hasher]{backend, rawIter}, nil +} + +func NewChildPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *statemachine.TrieBackend[H, Hasher], + childInfo storage.ChildInfo, + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*PairsIter[H, Hasher], error) { + args := statemachine.IterArgs{ + ChildInfo: childInfo, + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &PairsIter[H, Hasher]{backend, rawIter}, nil +} + +func (ki *PairsIter[H, Hasher]) Next() (*StorageKeyData, error) { + keyValue, err := ki.rawIter.NextKeyValue(ki.backend) + if err != nil { + return nil, err + } + + data := StorageKeyData{ + StorageKey: storage.StorageKey(keyValue.StorageKey), + StorageData: storage.StorageData(keyValue.StorageValue), + } + + return &data, nil +} + +func (ki *PairsIter[H, Hasher]) All() iter.Seq2[StorageKeyData, error] { + return func(yield func(StorageKeyData, error) bool) { + for { + item, err := ki.Next() + if err != nil { + return + } + if item == nil { + return + } + if !yield(*item, err) { + return + } + } + } +} + // StorageProvider provides access to storage primitives type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { // Storage returns the value under the key in that block, given a blocks hash and a key. @@ -360,13 +536,13 @@ type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { // StorageHash returns the value under the hash in that block, given a blocks hash and a key. StorageHash(hash H, key storage.StorageKey) (*H, error) - // StorageKeys returns a [statemachine.KeysIter] that iterates over matching storage keys in that block + // StorageKeys returns a [KeysIter] that iterates over matching storage keys in that block // given a blocks hash and a key prefix. - StorageKeys(hash H, prefix, startKey storage.StorageKey) (statemachine.KeysIter[H, Hasher], error) + StorageKeys(hash H, prefix, startKey storage.StorageKey) (KeysIter[H, Hasher], error) // StoragePairs returns an iterator over the storage keys and values in that block, // given the blocks hash and a key prefix. - StoragePairs(hash H, prefix, startKey storage.StorageKey) (statemachine.PairsIter[H, Hasher], error) + StoragePairs(hash H, prefix, startKey storage.StorageKey) (PairsIter[H, Hasher], error) // ChildStorage returns the value under the key in that block, given a blocks hash, // a key and a child storage key. @@ -376,14 +552,14 @@ type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { key storage.StorageKey, ) (storage.StorageData, error) - // ChildStorageKeys returns a [statemachine.KeysIter] that iterates matching storage keys in that block, + // ChildStorageKeys returns a [KeysIter] that iterates matching storage keys in that block, // given a blocks hash, an optional key prefix and an optional child storage key. ChildStorageKeys( hash H, childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey, - ) (statemachine.KeysIter[H, Hasher], error) + ) (KeysIter[H, Hasher], error) // ChildStorageHash returns the hash under the key in a block, given its hash, // a key and a child storage key. From 2b5ef15b556ab4258f20f559e49656b0572dfc30 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Fri, 20 Jun 2025 15:54:23 +0700 Subject: [PATCH 10/23] remove unused methods from BlockState and ClientAdapter --- dot/state/block.go | 2 -- internal/client/adapter/client_adapter.go | 30 ----------------------- 2 files changed, 32 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index bd91f09c32..c8d4033405 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -75,7 +75,6 @@ type BlockState interface { GetReceipt(hash common.Hash) ([]byte, error) GetMessageQueue(hash common.Hash) ([]byte, error) GetTries() *Tries - GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) GetAllBlocksAtNumber(num uint) ([]common.Hash, error) GetNonFinalisedBlocks() []common.Hash @@ -93,7 +92,6 @@ type BlockState interface { SetHeader(header *types.Header) error SetJustification(hash common.Hash, data []byte) error SetHighestRoundAndSetID(round, setID uint64) error - GetRoundAndSetID() (uint64, uint64) GetRuntime(blockHash common.Hash) (instance runtime.Instance, err error) UnregisterRuntimeUpdatedChannel(id uint32) bool diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 74a60ffd93..f9d060c892 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -325,30 +325,6 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetTries() *state.Tries { panic("unimplemented") } -// GetBlockHashesBySlot gets all block hashes that were produced in the given slot. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - children, err := ca.client.Children(ca.client.Info().FinalizedHash) - if err != nil { - return nil, err - } - - var blockHashes []common.Hash - for _, child := range children { - hash := common.NewHashFromGeneric(child) - - slot, err := ca.GetSlotForBlock(hash) - if err != nil { - return nil, fmt.Errorf("getting slot for block %s: %w", child.String(), err) - } - - if slot == slotNum { - blockHashes = append(blockHashes, hash) - } - } - - return blockHashes, nil -} - // GetAllBlocksAtNumber returns all unfinalised blocks with the given number func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetAllBlocksAtNumber(num uint) ([]common.Hash, error) { return ca.GetHashesByNumber(num) @@ -444,12 +420,6 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetHighestRoundAndSetID(round, panic("unimplemented") } -// GetRoundAndSetID returns the finalised round and setID -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetRoundAndSetID() (uint64, uint64) { - round, setID, _ := ca.GetHighestRoundAndSetID() - return round, setID -} - func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetRuntime(blockHash common.Hash) (instance rt.Instance, err error) { panic("unimplemented") } From ec5f7d05b35e2d969138dcc6cf8aa8552a2495e1 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Fri, 20 Jun 2025 16:57:02 +0700 Subject: [PATCH 11/23] move StorageProvider impl from ClientAdapter to Client --- internal/client/adapter/client_adapter.go | 161 +----- .../client/adapter/client_adapter_test.go | 43 +- internal/client/adapter/mocks/client.go | 538 ++++++++++++++++++ .../adapter/mocks/statemachine_backend.go | 57 +- internal/client/client.go | 162 ++++++ internal/client/client_test.go | 1 + 6 files changed, 761 insertions(+), 201 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index f9d060c892..a453299d81 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -25,7 +25,6 @@ import ( "github.com/ChainSafe/gossamer/pkg/trie" "github.com/ChainSafe/gossamer/pkg/trie/db" "github.com/ChainSafe/gossamer/pkg/trie/inmemory" - "github.com/ChainSafe/gossamer/pkg/trie/triedb" ) type ClientAdapterDB interface { @@ -43,6 +42,7 @@ type Client[ blockchain.HeaderBackend[H, N, Header] blockchain.BlockBackend[H, N, Header, Hasher, E] blockchain.Backend[H, N, Header, E] + api.StorageProvider[H, Hasher] CompareAndSetBlockData(bd *types.BlockData) error StateAt(hash H) (statemachine.Backend[H, Hasher], error) @@ -595,7 +595,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageByBlockHash(bhash *c hash = hasher.NewHash(bhash.ToBytes()) } - return ca.Storage(hash, key) + return ca.client.Storage(hash, key) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageRoot() (common.Hash, error) { @@ -729,163 +729,6 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetBlockTree(blocktree *blockt panic("unimplemented") } -// StorageProvider impl - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) Storage( - hash H, - key storage.StorageKey, -) (storage.StorageData, error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return nil, err - } - - data, err := stateAt.Storage(key) - return storage.StorageData(data), err -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageHash( - hash H, - key storage.StorageKey, -) (*H, error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return nil, err - } - - return stateAt.StorageHash(key) -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageKeys( - hash H, - prefix, - startKey storage.StorageKey, -) (api.KeysIter[H, Hasher], error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return api.KeysIter[H, Hasher]{}, err - } - backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) - if !ok { - return api.KeysIter[H, Hasher]{}, fmt.Errorf( - "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", - backend, - ) - } - - iter, err := api.NewKeysIter(backend, &prefix, &startKey) - if err != nil { - return api.KeysIter[H, Hasher]{}, err - } - - return *iter, nil -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoragePairs( - hash H, - prefix, - startKey storage.StorageKey, -) (api.PairsIter[H, Hasher], error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return api.PairsIter[H, Hasher]{}, err - } - backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) - if !ok { - return api.PairsIter[H, Hasher]{}, fmt.Errorf( - "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", - backend, - ) - } - - iter, err := api.NewPairsIter(backend, &prefix, &startKey) - if err != nil { - return api.PairsIter[H, Hasher]{}, err - } - - return *iter, nil -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorage( - hash H, - childInfo storage.ChildInfo, - key storage.StorageKey, -) (storage.StorageData, error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return storage.StorageData{}, err - } - - data, err := stateAt.ChildStorage(childInfo, key) - return storage.StorageData(data), err -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageKeys( - hash H, - childInfo storage.ChildInfo, - prefix storage.StorageKey, - startKey storage.StorageKey, -) (api.KeysIter[H, Hasher], error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return api.KeysIter[H, Hasher]{}, err - } - backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) - if !ok { - return api.KeysIter[H, Hasher]{}, fmt.Errorf( - "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", - backend, - ) - } - - iter, err := api.NewChildKeysIter(backend, childInfo, &prefix, &startKey) - if err != nil { - return api.KeysIter[H, Hasher]{}, err - } - - return *iter, nil -} - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildStorageHash( - hash H, - childInfo storage.ChildInfo, - key storage.StorageKey, -) (*H, error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return nil, err - } - - return stateAt.ChildStorageHash(childInfo, key) -} - -// ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) ClosestMerkleValue( - hash H, - key storage.StorageKey, -) (triedb.MerkleValue[H], error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return triedb.NodeMerkleValue{}, err - } - - return stateAt.ClosestMerkleValue(key) -} - -// ChildClosestMerkleValue returns the closest merkle value, given a blocks hash, a key and a child storage key. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) ChildClosestMerkleValue( - hash H, - childInfo storage.ChildInfo, - key storage.StorageKey, -) (triedb.MerkleValue[H], error) { - stateAt, err := ca.client.StateAt(hash) - if err != nil { - return triedb.NodeMerkleValue{}, err - } - - return stateAt.ChildClosestMerkleValue(childInfo, key) -} - func prefixKey(hash common.Hash, prefix []byte) []byte { return append(prefix, hash.ToBytes()...) } diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index c8edb75034..b63f9b7502 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -11,7 +11,6 @@ import ( "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/client/adapter/mocks" - "github.com/ChainSafe/gossamer/internal/client/api" "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" "github.com/ChainSafe/gossamer/internal/primitives/core/hash" @@ -60,10 +59,6 @@ var blockchainInfo = blockchain.Info[Hash, Number]{ FinalizedNumber: blockNumber, } -func TestStorageProviderImplemented(t *testing.T) { - var _ api.StorageProvider[Hash, Hasher] = &ClientAdapter[Hash, Hasher, Number, Extrinsic, Header]{} -} - func TestBlockStateImplemented(t *testing.T) { var _ state.BlockState = &ClientAdapter[Hash, Hasher, Number, Extrinsic, Header]{} } @@ -915,7 +910,16 @@ func TestGetStorageByBlockHash(t *testing.T) { client, _, adapter := setupTest(t) expectedError := errors.New("kaput") - client.EXPECT().StateAt(blockchainInfo.FinalizedHash).Return(nil, expectedError) + + client.EXPECT(). + Storage( + blockchainInfo.FinalizedHash, + storage.StorageKey("key"), + ). + Return( + nil, + expectedError, + ) bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) @@ -926,24 +930,35 @@ func TestGetStorageByBlockHash(t *testing.T) { t.Run("ok", func(t *testing.T) { client, _, adapter := setupTest(t) - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) - - client.EXPECT().StateAt(blockchainInfo.FinalizedHash).Return(backend, nil) + client.EXPECT(). + Storage( + blockchainInfo.FinalizedHash, + storage.StorageKey("key"), + ). + Return( + storage.StorageData("value"), + nil, + ) bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) - value, err := adapter.GetStorageByBlockHash(&bhash, []byte("key")) + value, err := adapter.GetStorageByBlockHash(&bhash, storage.StorageKey("key")) require.NoError(t, err) require.Equal(t, []byte("value"), value) }) t.Run("bhash_nil", func(t *testing.T) { client, _, adapter := setupTest(t) - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) + client.EXPECT(). + Storage( + blockchainInfo.BestHash, + storage.StorageKey("key"), + ). + Return( + storage.StorageData("value"), + nil, + ) - client.EXPECT().StateAt(blockchainInfo.BestHash).Return(backend, nil) client.EXPECT().Info().Return(blockchainInfo) value, err := adapter.GetStorageByBlockHash(nil, []byte("key")) diff --git a/internal/client/adapter/mocks/client.go b/internal/client/adapter/mocks/client.go index 9782d78746..a8ac354067 100644 --- a/internal/client/adapter/mocks/client.go +++ b/internal/client/adapter/mocks/client.go @@ -3,7 +3,9 @@ package mocks import ( + api "github.com/ChainSafe/gossamer/internal/client/api" blockchain "github.com/ChainSafe/gossamer/internal/primitives/blockchain" + common "github.com/ChainSafe/gossamer/internal/primitives/consensus/common" generic "github.com/ChainSafe/gossamer/internal/primitives/runtime/generic" @@ -14,8 +16,12 @@ import ( statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" + storage "github.com/ChainSafe/gossamer/internal/primitives/storage" + sync "sync" + triedb "github.com/ChainSafe/gossamer/pkg/trie/triedb" + types "github.com/ChainSafe/gossamer/dot/types" ) @@ -494,6 +500,245 @@ func (_c *Client_Body_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H) ([ return _c } +// ChildClosestMerkleValue provides a mock function with given fields: hash, childInfo, key +func (_m *Client[H, Hasher, N, E, Header]) ChildClosestMerkleValue(hash H, childInfo storage.ChildInfo, key storage.StorageKey) (triedb.MerkleValue[H], error) { + ret := _m.Called(hash, childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildClosestMerkleValue") + } + + var r0 triedb.MerkleValue[H] + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) (triedb.MerkleValue[H], error)); ok { + return rf(hash, childInfo, key) + } + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) triedb.MerkleValue[H]); ok { + r0 = rf(hash, childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(triedb.MerkleValue[H]) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.ChildInfo, storage.StorageKey) error); ok { + r1 = rf(hash, childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ChildClosestMerkleValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildClosestMerkleValue' +type Client_ChildClosestMerkleValue_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// ChildClosestMerkleValue is a helper method to define mock.On call +// - hash H +// - childInfo storage.ChildInfo +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) ChildClosestMerkleValue(hash interface{}, childInfo interface{}, key interface{}) *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header] { + return &Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("ChildClosestMerkleValue", hash, childInfo, key)} +} + +func (_c *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header]) Run(run func(hash H, childInfo storage.ChildInfo, key storage.StorageKey)) *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.ChildInfo), args[2].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header]) Return(_a0 triedb.MerkleValue[H], _a1 error) *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey) (triedb.MerkleValue[H], error)) *Client_ChildClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// ChildStorage provides a mock function with given fields: hash, childInfo, key +func (_m *Client[H, Hasher, N, E, Header]) ChildStorage(hash H, childInfo storage.ChildInfo, key storage.StorageKey) (storage.StorageData, error) { + ret := _m.Called(hash, childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildStorage") + } + + var r0 storage.StorageData + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) (storage.StorageData, error)); ok { + return rf(hash, childInfo, key) + } + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) storage.StorageData); ok { + r0 = rf(hash, childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(storage.StorageData) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.ChildInfo, storage.StorageKey) error); ok { + r1 = rf(hash, childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ChildStorage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorage' +type Client_ChildStorage_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// ChildStorage is a helper method to define mock.On call +// - hash H +// - childInfo storage.ChildInfo +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) ChildStorage(hash interface{}, childInfo interface{}, key interface{}) *Client_ChildStorage_Call[H, Hasher, N, E, Header] { + return &Client_ChildStorage_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("ChildStorage", hash, childInfo, key)} +} + +func (_c *Client_ChildStorage_Call[H, Hasher, N, E, Header]) Run(run func(hash H, childInfo storage.ChildInfo, key storage.StorageKey)) *Client_ChildStorage_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.ChildInfo), args[2].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_ChildStorage_Call[H, Hasher, N, E, Header]) Return(_a0 storage.StorageData, _a1 error) *Client_ChildStorage_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ChildStorage_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey) (storage.StorageData, error)) *Client_ChildStorage_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// ChildStorageHash provides a mock function with given fields: hash, childInfo, key +func (_m *Client[H, Hasher, N, E, Header]) ChildStorageHash(hash H, childInfo storage.ChildInfo, key storage.StorageKey) (*H, error) { + ret := _m.Called(hash, childInfo, key) + + if len(ret) == 0 { + panic("no return value specified for ChildStorageHash") + } + + var r0 *H + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) (*H, error)); ok { + return rf(hash, childInfo, key) + } + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey) *H); ok { + r0 = rf(hash, childInfo, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*H) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.ChildInfo, storage.StorageKey) error); ok { + r1 = rf(hash, childInfo, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ChildStorageHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorageHash' +type Client_ChildStorageHash_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// ChildStorageHash is a helper method to define mock.On call +// - hash H +// - childInfo storage.ChildInfo +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) ChildStorageHash(hash interface{}, childInfo interface{}, key interface{}) *Client_ChildStorageHash_Call[H, Hasher, N, E, Header] { + return &Client_ChildStorageHash_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("ChildStorageHash", hash, childInfo, key)} +} + +func (_c *Client_ChildStorageHash_Call[H, Hasher, N, E, Header]) Run(run func(hash H, childInfo storage.ChildInfo, key storage.StorageKey)) *Client_ChildStorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.ChildInfo), args[2].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_ChildStorageHash_Call[H, Hasher, N, E, Header]) Return(_a0 *H, _a1 error) *Client_ChildStorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ChildStorageHash_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey) (*H, error)) *Client_ChildStorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// ChildStorageKeys provides a mock function with given fields: hash, childInfo, prefix, startKey +func (_m *Client[H, Hasher, N, E, Header]) ChildStorageKeys(hash H, childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey) (api.KeysIter[H, Hasher], error) { + ret := _m.Called(hash, childInfo, prefix, startKey) + + if len(ret) == 0 { + panic("no return value specified for ChildStorageKeys") + } + + var r0 api.KeysIter[H, Hasher] + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)); ok { + return rf(hash, childInfo, prefix, startKey) + } + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) api.KeysIter[H, Hasher]); ok { + r0 = rf(hash, childInfo, prefix, startKey) + } else { + r0 = ret.Get(0).(api.KeysIter[H, Hasher]) + } + + if rf, ok := ret.Get(1).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) error); ok { + r1 = rf(hash, childInfo, prefix, startKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ChildStorageKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChildStorageKeys' +type Client_ChildStorageKeys_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// ChildStorageKeys is a helper method to define mock.On call +// - hash H +// - childInfo storage.ChildInfo +// - prefix storage.StorageKey +// - startKey storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) ChildStorageKeys(hash interface{}, childInfo interface{}, prefix interface{}, startKey interface{}) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { + return &Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("ChildStorageKeys", hash, childInfo, prefix, startKey)} +} + +func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) Run(run func(hash H, childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey)) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.ChildInfo), args[2].(storage.StorageKey), args[3].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 api.KeysIter[H, Hasher], _a1 error) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + // Children provides a mock function with given fields: parentHash func (_m *Client[H, Hasher, N, E, Header]) Children(parentHash H) ([]H, error) { ret := _m.Called(parentHash) @@ -552,6 +797,65 @@ func (_c *Client_Children_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H return _c } +// ClosestMerkleValue provides a mock function with given fields: hash, key +func (_m *Client[H, Hasher, N, E, Header]) ClosestMerkleValue(hash H, key storage.StorageKey) (triedb.MerkleValue[H], error) { + ret := _m.Called(hash, key) + + if len(ret) == 0 { + panic("no return value specified for ClosestMerkleValue") + } + + var r0 triedb.MerkleValue[H] + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) (triedb.MerkleValue[H], error)); ok { + return rf(hash, key) + } + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) triedb.MerkleValue[H]); ok { + r0 = rf(hash, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(triedb.MerkleValue[H]) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.StorageKey) error); ok { + r1 = rf(hash, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ClosestMerkleValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClosestMerkleValue' +type Client_ClosestMerkleValue_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// ClosestMerkleValue is a helper method to define mock.On call +// - hash H +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) ClosestMerkleValue(hash interface{}, key interface{}) *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header] { + return &Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("ClosestMerkleValue", hash, key)} +} + +func (_c *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header]) Run(run func(hash H, key storage.StorageKey)) *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header]) Return(_a0 triedb.MerkleValue[H], _a1 error) *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey) (triedb.MerkleValue[H], error)) *Client_ClosestMerkleValue_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + // CompareAndSetBlockData provides a mock function with given fields: bd func (_m *Client[H, Hasher, N, E, Header]) CompareAndSetBlockData(bd *types.BlockData) error { ret := _m.Called(bd) @@ -1501,6 +1805,240 @@ func (_c *Client_Status_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H) return _c } +// Storage provides a mock function with given fields: hash, key +func (_m *Client[H, Hasher, N, E, Header]) Storage(hash H, key storage.StorageKey) (storage.StorageData, error) { + ret := _m.Called(hash, key) + + if len(ret) == 0 { + panic("no return value specified for Storage") + } + + var r0 storage.StorageData + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) (storage.StorageData, error)); ok { + return rf(hash, key) + } + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) storage.StorageData); ok { + r0 = rf(hash, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(storage.StorageData) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.StorageKey) error); ok { + r1 = rf(hash, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_Storage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Storage' +type Client_Storage_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// Storage is a helper method to define mock.On call +// - hash H +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) Storage(hash interface{}, key interface{}) *Client_Storage_Call[H, Hasher, N, E, Header] { + return &Client_Storage_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("Storage", hash, key)} +} + +func (_c *Client_Storage_Call[H, Hasher, N, E, Header]) Run(run func(hash H, key storage.StorageKey)) *Client_Storage_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_Storage_Call[H, Hasher, N, E, Header]) Return(_a0 storage.StorageData, _a1 error) *Client_Storage_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_Storage_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey) (storage.StorageData, error)) *Client_Storage_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// StorageHash provides a mock function with given fields: hash, key +func (_m *Client[H, Hasher, N, E, Header]) StorageHash(hash H, key storage.StorageKey) (*H, error) { + ret := _m.Called(hash, key) + + if len(ret) == 0 { + panic("no return value specified for StorageHash") + } + + var r0 *H + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) (*H, error)); ok { + return rf(hash, key) + } + if rf, ok := ret.Get(0).(func(H, storage.StorageKey) *H); ok { + r0 = rf(hash, key) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*H) + } + } + + if rf, ok := ret.Get(1).(func(H, storage.StorageKey) error); ok { + r1 = rf(hash, key) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_StorageHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StorageHash' +type Client_StorageHash_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// StorageHash is a helper method to define mock.On call +// - hash H +// - key storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) StorageHash(hash interface{}, key interface{}) *Client_StorageHash_Call[H, Hasher, N, E, Header] { + return &Client_StorageHash_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("StorageHash", hash, key)} +} + +func (_c *Client_StorageHash_Call[H, Hasher, N, E, Header]) Run(run func(hash H, key storage.StorageKey)) *Client_StorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_StorageHash_Call[H, Hasher, N, E, Header]) Return(_a0 *H, _a1 error) *Client_StorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_StorageHash_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey) (*H, error)) *Client_StorageHash_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// StorageKeys provides a mock function with given fields: hash, prefix, startKey +func (_m *Client[H, Hasher, N, E, Header]) StorageKeys(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (api.KeysIter[H, Hasher], error) { + ret := _m.Called(hash, prefix, startKey) + + if len(ret) == 0 { + panic("no return value specified for StorageKeys") + } + + var r0 api.KeysIter[H, Hasher] + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)); ok { + return rf(hash, prefix, startKey) + } + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) api.KeysIter[H, Hasher]); ok { + r0 = rf(hash, prefix, startKey) + } else { + r0 = ret.Get(0).(api.KeysIter[H, Hasher]) + } + + if rf, ok := ret.Get(1).(func(H, storage.StorageKey, storage.StorageKey) error); ok { + r1 = rf(hash, prefix, startKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_StorageKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StorageKeys' +type Client_StorageKeys_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// StorageKeys is a helper method to define mock.On call +// - hash H +// - prefix storage.StorageKey +// - startKey storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) StorageKeys(hash interface{}, prefix interface{}, startKey interface{}) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { + return &Client_StorageKeys_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("StorageKeys", hash, prefix, startKey)} +} + +func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) Run(run func(hash H, prefix storage.StorageKey, startKey storage.StorageKey)) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.StorageKey), args[2].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 api.KeysIter[H, Hasher], _a1 error) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + +// StoragePairs provides a mock function with given fields: hash, prefix, startKey +func (_m *Client[H, Hasher, N, E, Header]) StoragePairs(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (api.PairsIter[H, Hasher], error) { + ret := _m.Called(hash, prefix, startKey) + + if len(ret) == 0 { + panic("no return value specified for StoragePairs") + } + + var r0 api.PairsIter[H, Hasher] + var r1 error + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (api.PairsIter[H, Hasher], error)); ok { + return rf(hash, prefix, startKey) + } + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) api.PairsIter[H, Hasher]); ok { + r0 = rf(hash, prefix, startKey) + } else { + r0 = ret.Get(0).(api.PairsIter[H, Hasher]) + } + + if rf, ok := ret.Get(1).(func(H, storage.StorageKey, storage.StorageKey) error); ok { + r1 = rf(hash, prefix, startKey) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_StoragePairs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StoragePairs' +type Client_StoragePairs_Call[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]] struct { + *mock.Call +} + +// StoragePairs is a helper method to define mock.On call +// - hash H +// - prefix storage.StorageKey +// - startKey storage.StorageKey +func (_e *Client_Expecter[H, Hasher, N, E, Header]) StoragePairs(hash interface{}, prefix interface{}, startKey interface{}) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { + return &Client_StoragePairs_Call[H, Hasher, N, E, Header]{Call: _e.mock.On("StoragePairs", hash, prefix, startKey)} +} + +func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) Run(run func(hash H, prefix storage.StorageKey, startKey storage.StorageKey)) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(H), args[1].(storage.StorageKey), args[2].(storage.StorageKey)) + }) + return _c +} + +func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) Return(_a0 api.PairsIter[H, Hasher], _a1 error) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (api.PairsIter[H, Hasher], error)) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { + _c.Call.Return(run) + return _c +} + // NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewClient[H runtime.Hash, Hasher runtime.Hasher[H], N runtime.Number, E runtime.Extrinsic, Header runtime.Header[N, H]](t interface { diff --git a/internal/client/adapter/mocks/statemachine_backend.go b/internal/client/adapter/mocks/statemachine_backend.go index 15dadc3ead..853394c6da 100644 --- a/internal/client/adapter/mocks/statemachine_backend.go +++ b/internal/client/adapter/mocks/statemachine_backend.go @@ -3,14 +3,15 @@ package mocks import ( + kv "github.com/ChainSafe/gossamer/internal/primitives/kv" + mock "github.com/stretchr/testify/mock" + runtime "github.com/ChainSafe/gossamer/internal/primitives/runtime" + statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" - mock "github.com/stretchr/testify/mock" storage "github.com/ChainSafe/gossamer/internal/primitives/storage" - trie "github.com/ChainSafe/gossamer/internal/primitives/trie" - triedb "github.com/ChainSafe/gossamer/pkg/trie/triedb" ) @@ -205,7 +206,7 @@ func (_c *StatemachineBackend_ChildStorageHash_Call[Hash, H]) RunAndReturn(run f } // ChildStorageRoot provides a mock function with given fields: childInfo, delta, stateVersion -func (_m *StatemachineBackend[Hash, H]) ChildStorageRoot(childInfo storage.ChildInfo, delta []trie.KeyValue, stateVersion storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H]) { +func (_m *StatemachineBackend[Hash, H]) ChildStorageRoot(childInfo storage.ChildInfo, delta []kv.KeyValue, stateVersion storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H]) { ret := _m.Called(childInfo, delta, stateVersion) if len(ret) == 0 { @@ -215,10 +216,10 @@ func (_m *StatemachineBackend[Hash, H]) ChildStorageRoot(childInfo storage.Child var r0 Hash var r1 bool var r2 statemachine.BackendTransaction[Hash, H] - if rf, ok := ret.Get(0).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])); ok { + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []kv.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])); ok { return rf(childInfo, delta, stateVersion) } - if rf, ok := ret.Get(0).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) Hash); ok { + if rf, ok := ret.Get(0).(func(storage.ChildInfo, []kv.KeyValue, storage.StateVersion) Hash); ok { r0 = rf(childInfo, delta, stateVersion) } else { if ret.Get(0) != nil { @@ -226,13 +227,13 @@ func (_m *StatemachineBackend[Hash, H]) ChildStorageRoot(childInfo storage.Child } } - if rf, ok := ret.Get(1).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) bool); ok { + if rf, ok := ret.Get(1).(func(storage.ChildInfo, []kv.KeyValue, storage.StateVersion) bool); ok { r1 = rf(childInfo, delta, stateVersion) } else { r1 = ret.Get(1).(bool) } - if rf, ok := ret.Get(2).(func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + if rf, ok := ret.Get(2).(func(storage.ChildInfo, []kv.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { r2 = rf(childInfo, delta, stateVersion) } else { r2 = ret.Get(2).(statemachine.BackendTransaction[Hash, H]) @@ -248,15 +249,15 @@ type StatemachineBackend_ChildStorageRoot_Call[Hash runtime.Hash, H runtime.Hash // ChildStorageRoot is a helper method to define mock.On call // - childInfo storage.ChildInfo -// - delta []trie.KeyValue +// - delta []kv.KeyValue // - stateVersion storage.StateVersion func (_e *StatemachineBackend_Expecter[Hash, H]) ChildStorageRoot(childInfo interface{}, delta interface{}, stateVersion interface{}) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { return &StatemachineBackend_ChildStorageRoot_Call[Hash, H]{Call: _e.mock.On("ChildStorageRoot", childInfo, delta, stateVersion)} } -func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, delta []trie.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) Run(run func(childInfo storage.ChildInfo, delta []kv.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(storage.ChildInfo), args[1].([]trie.KeyValue), args[2].(storage.StateVersion)) + run(args[0].(storage.ChildInfo), args[1].([]kv.KeyValue), args[2].(storage.StateVersion)) }) return _c } @@ -266,7 +267,7 @@ func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) Return(_a0 Hash, _ return _c } -func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []trie.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_ChildStorageRoot_Call[Hash, H]) RunAndReturn(run func(storage.ChildInfo, []kv.KeyValue, storage.StateVersion) (Hash, bool, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_ChildStorageRoot_Call[Hash, H] { _c.Call.Return(run) return _c } @@ -443,7 +444,7 @@ func (_c *StatemachineBackend_ExistsStorage_Call[Hash, H]) RunAndReturn(run func } // FullStorageRoot provides a mock function with given fields: delta, childDeltas, stateVersion -func (_m *StatemachineBackend[Hash, H]) FullStorageRoot(delta []trie.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { +func (_m *StatemachineBackend[Hash, H]) FullStorageRoot(delta []kv.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { ret := _m.Called(delta, childDeltas, stateVersion) if len(ret) == 0 { @@ -452,10 +453,10 @@ func (_m *StatemachineBackend[Hash, H]) FullStorageRoot(delta []trie.KeyValue, c var r0 Hash var r1 statemachine.BackendTransaction[Hash, H] - if rf, ok := ret.Get(0).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { + if rf, ok := ret.Get(0).(func([]kv.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { return rf(delta, childDeltas, stateVersion) } - if rf, ok := ret.Get(0).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) Hash); ok { + if rf, ok := ret.Get(0).(func([]kv.KeyValue, []statemachine.ChildDelta, storage.StateVersion) Hash); ok { r0 = rf(delta, childDeltas, stateVersion) } else { if ret.Get(0) != nil { @@ -463,7 +464,7 @@ func (_m *StatemachineBackend[Hash, H]) FullStorageRoot(delta []trie.KeyValue, c } } - if rf, ok := ret.Get(1).(func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + if rf, ok := ret.Get(1).(func([]kv.KeyValue, []statemachine.ChildDelta, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { r1 = rf(delta, childDeltas, stateVersion) } else { r1 = ret.Get(1).(statemachine.BackendTransaction[Hash, H]) @@ -478,16 +479,16 @@ type StatemachineBackend_FullStorageRoot_Call[Hash runtime.Hash, H runtime.Hashe } // FullStorageRoot is a helper method to define mock.On call -// - delta []trie.KeyValue +// - delta []kv.KeyValue // - childDeltas []statemachine.ChildDelta // - stateVersion storage.StateVersion func (_e *StatemachineBackend_Expecter[Hash, H]) FullStorageRoot(delta interface{}, childDeltas interface{}, stateVersion interface{}) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { return &StatemachineBackend_FullStorageRoot_Call[Hash, H]{Call: _e.mock.On("FullStorageRoot", delta, childDeltas, stateVersion)} } -func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) Run(run func(delta []trie.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion)) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) Run(run func(delta []kv.KeyValue, childDeltas []statemachine.ChildDelta, stateVersion storage.StateVersion)) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]trie.KeyValue), args[1].([]statemachine.ChildDelta), args[2].(storage.StateVersion)) + run(args[0].([]kv.KeyValue), args[1].([]statemachine.ChildDelta), args[2].(storage.StateVersion)) }) return _c } @@ -497,7 +498,7 @@ func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) Return(_a0 Hash, _a return _c } -func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) RunAndReturn(run func([]trie.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_FullStorageRoot_Call[Hash, H]) RunAndReturn(run func([]kv.KeyValue, []statemachine.ChildDelta, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_FullStorageRoot_Call[Hash, H] { _c.Call.Return(run) return _c } @@ -906,7 +907,7 @@ func (_c *StatemachineBackend_StorageHash_Call[Hash, H]) RunAndReturn(run func([ } // StorageRoot provides a mock function with given fields: delta, stateVersion -func (_m *StatemachineBackend[Hash, H]) StorageRoot(delta []trie.KeyValue, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { +func (_m *StatemachineBackend[Hash, H]) StorageRoot(delta []kv.KeyValue, stateVersion storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H]) { ret := _m.Called(delta, stateVersion) if len(ret) == 0 { @@ -915,10 +916,10 @@ func (_m *StatemachineBackend[Hash, H]) StorageRoot(delta []trie.KeyValue, state var r0 Hash var r1 statemachine.BackendTransaction[Hash, H] - if rf, ok := ret.Get(0).(func([]trie.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { + if rf, ok := ret.Get(0).(func([]kv.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])); ok { return rf(delta, stateVersion) } - if rf, ok := ret.Get(0).(func([]trie.KeyValue, storage.StateVersion) Hash); ok { + if rf, ok := ret.Get(0).(func([]kv.KeyValue, storage.StateVersion) Hash); ok { r0 = rf(delta, stateVersion) } else { if ret.Get(0) != nil { @@ -926,7 +927,7 @@ func (_m *StatemachineBackend[Hash, H]) StorageRoot(delta []trie.KeyValue, state } } - if rf, ok := ret.Get(1).(func([]trie.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { + if rf, ok := ret.Get(1).(func([]kv.KeyValue, storage.StateVersion) statemachine.BackendTransaction[Hash, H]); ok { r1 = rf(delta, stateVersion) } else { r1 = ret.Get(1).(statemachine.BackendTransaction[Hash, H]) @@ -941,15 +942,15 @@ type StatemachineBackend_StorageRoot_Call[Hash runtime.Hash, H runtime.Hasher[Ha } // StorageRoot is a helper method to define mock.On call -// - delta []trie.KeyValue +// - delta []kv.KeyValue // - stateVersion storage.StateVersion func (_e *StatemachineBackend_Expecter[Hash, H]) StorageRoot(delta interface{}, stateVersion interface{}) *StatemachineBackend_StorageRoot_Call[Hash, H] { return &StatemachineBackend_StorageRoot_Call[Hash, H]{Call: _e.mock.On("StorageRoot", delta, stateVersion)} } -func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) Run(run func(delta []trie.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_StorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) Run(run func(delta []kv.KeyValue, stateVersion storage.StateVersion)) *StatemachineBackend_StorageRoot_Call[Hash, H] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]trie.KeyValue), args[1].(storage.StateVersion)) + run(args[0].([]kv.KeyValue), args[1].(storage.StateVersion)) }) return _c } @@ -959,7 +960,7 @@ func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) Return(_a0 Hash, _a1 st return _c } -func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) RunAndReturn(run func([]trie.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_StorageRoot_Call[Hash, H] { +func (_c *StatemachineBackend_StorageRoot_Call[Hash, H]) RunAndReturn(run func([]kv.KeyValue, storage.StateVersion) (Hash, statemachine.BackendTransaction[Hash, H])) *StatemachineBackend_StorageRoot_Call[Hash, H] { _c.Call.Return(run) return _c } diff --git a/internal/client/client.go b/internal/client/client.go index 058ea996d2..2101560503 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -24,6 +24,7 @@ import ( "github.com/ChainSafe/gossamer/internal/primitives/runtime/generic" statemachine "github.com/ChainSafe/gossamer/internal/primitives/state-machine" "github.com/ChainSafe/gossamer/internal/primitives/storage" + "github.com/ChainSafe/gossamer/pkg/trie/triedb" "github.com/tidwall/btree" ) @@ -1345,3 +1346,164 @@ func (c *Client[H, Hasher, N, E, Header]) RuntimeAPI() primitives_api.ApiExt[ ] { return c.runtimeConstructor.ConstructRuntimeAPI() } + +func (c *Client[H, Hasher, N, E, Header]) StateAt(hash H) (statemachine.Backend[H, Hasher], error) { + return c.backend.StateAt(hash) +} + +// StorageProvider impl + +func (c *Client[H, Hasher, N, E, Header]) Storage( + hash H, + key storage.StorageKey, +) (storage.StorageData, error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return nil, err + } + + data, err := stateAt.Storage(key) + return storage.StorageData(data), err +} + +func (c *Client[H, Hasher, N, E, Header]) StorageHash( + hash H, + key storage.StorageKey, +) (*H, error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return nil, err + } + + return stateAt.StorageHash(key) +} + +func (c *Client[H, Hasher, N, E, Header]) StorageKeys( + hash H, + prefix, + startKey storage.StorageKey, +) (api.KeysIter[H, Hasher], error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return api.KeysIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.KeysIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewKeysIter(backend, &prefix, &startKey) + if err != nil { + return api.KeysIter[H, Hasher]{}, err + } + + return *iter, nil +} + +func (c *Client[H, Hasher, N, E, Header]) StoragePairs( + hash H, + prefix, + startKey storage.StorageKey, +) (api.PairsIter[H, Hasher], error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return api.PairsIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.PairsIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewPairsIter(backend, &prefix, &startKey) + if err != nil { + return api.PairsIter[H, Hasher]{}, err + } + + return *iter, nil +} + +func (c *Client[H, Hasher, N, E, Header]) ChildStorage( + hash H, + childInfo storage.ChildInfo, + key storage.StorageKey, +) (storage.StorageData, error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return storage.StorageData{}, err + } + + data, err := stateAt.ChildStorage(childInfo, key) + return storage.StorageData(data), err +} + +func (c *Client[H, Hasher, N, E, Header]) ChildStorageKeys( + hash H, + childInfo storage.ChildInfo, + prefix storage.StorageKey, + startKey storage.StorageKey, +) (api.KeysIter[H, Hasher], error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return api.KeysIter[H, Hasher]{}, err + } + backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) + if !ok { + return api.KeysIter[H, Hasher]{}, fmt.Errorf( + "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", + backend, + ) + } + + iter, err := api.NewChildKeysIter(backend, childInfo, &prefix, &startKey) + if err != nil { + return api.KeysIter[H, Hasher]{}, err + } + + return *iter, nil +} + +func (c *Client[H, Hasher, N, E, Header]) ChildStorageHash( + hash H, + childInfo storage.ChildInfo, + key storage.StorageKey, +) (*H, error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return nil, err + } + + return stateAt.ChildStorageHash(childInfo, key) +} + +// ClosestMerkleValue returns the closest merkle value, given a blocks hash and a key. +func (c *Client[H, Hasher, N, E, Header]) ClosestMerkleValue( + hash H, + key storage.StorageKey, +) (triedb.MerkleValue[H], error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return triedb.NodeMerkleValue{}, err + } + + return stateAt.ClosestMerkleValue(key) +} + +// ChildClosestMerkleValue returns the closest merkle value, given a blocks hash, a key and a child storage key. +func (c *Client[H, Hasher, N, E, Header]) ChildClosestMerkleValue( + hash H, + childInfo storage.ChildInfo, + key storage.StorageKey, +) (triedb.MerkleValue[H], error) { + stateAt, err := c.backend.StateAt(hash) + if err != nil { + return triedb.NodeMerkleValue{}, err + } + + return stateAt.ChildClosestMerkleValue(childInfo, key) +} diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 464e92e18a..9077045310 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -63,6 +63,7 @@ var ( statemachine.Backend[hash.H256, runtime.BlakeTwo256], any, *generic.Header[uint64, hash.H256, runtime.BlakeTwo256], ]] = &TestClient{} + _ api.StorageProvider[hash.H256, runtime.BlakeTwo256] = &TestClient{} ) type TestExecutor struct{} From d05af3e4b3603051e05c11f14fa027a35300a5df Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 20:27:28 +0700 Subject: [PATCH 12/23] remove another unused method from BlockState --- dot/state/block.go | 1 - 1 file changed, 1 deletion(-) diff --git a/dot/state/block.go b/dot/state/block.go index 267b7fe26e..8badbcda06 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -78,7 +78,6 @@ type BlockState interface { GetHeaderByNumber(num uint) (*types.Header, error) GetHighestFinalisedHeader() (*types.Header, error) GetHighestFinalisedHash() (common.Hash, error) - GetHighestRoundAndSetID() (uint64, uint64, error) GetJustification(common.Hash) ([]byte, error) GetFirstNonOriginSlotNumber() (uint64, error) GetReceipt(hash common.Hash) ([]byte, error) From 5b016e56701f8975de760be324365d99e49c44a3 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 20:27:48 +0700 Subject: [PATCH 13/23] implement ClientAdapter.Leaves() --- internal/client/adapter/client_adapter.go | 42 ++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index e0afde361e..21514b706f 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -41,11 +41,11 @@ type ClientAdapterDB interface { } type Client[ -H runtime.Hash, -Hasher runtime.Hasher[H], -N runtime.Number, -E runtime.Extrinsic, -Header runtime.Header[N, H], + H runtime.Hash, + Hasher runtime.Hasher[H], + N runtime.Number, + E runtime.Extrinsic, + Header runtime.Header[N, H], ] interface { blockchain.HeaderBackend[H, N, Header] blockchain.HeaderMetadata[H, N] @@ -63,11 +63,11 @@ type Backend[H runtime.Hash, Hasher runtime.Hasher[H]] interface { } type ClientAdapter[ -H runtime.Hash, -Hasher runtime.Hasher[H], -N runtime.Number, -E runtime.Extrinsic, -Header runtime.Header[N, H], + H runtime.Hash, + Hasher runtime.Hasher[H], + N runtime.Number, + E runtime.Extrinsic, + Header runtime.Header[N, H], ] struct { backend Backend[H, Hasher] client Client[H, Hasher, N, E, Header] @@ -75,11 +75,11 @@ Header runtime.Header[N, H], } func NewClientAdapter[ -H runtime.Hash, -Hasher runtime.Hasher[H], -N runtime.Number, -E runtime.Extrinsic, -Header runtime.Header[N, H], + H runtime.Hash, + Hasher runtime.Hasher[H], + N runtime.Number, + E runtime.Extrinsic, + Header runtime.Header[N, H], ]( client Client[H, Hasher, N, E, Header], db ClientAdapterDB, @@ -539,8 +539,18 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) BlocktreeAsString() string { panic("unimplemented") } +// Leaves returns hashes of all blocks that are leaves of the block tree. +// in other words, that have no children, are chain heads. +// Results must be ordered best (longest, highest) chain first. func (ca *ClientAdapter[H, Hasher, N, E, Header]) Leaves() []common.Hash { - panic("unimplemented") + leaves, _ := ca.client.Leaves() + hashes := make([]common.Hash, len(leaves)) + + for i, leaf := range leaves { + hashes[i] = common.NewHashFromGeneric(leaf) + } + + return hashes } func (ca *ClientAdapter[H, Hasher, N, E, Header]) Range(startHash, endHash common.Hash) ( From e6f4a0e52aad7a37057f79277a1d985ad5b8180a Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 21:13:30 +0700 Subject: [PATCH 14/23] implement ClientAdapter.TrieState() --- internal/client/adapter/client_adapter.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 21514b706f..829c39220a 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -615,7 +615,13 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) Pause() error { } func (ca *ClientAdapter[H, Hasher, N, E, Header]) TrieState(root *common.Hash) (rtstorage.TrieState, error) { - panic("unimplemented") + stateAt, err := ca.getStateByStateRoot(root) + if err != nil { + return nil, err + } + + ext := overlayedchanges.NewExt(overlayedchanges.NewOverlayedChanges[H, Hasher](), stateAt) + return rtstorage.NewExtBackedTrieState(ext), nil } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoreTrie(rtstorage.TrieState, *types.Header) error { From 2196b5d94e0fa0fa8e8578e6d5f09bdec0a9f3cc Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 21:26:16 +0700 Subject: [PATCH 15/23] Revert "remove another unused method from BlockState" This reverts commit d05af3e4b3603051e05c11f14fa027a35300a5df. --- dot/state/block.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dot/state/block.go b/dot/state/block.go index 8badbcda06..267b7fe26e 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -78,6 +78,7 @@ type BlockState interface { GetHeaderByNumber(num uint) (*types.Header, error) GetHighestFinalisedHeader() (*types.Header, error) GetHighestFinalisedHash() (common.Hash, error) + GetHighestRoundAndSetID() (uint64, uint64, error) GetJustification(common.Hash) ([]byte, error) GetFirstNonOriginSlotNumber() (uint64, error) GetReceipt(hash common.Hash) ([]byte, error) From c9c2bb012702bf609e11739810c5866d27ff97c4 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 21:37:44 +0700 Subject: [PATCH 16/23] maybe fix mock --- dot/core/mock_state_test.go | 126 ++++++++++++++---------------------- 1 file changed, 48 insertions(+), 78 deletions(-) diff --git a/dot/core/mock_state_test.go b/dot/core/mock_state_test.go index c41845a34a..af24721eb0 100644 --- a/dot/core/mock_state_test.go +++ b/dot/core/mock_state_test.go @@ -220,18 +220,18 @@ func (mr *MockBlockStateMockRecorder) GetAllBlocksAtNumber(num any) *gomock.Call } // GetBlockBody mocks base method. -func (m *MockBlockState) GetBlockBody(arg0 common.Hash) (*types.Body, error) { +func (m *MockBlockState) GetBlockBody(hash common.Hash) (*types.Body, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockBody", arg0) + ret := m.ctrl.Call(m, "GetBlockBody", hash) ret0, _ := ret[0].(*types.Body) ret1, _ := ret[1].(error) return ret0, ret1 } // GetBlockBody indicates an expected call of GetBlockBody. -func (mr *MockBlockStateMockRecorder) GetBlockBody(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetBlockBody(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockBody", reflect.TypeOf((*MockBlockState)(nil).GetBlockBody), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockBody", reflect.TypeOf((*MockBlockState)(nil).GetBlockBody), hash) } // GetBlockByHash mocks base method. @@ -264,21 +264,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -488,18 +473,18 @@ func (mr *MockBlockStateMockRecorder) GetLastFinalized() *gomock.Call { } // GetMessageQueue mocks base method. -func (m *MockBlockState) GetMessageQueue(arg0 common.Hash) ([]byte, error) { +func (m *MockBlockState) GetMessageQueue(hash common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMessageQueue", arg0) + ret := m.ctrl.Call(m, "GetMessageQueue", hash) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMessageQueue indicates an expected call of GetMessageQueue. -func (mr *MockBlockStateMockRecorder) GetMessageQueue(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetMessageQueue(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessageQueue", reflect.TypeOf((*MockBlockState)(nil).GetMessageQueue), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessageQueue", reflect.TypeOf((*MockBlockState)(nil).GetMessageQueue), hash) } // GetNonFinalisedBlocks mocks base method. @@ -517,33 +502,18 @@ func (mr *MockBlockStateMockRecorder) GetNonFinalisedBlocks() *gomock.Call { } // GetReceipt mocks base method. -func (m *MockBlockState) GetReceipt(arg0 common.Hash) ([]byte, error) { +func (m *MockBlockState) GetReceipt(hash common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReceipt", arg0) + ret := m.ctrl.Call(m, "GetReceipt", hash) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetReceipt indicates an expected call of GetReceipt. -func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) -} - -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetReceipt(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), hash) } // GetRuntime mocks base method. @@ -620,48 +590,48 @@ func (mr *MockBlockStateMockRecorder) HasFinalisedBlock(round, setID any) *gomoc } // HasHeader mocks base method. -func (m *MockBlockState) HasHeader(arg0 common.Hash) (bool, error) { +func (m *MockBlockState) HasHeader(hash common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasHeader", arg0) + ret := m.ctrl.Call(m, "HasHeader", hash) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasHeader indicates an expected call of HasHeader. -func (mr *MockBlockStateMockRecorder) HasHeader(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasHeader(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeader", reflect.TypeOf((*MockBlockState)(nil).HasHeader), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeader", reflect.TypeOf((*MockBlockState)(nil).HasHeader), hash) } // HasHeaderInDatabase mocks base method. -func (m *MockBlockState) HasHeaderInDatabase(arg0 common.Hash) (bool, error) { +func (m *MockBlockState) HasHeaderInDatabase(hash common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasHeaderInDatabase", arg0) + ret := m.ctrl.Call(m, "HasHeaderInDatabase", hash) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasHeaderInDatabase indicates an expected call of HasHeaderInDatabase. -func (mr *MockBlockStateMockRecorder) HasHeaderInDatabase(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasHeaderInDatabase(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeaderInDatabase", reflect.TypeOf((*MockBlockState)(nil).HasHeaderInDatabase), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeaderInDatabase", reflect.TypeOf((*MockBlockState)(nil).HasHeaderInDatabase), hash) } // HasJustification mocks base method. -func (m *MockBlockState) HasJustification(arg0 common.Hash) (bool, error) { +func (m *MockBlockState) HasJustification(hash common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasJustification", arg0) + ret := m.ctrl.Call(m, "HasJustification", hash) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasJustification indicates an expected call of HasJustification. -func (mr *MockBlockStateMockRecorder) HasJustification(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasJustification(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasJustification", reflect.TypeOf((*MockBlockState)(nil).HasJustification), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasJustification", reflect.TypeOf((*MockBlockState)(nil).HasJustification), hash) } // IsDescendantOf mocks base method. @@ -811,29 +781,29 @@ func (mr *MockBlockStateMockRecorder) Rewind(toBlock any) *gomock.Call { } // SetBlockTree mocks base method. -func (m *MockBlockState) SetBlockTree(arg0 *blocktree.BlockTree) { +func (m *MockBlockState) SetBlockTree(blocktree *blocktree.BlockTree) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetBlockTree", arg0) + m.ctrl.Call(m, "SetBlockTree", blocktree) } // SetBlockTree indicates an expected call of SetBlockTree. -func (mr *MockBlockStateMockRecorder) SetBlockTree(arg0 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetBlockTree(blocktree any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBlockTree", reflect.TypeOf((*MockBlockState)(nil).SetBlockTree), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBlockTree", reflect.TypeOf((*MockBlockState)(nil).SetBlockTree), blocktree) } // SetFinalisedHash mocks base method. -func (m *MockBlockState) SetFinalisedHash(arg0 common.Hash, round, setID uint64, finalizeAncestors bool) error { +func (m *MockBlockState) SetFinalisedHash(hash common.Hash, round, setID uint64, finalizeAncestors bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetFinalisedHash", arg0, round, setID, finalizeAncestors) + ret := m.ctrl.Call(m, "SetFinalisedHash", hash, round, setID, finalizeAncestors) ret0, _ := ret[0].(error) return ret0 } // SetFinalisedHash indicates an expected call of SetFinalisedHash. -func (mr *MockBlockStateMockRecorder) SetFinalisedHash(arg0, round, setID, finalizeAncestors any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetFinalisedHash(hash, round, setID, finalizeAncestors any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFinalisedHash", reflect.TypeOf((*MockBlockState)(nil).SetFinalisedHash), arg0, round, setID, finalizeAncestors) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFinalisedHash", reflect.TypeOf((*MockBlockState)(nil).SetFinalisedHash), hash, round, setID, finalizeAncestors) } // SetFinalizedHeader mocks base method. @@ -893,29 +863,29 @@ func (mr *MockBlockStateMockRecorder) SetHighestRoundAndSetID(round, setID any) } // SetJustification mocks base method. -func (m *MockBlockState) SetJustification(arg0 common.Hash, data []byte) error { +func (m *MockBlockState) SetJustification(hash common.Hash, data []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetJustification", arg0, data) + ret := m.ctrl.Call(m, "SetJustification", hash, data) ret0, _ := ret[0].(error) return ret0 } // SetJustification indicates an expected call of SetJustification. -func (mr *MockBlockStateMockRecorder) SetJustification(arg0, data any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetJustification(hash, data any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetJustification", reflect.TypeOf((*MockBlockState)(nil).SetJustification), arg0, data) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetJustification", reflect.TypeOf((*MockBlockState)(nil).SetJustification), hash, data) } // StoreRuntime mocks base method. -func (m *MockBlockState) StoreRuntime(blockHash common.Hash, arg1 runtime0.Instance) { +func (m *MockBlockState) StoreRuntime(blockHash common.Hash, runtime runtime0.Instance) { m.ctrl.T.Helper() - m.ctrl.Call(m, "StoreRuntime", blockHash, arg1) + m.ctrl.Call(m, "StoreRuntime", blockHash, runtime) } // StoreRuntime indicates an expected call of StoreRuntime. -func (mr *MockBlockStateMockRecorder) StoreRuntime(blockHash, arg1 any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) StoreRuntime(blockHash, runtime any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreRuntime", reflect.TypeOf((*MockBlockState)(nil).StoreRuntime), blockHash, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreRuntime", reflect.TypeOf((*MockBlockState)(nil).StoreRuntime), blockHash, runtime) } // UnregisterRuntimeUpdatedChannel mocks base method. @@ -1077,33 +1047,33 @@ func (mr *MockStorageStateMockRecorder) GetStorageFromChild(root, keyToChild, ke } // LoadCode mocks base method. -func (m *MockStorageState) LoadCode(arg0 *common.Hash) ([]byte, error) { +func (m *MockStorageState) LoadCode(hash *common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCode", arg0) + ret := m.ctrl.Call(m, "LoadCode", hash) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCode indicates an expected call of LoadCode. -func (mr *MockStorageStateMockRecorder) LoadCode(arg0 any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCode(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), hash) } // LoadCodeHash mocks base method. -func (m *MockStorageState) LoadCodeHash(arg0 *common.Hash) (common.Hash, error) { +func (m *MockStorageState) LoadCodeHash(hash *common.Hash) (common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCodeHash", arg0) + ret := m.ctrl.Call(m, "LoadCodeHash", hash) ret0, _ := ret[0].(common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCodeHash indicates an expected call of LoadCodeHash. -func (mr *MockStorageStateMockRecorder) LoadCodeHash(arg0 any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCodeHash(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), hash) } // Lock mocks base method. From 9aa715cbadfa84bad1cbb227c0247005fbe29ba3 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 21:43:07 +0700 Subject: [PATCH 17/23] more mock fixery --- dot/core/mock_state_test.go | 96 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/dot/core/mock_state_test.go b/dot/core/mock_state_test.go index af24721eb0..b09a7e0d37 100644 --- a/dot/core/mock_state_test.go +++ b/dot/core/mock_state_test.go @@ -220,18 +220,18 @@ func (mr *MockBlockStateMockRecorder) GetAllBlocksAtNumber(num any) *gomock.Call } // GetBlockBody mocks base method. -func (m *MockBlockState) GetBlockBody(hash common.Hash) (*types.Body, error) { +func (m *MockBlockState) GetBlockBody(arg0 common.Hash) (*types.Body, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockBody", hash) + ret := m.ctrl.Call(m, "GetBlockBody", arg0) ret0, _ := ret[0].(*types.Body) ret1, _ := ret[1].(error) return ret0, ret1 } // GetBlockBody indicates an expected call of GetBlockBody. -func (mr *MockBlockStateMockRecorder) GetBlockBody(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetBlockBody(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockBody", reflect.TypeOf((*MockBlockState)(nil).GetBlockBody), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockBody", reflect.TypeOf((*MockBlockState)(nil).GetBlockBody), arg0) } // GetBlockByHash mocks base method. @@ -473,18 +473,18 @@ func (mr *MockBlockStateMockRecorder) GetLastFinalized() *gomock.Call { } // GetMessageQueue mocks base method. -func (m *MockBlockState) GetMessageQueue(hash common.Hash) ([]byte, error) { +func (m *MockBlockState) GetMessageQueue(arg0 common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetMessageQueue", hash) + ret := m.ctrl.Call(m, "GetMessageQueue", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetMessageQueue indicates an expected call of GetMessageQueue. -func (mr *MockBlockStateMockRecorder) GetMessageQueue(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetMessageQueue(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessageQueue", reflect.TypeOf((*MockBlockState)(nil).GetMessageQueue), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessageQueue", reflect.TypeOf((*MockBlockState)(nil).GetMessageQueue), arg0) } // GetNonFinalisedBlocks mocks base method. @@ -502,18 +502,18 @@ func (mr *MockBlockStateMockRecorder) GetNonFinalisedBlocks() *gomock.Call { } // GetReceipt mocks base method. -func (m *MockBlockState) GetReceipt(hash common.Hash) ([]byte, error) { +func (m *MockBlockState) GetReceipt(arg0 common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReceipt", hash) + ret := m.ctrl.Call(m, "GetReceipt", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetReceipt indicates an expected call of GetReceipt. -func (mr *MockBlockStateMockRecorder) GetReceipt(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } // GetRuntime mocks base method. @@ -590,48 +590,48 @@ func (mr *MockBlockStateMockRecorder) HasFinalisedBlock(round, setID any) *gomoc } // HasHeader mocks base method. -func (m *MockBlockState) HasHeader(hash common.Hash) (bool, error) { +func (m *MockBlockState) HasHeader(arg0 common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasHeader", hash) + ret := m.ctrl.Call(m, "HasHeader", arg0) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasHeader indicates an expected call of HasHeader. -func (mr *MockBlockStateMockRecorder) HasHeader(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasHeader(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeader", reflect.TypeOf((*MockBlockState)(nil).HasHeader), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeader", reflect.TypeOf((*MockBlockState)(nil).HasHeader), arg0) } // HasHeaderInDatabase mocks base method. -func (m *MockBlockState) HasHeaderInDatabase(hash common.Hash) (bool, error) { +func (m *MockBlockState) HasHeaderInDatabase(arg0 common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasHeaderInDatabase", hash) + ret := m.ctrl.Call(m, "HasHeaderInDatabase", arg0) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasHeaderInDatabase indicates an expected call of HasHeaderInDatabase. -func (mr *MockBlockStateMockRecorder) HasHeaderInDatabase(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasHeaderInDatabase(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeaderInDatabase", reflect.TypeOf((*MockBlockState)(nil).HasHeaderInDatabase), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasHeaderInDatabase", reflect.TypeOf((*MockBlockState)(nil).HasHeaderInDatabase), arg0) } // HasJustification mocks base method. -func (m *MockBlockState) HasJustification(hash common.Hash) (bool, error) { +func (m *MockBlockState) HasJustification(arg0 common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasJustification", hash) + ret := m.ctrl.Call(m, "HasJustification", arg0) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // HasJustification indicates an expected call of HasJustification. -func (mr *MockBlockStateMockRecorder) HasJustification(hash any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) HasJustification(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasJustification", reflect.TypeOf((*MockBlockState)(nil).HasJustification), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasJustification", reflect.TypeOf((*MockBlockState)(nil).HasJustification), arg0) } // IsDescendantOf mocks base method. @@ -781,29 +781,29 @@ func (mr *MockBlockStateMockRecorder) Rewind(toBlock any) *gomock.Call { } // SetBlockTree mocks base method. -func (m *MockBlockState) SetBlockTree(blocktree *blocktree.BlockTree) { +func (m *MockBlockState) SetBlockTree(arg0 *blocktree.BlockTree) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetBlockTree", blocktree) + m.ctrl.Call(m, "SetBlockTree", arg0) } // SetBlockTree indicates an expected call of SetBlockTree. -func (mr *MockBlockStateMockRecorder) SetBlockTree(blocktree any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetBlockTree(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBlockTree", reflect.TypeOf((*MockBlockState)(nil).SetBlockTree), blocktree) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetBlockTree", reflect.TypeOf((*MockBlockState)(nil).SetBlockTree), arg0) } // SetFinalisedHash mocks base method. -func (m *MockBlockState) SetFinalisedHash(hash common.Hash, round, setID uint64, finalizeAncestors bool) error { +func (m *MockBlockState) SetFinalisedHash(arg0 common.Hash, round, setID uint64, finalizeAncestors bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetFinalisedHash", hash, round, setID, finalizeAncestors) + ret := m.ctrl.Call(m, "SetFinalisedHash", arg0, round, setID, finalizeAncestors) ret0, _ := ret[0].(error) return ret0 } // SetFinalisedHash indicates an expected call of SetFinalisedHash. -func (mr *MockBlockStateMockRecorder) SetFinalisedHash(hash, round, setID, finalizeAncestors any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetFinalisedHash(arg0, round, setID, finalizeAncestors any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFinalisedHash", reflect.TypeOf((*MockBlockState)(nil).SetFinalisedHash), hash, round, setID, finalizeAncestors) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFinalisedHash", reflect.TypeOf((*MockBlockState)(nil).SetFinalisedHash), arg0, round, setID, finalizeAncestors) } // SetFinalizedHeader mocks base method. @@ -863,29 +863,29 @@ func (mr *MockBlockStateMockRecorder) SetHighestRoundAndSetID(round, setID any) } // SetJustification mocks base method. -func (m *MockBlockState) SetJustification(hash common.Hash, data []byte) error { +func (m *MockBlockState) SetJustification(arg0 common.Hash, data []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetJustification", hash, data) + ret := m.ctrl.Call(m, "SetJustification", arg0, data) ret0, _ := ret[0].(error) return ret0 } // SetJustification indicates an expected call of SetJustification. -func (mr *MockBlockStateMockRecorder) SetJustification(hash, data any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) SetJustification(arg0, data any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetJustification", reflect.TypeOf((*MockBlockState)(nil).SetJustification), hash, data) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetJustification", reflect.TypeOf((*MockBlockState)(nil).SetJustification), arg0, data) } // StoreRuntime mocks base method. -func (m *MockBlockState) StoreRuntime(blockHash common.Hash, runtime runtime0.Instance) { +func (m *MockBlockState) StoreRuntime(blockHash common.Hash, arg1 runtime0.Instance) { m.ctrl.T.Helper() - m.ctrl.Call(m, "StoreRuntime", blockHash, runtime) + m.ctrl.Call(m, "StoreRuntime", blockHash, arg1) } // StoreRuntime indicates an expected call of StoreRuntime. -func (mr *MockBlockStateMockRecorder) StoreRuntime(blockHash, runtime any) *gomock.Call { +func (mr *MockBlockStateMockRecorder) StoreRuntime(blockHash, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreRuntime", reflect.TypeOf((*MockBlockState)(nil).StoreRuntime), blockHash, runtime) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreRuntime", reflect.TypeOf((*MockBlockState)(nil).StoreRuntime), blockHash, arg1) } // UnregisterRuntimeUpdatedChannel mocks base method. @@ -1047,33 +1047,33 @@ func (mr *MockStorageStateMockRecorder) GetStorageFromChild(root, keyToChild, ke } // LoadCode mocks base method. -func (m *MockStorageState) LoadCode(hash *common.Hash) ([]byte, error) { +func (m *MockStorageState) LoadCode(arg0 *common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCode", hash) + ret := m.ctrl.Call(m, "LoadCode", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCode indicates an expected call of LoadCode. -func (mr *MockStorageStateMockRecorder) LoadCode(hash any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCode(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), arg0) } // LoadCodeHash mocks base method. -func (m *MockStorageState) LoadCodeHash(hash *common.Hash) (common.Hash, error) { +func (m *MockStorageState) LoadCodeHash(arg0 *common.Hash) (common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCodeHash", hash) + ret := m.ctrl.Call(m, "LoadCodeHash", arg0) ret0, _ := ret[0].(common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCodeHash indicates an expected call of LoadCodeHash. -func (mr *MockStorageStateMockRecorder) LoadCodeHash(hash any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCodeHash(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), arg0) } // Lock mocks base method. From 96a0c2e6445c94ffc7cc34944aafe97076f64013 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 21 Jun 2025 21:49:29 +0700 Subject: [PATCH 18/23] update a bazillion BlockState mocks --- dot/mock_block_state_test.go | 30 ------------------- dot/network/mock_block_state_test.go | 30 ------------------- dot/rpc/modules/mock_block_state_test.go | 30 ------------------- dot/sync/mock_block_state_maker.go | 30 ------------------- lib/babe/mock_block_state_test.go | 30 ------------------- lib/grandpa/mocks_block_state_test.go | 30 ------------------- .../warpsync/mocks_block_state_test.go | 30 ------------------- 7 files changed, 210 deletions(-) diff --git a/dot/mock_block_state_test.go b/dot/mock_block_state_test.go index 75b6c6506f..e2745a4b1b 100644 --- a/dot/mock_block_state_test.go +++ b/dot/mock_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/dot/network/mock_block_state_test.go b/dot/network/mock_block_state_test.go index d5f4c1c563..5c89a3d699 100644 --- a/dot/network/mock_block_state_test.go +++ b/dot/network/mock_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/dot/rpc/modules/mock_block_state_test.go b/dot/rpc/modules/mock_block_state_test.go index 921a000e29..a41618f5d9 100644 --- a/dot/rpc/modules/mock_block_state_test.go +++ b/dot/rpc/modules/mock_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/dot/sync/mock_block_state_maker.go b/dot/sync/mock_block_state_maker.go index fa1f9cf9f2..68e78a336b 100644 --- a/dot/sync/mock_block_state_maker.go +++ b/dot/sync/mock_block_state_maker.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/lib/babe/mock_block_state_test.go b/lib/babe/mock_block_state_test.go index a286778f2c..dea7581fa8 100644 --- a/lib/babe/mock_block_state_test.go +++ b/lib/babe/mock_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/lib/grandpa/mocks_block_state_test.go b/lib/grandpa/mocks_block_state_test.go index 702aa75567..821dd00891 100644 --- a/lib/grandpa/mocks_block_state_test.go +++ b/lib/grandpa/mocks_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() diff --git a/lib/grandpa/warpsync/mocks_block_state_test.go b/lib/grandpa/warpsync/mocks_block_state_test.go index 6005577837..7149a7029c 100644 --- a/lib/grandpa/warpsync/mocks_block_state_test.go +++ b/lib/grandpa/warpsync/mocks_block_state_test.go @@ -263,21 +263,6 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(blockNumber any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), blockNumber) } -// GetBlockHashesBySlot mocks base method. -func (m *MockBlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockHashesBySlot", slotNum) - ret0, _ := ret[0].([]common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. -func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(slotNum any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), slotNum) -} - // GetBlockStateRoot mocks base method. func (m *MockBlockState) GetBlockStateRoot(bhash common.Hash) (common.Hash, error) { m.ctrl.T.Helper() @@ -530,21 +515,6 @@ func (mr *MockBlockStateMockRecorder) GetReceipt(arg0 any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipt", reflect.TypeOf((*MockBlockState)(nil).GetReceipt), arg0) } -// GetRoundAndSetID mocks base method. -func (m *MockBlockState) GetRoundAndSetID() (uint64, uint64) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRoundAndSetID") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(uint64) - return ret0, ret1 -} - -// GetRoundAndSetID indicates an expected call of GetRoundAndSetID. -func (mr *MockBlockStateMockRecorder) GetRoundAndSetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoundAndSetID", reflect.TypeOf((*MockBlockState)(nil).GetRoundAndSetID)) -} - // GetRuntime mocks base method. func (m *MockBlockState) GetRuntime(blockHash common.Hash) (runtime0.Instance, error) { m.ctrl.T.Helper() From 9ee8088103b8a3746b6e61dfcadbe7379517a3b5 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Wed, 25 Jun 2025 16:17:26 +0700 Subject: [PATCH 19/23] WIP GenerateTrieProof() --- internal/client/adapter/client_adapter.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 829c39220a..8b195d341b 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -8,6 +8,7 @@ import ( "encoding/binary" "errors" "fmt" + "slices" "time" "github.com/ChainSafe/gossamer/dot/state" @@ -30,6 +31,7 @@ import ( "github.com/ChainSafe/gossamer/pkg/trie" "github.com/ChainSafe/gossamer/pkg/trie/db" "github.com/ChainSafe/gossamer/pkg/trie/inmemory" + "github.com/ChainSafe/gossamer/pkg/trie/triedb/proof" ) var ErrMissingOverlayedChanges = errors.New("missing overlayed changes") @@ -654,6 +656,15 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStateRootFromBlock(bhash *c func (ca *ClientAdapter[H, Hasher, N, E, Header]) GenerateTrieProof(stateRoot common.Hash, keys [][]byte) ( [][]byte, error) { + //hasher := *new(Hasher) + //rootHash := hasher.NewHash(stateRoot.ToBytes()) + // + //sKeys := make([]string, len(keys)) + //for i, k := range keys { + // sKeys[i] = string(k) + //} + // + //return proof.NewMerkleProof[H, Hasher](/* FIXME */, trie.DefaultStateVersion, rootHash, sKeys) panic("unimplemented") } From 65615ce006a2865c7f63cf0adbb8fecf8af2d87c Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Thu, 26 Jun 2025 21:37:33 +0700 Subject: [PATCH 20/23] use statemachine.KeysIter in StorageProvider --- internal/client/adapter/client_adapter.go | 2 - internal/client/adapter/mocks/client.go | 44 +++-- internal/client/api/backend.go | 176 +------------------ internal/client/client.go | 30 ++-- internal/primitives/state-machine/backend.go | 108 ++++++++++++ 5 files changed, 147 insertions(+), 213 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 8b195d341b..cfd4a93528 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -8,7 +8,6 @@ import ( "encoding/binary" "errors" "fmt" - "slices" "time" "github.com/ChainSafe/gossamer/dot/state" @@ -31,7 +30,6 @@ import ( "github.com/ChainSafe/gossamer/pkg/trie" "github.com/ChainSafe/gossamer/pkg/trie/db" "github.com/ChainSafe/gossamer/pkg/trie/inmemory" - "github.com/ChainSafe/gossamer/pkg/trie/triedb/proof" ) var ErrMissingOverlayedChanges = errors.New("missing overlayed changes") diff --git a/internal/client/adapter/mocks/client.go b/internal/client/adapter/mocks/client.go index 1a2bff5b14..fbbb726d7b 100644 --- a/internal/client/adapter/mocks/client.go +++ b/internal/client/adapter/mocks/client.go @@ -3,9 +3,7 @@ package mocks import ( - api "github.com/ChainSafe/gossamer/internal/client/api" blockchain "github.com/ChainSafe/gossamer/internal/primitives/blockchain" - common "github.com/ChainSafe/gossamer/internal/primitives/consensus/common" consensuscommon "github.com/ChainSafe/gossamer/internal/client/consensus/common" @@ -741,22 +739,22 @@ func (_c *Client_ChildStorageHash_Call[H, Hasher, N, E, Header]) RunAndReturn(ru } // ChildStorageKeys provides a mock function with given fields: hash, childInfo, prefix, startKey -func (_m *Client[H, Hasher, N, E, Header]) ChildStorageKeys(hash H, childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey) (api.KeysIter[H, Hasher], error) { +func (_m *Client[H, Hasher, N, E, Header]) ChildStorageKeys(hash H, childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey) (statemachine.KeysIter[H, Hasher], error) { ret := _m.Called(hash, childInfo, prefix, startKey) if len(ret) == 0 { panic("no return value specified for ChildStorageKeys") } - var r0 api.KeysIter[H, Hasher] + var r0 statemachine.KeysIter[H, Hasher] var r1 error - if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)); ok { + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (statemachine.KeysIter[H, Hasher], error)); ok { return rf(hash, childInfo, prefix, startKey) } - if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) api.KeysIter[H, Hasher]); ok { + if rf, ok := ret.Get(0).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) statemachine.KeysIter[H, Hasher]); ok { r0 = rf(hash, childInfo, prefix, startKey) } else { - r0 = ret.Get(0).(api.KeysIter[H, Hasher]) + r0 = ret.Get(0).(statemachine.KeysIter[H, Hasher]) } if rf, ok := ret.Get(1).(func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) error); ok { @@ -789,12 +787,12 @@ func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) Run(run func(ha return _c } -func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 api.KeysIter[H, Hasher], _a1 error) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { +func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 statemachine.KeysIter[H, Hasher], _a1 error) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { _c.Call.Return(_a0, _a1) return _c } -func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { +func (_c *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.ChildInfo, storage.StorageKey, storage.StorageKey) (statemachine.KeysIter[H, Hasher], error)) *Client_ChildStorageKeys_Call[H, Hasher, N, E, Header] { _c.Call.Return(run) return _c } @@ -2042,22 +2040,22 @@ func (_c *Client_StorageHash_Call[H, Hasher, N, E, Header]) RunAndReturn(run fun } // StorageKeys provides a mock function with given fields: hash, prefix, startKey -func (_m *Client[H, Hasher, N, E, Header]) StorageKeys(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (api.KeysIter[H, Hasher], error) { +func (_m *Client[H, Hasher, N, E, Header]) StorageKeys(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (statemachine.KeysIter[H, Hasher], error) { ret := _m.Called(hash, prefix, startKey) if len(ret) == 0 { panic("no return value specified for StorageKeys") } - var r0 api.KeysIter[H, Hasher] + var r0 statemachine.KeysIter[H, Hasher] var r1 error - if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)); ok { + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (statemachine.KeysIter[H, Hasher], error)); ok { return rf(hash, prefix, startKey) } - if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) api.KeysIter[H, Hasher]); ok { + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) statemachine.KeysIter[H, Hasher]); ok { r0 = rf(hash, prefix, startKey) } else { - r0 = ret.Get(0).(api.KeysIter[H, Hasher]) + r0 = ret.Get(0).(statemachine.KeysIter[H, Hasher]) } if rf, ok := ret.Get(1).(func(H, storage.StorageKey, storage.StorageKey) error); ok { @@ -2089,33 +2087,33 @@ func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) Run(run func(hash H, return _c } -func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 api.KeysIter[H, Hasher], _a1 error) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { +func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) Return(_a0 statemachine.KeysIter[H, Hasher], _a1 error) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { _c.Call.Return(_a0, _a1) return _c } -func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (api.KeysIter[H, Hasher], error)) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { +func (_c *Client_StorageKeys_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (statemachine.KeysIter[H, Hasher], error)) *Client_StorageKeys_Call[H, Hasher, N, E, Header] { _c.Call.Return(run) return _c } // StoragePairs provides a mock function with given fields: hash, prefix, startKey -func (_m *Client[H, Hasher, N, E, Header]) StoragePairs(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (api.PairsIter[H, Hasher], error) { +func (_m *Client[H, Hasher, N, E, Header]) StoragePairs(hash H, prefix storage.StorageKey, startKey storage.StorageKey) (statemachine.PairsIter[H, Hasher], error) { ret := _m.Called(hash, prefix, startKey) if len(ret) == 0 { panic("no return value specified for StoragePairs") } - var r0 api.PairsIter[H, Hasher] + var r0 statemachine.PairsIter[H, Hasher] var r1 error - if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (api.PairsIter[H, Hasher], error)); ok { + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) (statemachine.PairsIter[H, Hasher], error)); ok { return rf(hash, prefix, startKey) } - if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) api.PairsIter[H, Hasher]); ok { + if rf, ok := ret.Get(0).(func(H, storage.StorageKey, storage.StorageKey) statemachine.PairsIter[H, Hasher]); ok { r0 = rf(hash, prefix, startKey) } else { - r0 = ret.Get(0).(api.PairsIter[H, Hasher]) + r0 = ret.Get(0).(statemachine.PairsIter[H, Hasher]) } if rf, ok := ret.Get(1).(func(H, storage.StorageKey, storage.StorageKey) error); ok { @@ -2147,12 +2145,12 @@ func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) Run(run func(hash H return _c } -func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) Return(_a0 api.PairsIter[H, Hasher], _a1 error) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { +func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) Return(_a0 statemachine.PairsIter[H, Hasher], _a1 error) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { _c.Call.Return(_a0, _a1) return _c } -func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (api.PairsIter[H, Hasher], error)) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { +func (_c *Client_StoragePairs_Call[H, Hasher, N, E, Header]) RunAndReturn(run func(H, storage.StorageKey, storage.StorageKey) (statemachine.PairsIter[H, Hasher], error)) *Client_StoragePairs_Call[H, Hasher, N, E, Header] { _c.Call.Return(run) return _c } diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index e3465989b4..4338f0057d 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -4,7 +4,6 @@ package api import ( - "iter" "sync" "github.com/ChainSafe/gossamer/internal/primitives/blockchain" @@ -353,181 +352,12 @@ type Backend[ // UsageInfo() *UsageInfo } -// KeysIter is an iterator over storage keys. -type KeysIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { - backend *statemachine.TrieBackend[H, Hasher] - rawIter statemachine.StorageIterator[H, Hasher] -} - -func NewKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( - backend *statemachine.TrieBackend[H, Hasher], - prefix *storage.StorageKey, - startAt *storage.StorageKey, -) (*KeysIter[H, Hasher], error) { - args := statemachine.IterArgs{ - StartAtExclusive: true, - } - - if prefix != nil { - args.Prefix = *prefix - } - - if startAt != nil { - args.StartAt = *startAt - } - - rawIter, err := backend.RawIter(args) - if err != nil { - return nil, err - } - - return &KeysIter[H, Hasher]{backend, rawIter}, nil -} - -func NewChildKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( - backend *statemachine.TrieBackend[H, Hasher], - childInfo storage.ChildInfo, - prefix *storage.StorageKey, - startAt *storage.StorageKey, -) (*KeysIter[H, Hasher], error) { - args := statemachine.IterArgs{ - ChildInfo: childInfo, - StartAtExclusive: true, - } - - if prefix != nil { - args.Prefix = *prefix - } - - if startAt != nil { - args.StartAt = *startAt - } - - rawIter, err := backend.RawIter(args) - if err != nil { - return nil, err - } - - return &KeysIter[H, Hasher]{backend, rawIter}, nil -} - -func (ki *KeysIter[H, Hasher]) Next() (storage.StorageKey, error) { - key, err := ki.rawIter.NextKey(ki.backend) - return storage.StorageKey(key), err -} - -func (ki *KeysIter[H, Hasher]) All() iter.Seq2[storage.StorageKey, error] { - return func(yield func(storage.StorageKey, error) bool) { - for { - item, err := ki.Next() - if err != nil { - return - } - if item == nil { - return - } - if !yield(item, err) { - return - } - } - } -} - // StorageKeyData is a storage key/value pair. type StorageKeyData struct { storage.StorageKey storage.StorageData } -// PairsIter is an iterator over storage key/value pairs. -type PairsIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { - backend *statemachine.TrieBackend[H, Hasher] - rawIter statemachine.StorageIterator[H, Hasher] -} - -func NewPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( - backend *statemachine.TrieBackend[H, Hasher], - prefix *storage.StorageKey, - startAt *storage.StorageKey, -) (*PairsIter[H, Hasher], error) { - args := statemachine.IterArgs{ - StartAtExclusive: true, - } - - if prefix != nil { - args.Prefix = *prefix - } - - if startAt != nil { - args.StartAt = *startAt - } - - rawIter, err := backend.RawIter(args) - if err != nil { - return nil, err - } - - return &PairsIter[H, Hasher]{backend, rawIter}, nil -} - -func NewChildPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( - backend *statemachine.TrieBackend[H, Hasher], - childInfo storage.ChildInfo, - prefix *storage.StorageKey, - startAt *storage.StorageKey, -) (*PairsIter[H, Hasher], error) { - args := statemachine.IterArgs{ - ChildInfo: childInfo, - StartAtExclusive: true, - } - - if prefix != nil { - args.Prefix = *prefix - } - - if startAt != nil { - args.StartAt = *startAt - } - - rawIter, err := backend.RawIter(args) - if err != nil { - return nil, err - } - - return &PairsIter[H, Hasher]{backend, rawIter}, nil -} - -func (ki *PairsIter[H, Hasher]) Next() (*StorageKeyData, error) { - keyValue, err := ki.rawIter.NextKeyValue(ki.backend) - if err != nil { - return nil, err - } - - data := StorageKeyData{ - StorageKey: storage.StorageKey(keyValue.StorageKey), - StorageData: storage.StorageData(keyValue.StorageValue), - } - - return &data, nil -} - -func (ki *PairsIter[H, Hasher]) All() iter.Seq2[StorageKeyData, error] { - return func(yield func(StorageKeyData, error) bool) { - for { - item, err := ki.Next() - if err != nil { - return - } - if item == nil { - return - } - if !yield(*item, err) { - return - } - } - } -} - // StorageProvider provides access to storage primitives type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { // Storage returns the value under the key in that block, given a blocks hash and a key. @@ -538,11 +368,11 @@ type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { // StorageKeys returns a [KeysIter] that iterates over matching storage keys in that block // given a blocks hash and a key prefix. - StorageKeys(hash H, prefix, startKey storage.StorageKey) (KeysIter[H, Hasher], error) + StorageKeys(hash H, prefix, startKey storage.StorageKey) (statemachine.KeysIter[H, Hasher], error) // StoragePairs returns an iterator over the storage keys and values in that block, // given the blocks hash and a key prefix. - StoragePairs(hash H, prefix, startKey storage.StorageKey) (PairsIter[H, Hasher], error) + StoragePairs(hash H, prefix, startKey storage.StorageKey) (statemachine.PairsIter[H, Hasher], error) // ChildStorage returns the value under the key in that block, given a blocks hash, // a key and a child storage key. @@ -559,7 +389,7 @@ type StorageProvider[H runtime.Hash, Hasher runtime.Hasher[H]] interface { childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey, - ) (KeysIter[H, Hasher], error) + ) (statemachine.KeysIter[H, Hasher], error) // ChildStorageHash returns the hash under the key in a block, given its hash, // a key and a child storage key. diff --git a/internal/client/client.go b/internal/client/client.go index 2101560503..1c60221e56 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -1382,22 +1382,22 @@ func (c *Client[H, Hasher, N, E, Header]) StorageKeys( hash H, prefix, startKey storage.StorageKey, -) (api.KeysIter[H, Hasher], error) { +) (statemachine.KeysIter[H, Hasher], error) { stateAt, err := c.backend.StateAt(hash) if err != nil { - return api.KeysIter[H, Hasher]{}, err + return statemachine.KeysIter[H, Hasher]{}, err } backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) if !ok { - return api.KeysIter[H, Hasher]{}, fmt.Errorf( + return statemachine.KeysIter[H, Hasher]{}, fmt.Errorf( "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", backend, ) } - iter, err := api.NewKeysIter(backend, &prefix, &startKey) + iter, err := statemachine.NewKeysIter(backend, &prefix, &startKey) if err != nil { - return api.KeysIter[H, Hasher]{}, err + return statemachine.KeysIter[H, Hasher]{}, err } return *iter, nil @@ -1407,22 +1407,22 @@ func (c *Client[H, Hasher, N, E, Header]) StoragePairs( hash H, prefix, startKey storage.StorageKey, -) (api.PairsIter[H, Hasher], error) { +) (statemachine.PairsIter[H, Hasher], error) { stateAt, err := c.backend.StateAt(hash) if err != nil { - return api.PairsIter[H, Hasher]{}, err + return statemachine.PairsIter[H, Hasher]{}, err } backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) if !ok { - return api.PairsIter[H, Hasher]{}, fmt.Errorf( + return statemachine.PairsIter[H, Hasher]{}, fmt.Errorf( "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", backend, ) } - iter, err := api.NewPairsIter(backend, &prefix, &startKey) + iter, err := statemachine.NewPairsIter(backend, &prefix, &startKey) if err != nil { - return api.PairsIter[H, Hasher]{}, err + return statemachine.PairsIter[H, Hasher]{}, err } return *iter, nil @@ -1447,22 +1447,22 @@ func (c *Client[H, Hasher, N, E, Header]) ChildStorageKeys( childInfo storage.ChildInfo, prefix storage.StorageKey, startKey storage.StorageKey, -) (api.KeysIter[H, Hasher], error) { +) (statemachine.KeysIter[H, Hasher], error) { stateAt, err := c.backend.StateAt(hash) if err != nil { - return api.KeysIter[H, Hasher]{}, err + return statemachine.KeysIter[H, Hasher]{}, err } backend, ok := stateAt.(*statemachine.TrieBackend[H, Hasher]) if !ok { - return api.KeysIter[H, Hasher]{}, fmt.Errorf( + return statemachine.KeysIter[H, Hasher]{}, fmt.Errorf( "got unexpected Backend type from StateAt() %T instead of statemachine.TrieBackend", backend, ) } - iter, err := api.NewChildKeysIter(backend, childInfo, &prefix, &startKey) + iter, err := statemachine.NewChildKeysIter(backend, childInfo, &prefix, &startKey) if err != nil { - return api.KeysIter[H, Hasher]{}, err + return statemachine.KeysIter[H, Hasher]{}, err } return *iter, nil diff --git a/internal/primitives/state-machine/backend.go b/internal/primitives/state-machine/backend.go index 23e33767c1..eede6167fe 100644 --- a/internal/primitives/state-machine/backend.go +++ b/internal/primitives/state-machine/backend.go @@ -78,6 +78,60 @@ type PairsIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { rawIter StorageIterator[H, Hasher] } +// NewPairsIter returns on iterator over key/value pairs in the given [TrieBackend]. +func NewPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *TrieBackend[H, Hasher], + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*PairsIter[H, Hasher], error) { + args := IterArgs{ + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &PairsIter[H, Hasher]{backend, rawIter}, nil +} + +// NewChildPairsIter returns on iterator over key/value pairs of a child trie in the given [TrieBackend]. +func NewChildPairsIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *TrieBackend[H, Hasher], + childInfo storage.ChildInfo, + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*PairsIter[H, Hasher], error) { + args := IterArgs{ + ChildInfo: childInfo, + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &PairsIter[H, Hasher]{backend, rawIter}, nil +} + func (pi *PairsIter[H, Hasher]) Next() (*StorageKeyValue, error) { return pi.rawIter.NextKeyValue(pi.backend) } @@ -105,6 +159,60 @@ type KeysIter[H runtime.Hash, Hasher runtime.Hasher[H]] struct { rawIter StorageIterator[H, Hasher] } +// NewKeysIter returns an interator over keys in the given [TrieBackend]. +func NewKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *TrieBackend[H, Hasher], + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*KeysIter[H, Hasher], error) { + args := IterArgs{ + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &KeysIter[H, Hasher]{backend, rawIter}, nil +} + +// NewChildKeysIter returns an interator over keys of a child trie in the given [TrieBackend]. +func NewChildKeysIter[H runtime.Hash, Hasher runtime.Hasher[H]]( + backend *TrieBackend[H, Hasher], + childInfo storage.ChildInfo, + prefix *storage.StorageKey, + startAt *storage.StorageKey, +) (*KeysIter[H, Hasher], error) { + args := IterArgs{ + ChildInfo: childInfo, + StartAtExclusive: true, + } + + if prefix != nil { + args.Prefix = *prefix + } + + if startAt != nil { + args.StartAt = *startAt + } + + rawIter, err := backend.RawIter(args) + if err != nil { + return nil, err + } + + return &KeysIter[H, Hasher]{backend, rawIter}, nil +} + func (ki *KeysIter[H, Hasher]) Next() (StorageKey, error) { return ki.rawIter.NextKey(ki.backend) } From 3a71c456e5430c965d9daf69adb33c05ec7d3224 Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 5 Jul 2025 11:47:34 +0700 Subject: [PATCH 21/23] fix(state): Change StorageState methods to always expect a block hash (#4792) --- dot/core/messages.go | 5 +- dot/core/messages_test.go | 11 +- dot/core/mock_state_test.go | 94 ++++------- dot/core/service.go | 25 +-- dot/core/service_integration_test.go | 3 +- dot/core/service_test.go | 33 ---- dot/node.go | 2 +- dot/node_integration_test.go | 2 +- dot/rpc/interfaces.go | 12 +- dot/rpc/modules/api.go | 12 +- dot/rpc/modules/api_mocks.go | 3 - dot/rpc/modules/childstate.go | 64 +------- dot/rpc/modules/childstate_test.go | 190 ++++++++-------------- dot/rpc/modules/mocks/mocks.go | 70 +++----- dot/rpc/modules/mocks_test.go | 70 +++----- dot/rpc/modules/state.go | 86 +++------- dot/rpc/modules/state_integration_test.go | 28 ++-- dot/rpc/modules/state_test.go | 102 +++++------- dot/state/initialize.go | 2 +- dot/state/inmemory_storage.go | 123 +++++++------- dot/state/inmemory_storage_test.go | 83 +++++----- dot/state/storage_notify.go | 17 +- dot/state/storage_notify_test.go | 5 +- dot/state/storage_state.go | 18 +- dot/sync/block_importer.go | 6 +- internal/client/adapter/client_adapter.go | 13 +- lib/babe/babe.go | 6 +- lib/babe/mock_storage_state_test.go | 94 ++++------- 28 files changed, 425 insertions(+), 754 deletions(-) diff --git a/dot/core/messages.go b/dot/core/messages.go index b8e907899f..83f30ba390 100644 --- a/dot/core/messages.go +++ b/dot/core/messages.go @@ -19,10 +19,11 @@ func (s *Service) validateTransaction(head *types.Header, rt runtime.Instance, tx types.Extrinsic) (validity *transaction.Validity, err error) { s.storageState.Lock() - ts, err := s.storageState.TrieState(&head.StateRoot) + bhash := head.Hash() + ts, err := s.storageState.TrieState(&bhash) s.storageState.Unlock() if err != nil { - return nil, fmt.Errorf("cannot get trie state from storage for root %s: %w", head.StateRoot, err) + return nil, fmt.Errorf("cannot get trie state from storage for block hash %s: %w", bhash.String(), err) } rt.SetContextStorage(ts) diff --git a/dot/core/messages_test.go b/dot/core/messages_test.go index 77f92e929c..111a0b68ee 100644 --- a/dot/core/messages_test.go +++ b/dot/core/messages_test.go @@ -114,6 +114,7 @@ func TestService_TransactionsCount(t *testing.T) { func TestServiceHandleTransactionMessage(t *testing.T) { testEmptyHeader := types.NewEmptyHeader() + headerHash := testEmptyHeader.Hash() testExtrinsic := []types.Extrinsic{{1, 2, 3}} ctrl := gomock.NewController(t) @@ -222,7 +223,7 @@ func TestServiceHandleTransactionMessage(t *testing.T) { }, }, mockStorageState: &mockStorageState{ - input: &common.Hash{}, + input: &headerHash, err: errDummyErr, }, args: args{ @@ -232,8 +233,8 @@ func TestServiceHandleTransactionMessage(t *testing.T) { }, }, expErr: errDummyErr, - expErrMsg: "validating transaction from peerID D1KeRhQ: cannot get trie state from storage" + - " for root 0x0000000000000000000000000000000000000000000000000000000000000000: dummy error for testing", + expErrMsg: "validating transaction from peerID D1KeRhQ: cannot get trie state from storage for block " + + "hash 0xdcdd89927d8a348e00257e1ecc8617f45edb5118efff3ea2f9961b2ad9b7690a: dummy error for testing", }, { name: "runtime.ErrInvalidTransaction", @@ -257,7 +258,7 @@ func TestServiceHandleTransactionMessage(t *testing.T) { callsBestBlockHash: true, }, mockStorageState: &mockStorageState{ - input: &common.Hash{}, + input: &headerHash, trieState: &storage.InMemoryTrieState{}, }, mockRuntime: &mockRuntime{ @@ -301,7 +302,7 @@ func TestServiceHandleTransactionMessage(t *testing.T) { callsBestBlockHash: true, }, mockStorageState: &mockStorageState{ - input: &common.Hash{}, + input: &headerHash, trieState: &storage.InMemoryTrieState{}, }, mockTxnState: &mockTxnState{ diff --git a/dot/core/mock_state_test.go b/dot/core/mock_state_test.go index b09a7e0d37..b337079090 100644 --- a/dot/core/mock_state_test.go +++ b/dot/core/mock_state_test.go @@ -927,18 +927,18 @@ func (m *MockStorageState) EXPECT() *MockStorageStateMockRecorder { } // Entries mocks base method. -func (m *MockStorageState) Entries(root *common.Hash) (map[string][]byte, error) { +func (m *MockStorageState) Entries(bhash *common.Hash) (map[string][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Entries", root) + ret := m.ctrl.Call(m, "Entries", bhash) ret0, _ := ret[0].(map[string][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Entries indicates an expected call of Entries. -func (mr *MockStorageStateMockRecorder) Entries(root any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) Entries(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageState)(nil).Entries), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageState)(nil).Entries), bhash) } // GenerateTrieProof mocks base method. @@ -957,123 +957,93 @@ func (mr *MockStorageStateMockRecorder) GenerateTrieProof(stateRoot, keys any) * } // GetKeysWithPrefix mocks base method. -func (m *MockStorageState) GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) { +func (m *MockStorageState) GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetKeysWithPrefix", root, prefix) + ret := m.ctrl.Call(m, "GetKeysWithPrefix", bhash, prefix) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetKeysWithPrefix indicates an expected call of GetKeysWithPrefix. -func (mr *MockStorageStateMockRecorder) GetKeysWithPrefix(root, prefix any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetKeysWithPrefix(bhash, prefix any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageState)(nil).GetKeysWithPrefix), root, prefix) -} - -// GetStateRootFromBlock mocks base method. -func (m *MockStorageState) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStateRootFromBlock", bhash) - ret0, _ := ret[0].(*common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStateRootFromBlock indicates an expected call of GetStateRootFromBlock. -func (mr *MockStorageStateMockRecorder) GetStateRootFromBlock(bhash any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStateRootFromBlock", reflect.TypeOf((*MockStorageState)(nil).GetStateRootFromBlock), bhash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageState)(nil).GetKeysWithPrefix), bhash, prefix) } // GetStorage mocks base method. -func (m *MockStorageState) GetStorage(root *common.Hash, key []byte) ([]byte, error) { +func (m *MockStorageState) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorage", root, key) + ret := m.ctrl.Call(m, "GetStorage", bhash, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorage indicates an expected call of GetStorage. -func (mr *MockStorageStateMockRecorder) GetStorage(root, key any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageState)(nil).GetStorage), root, key) -} - -// GetStorageByBlockHash mocks base method. -func (m *MockStorageState) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageByBlockHash", bhash, key) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStorageByBlockHash indicates an expected call of GetStorageByBlockHash. -func (mr *MockStorageStateMockRecorder) GetStorageByBlockHash(bhash, key any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorage(bhash, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageByBlockHash", reflect.TypeOf((*MockStorageState)(nil).GetStorageByBlockHash), bhash, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageState)(nil).GetStorage), bhash, key) } // GetStorageChild mocks base method. -func (m *MockStorageState) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) { +func (m *MockStorageState) GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageChild", root, keyToChild) + ret := m.ctrl.Call(m, "GetStorageChild", bhash, keyToChild) ret0, _ := ret[0].(trie.Trie) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageChild indicates an expected call of GetStorageChild. -func (mr *MockStorageStateMockRecorder) GetStorageChild(root, keyToChild any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorageChild(bhash, keyToChild any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageChild), root, keyToChild) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageChild), bhash, keyToChild) } // GetStorageFromChild mocks base method. -func (m *MockStorageState) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) { +func (m *MockStorageState) GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageFromChild", root, keyToChild, key) + ret := m.ctrl.Call(m, "GetStorageFromChild", bhash, keyToChild, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageFromChild indicates an expected call of GetStorageFromChild. -func (mr *MockStorageStateMockRecorder) GetStorageFromChild(root, keyToChild, key any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorageFromChild(bhash, keyToChild, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageFromChild), root, keyToChild, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageFromChild), bhash, keyToChild, key) } // LoadCode mocks base method. -func (m *MockStorageState) LoadCode(arg0 *common.Hash) ([]byte, error) { +func (m *MockStorageState) LoadCode(bhash *common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCode", arg0) + ret := m.ctrl.Call(m, "LoadCode", bhash) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCode indicates an expected call of LoadCode. -func (mr *MockStorageStateMockRecorder) LoadCode(arg0 any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCode(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), bhash) } // LoadCodeHash mocks base method. -func (m *MockStorageState) LoadCodeHash(arg0 *common.Hash) (common.Hash, error) { +func (m *MockStorageState) LoadCodeHash(bhash *common.Hash) (common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCodeHash", arg0) + ret := m.ctrl.Call(m, "LoadCodeHash", bhash) ret0, _ := ret[0].(common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCodeHash indicates an expected call of LoadCodeHash. -func (mr *MockStorageStateMockRecorder) LoadCodeHash(arg0 any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCodeHash(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), bhash) } // Lock mocks base method. @@ -1130,18 +1100,18 @@ func (mr *MockStorageStateMockRecorder) StoreTrie(arg0, arg1 any) *gomock.Call { } // TrieState mocks base method. -func (m *MockStorageState) TrieState(root *common.Hash) (storage0.TrieState, error) { +func (m *MockStorageState) TrieState(bhash *common.Hash) (storage0.TrieState, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TrieState", root) + ret := m.ctrl.Call(m, "TrieState", bhash) ret0, _ := ret[0].(storage0.TrieState) ret1, _ := ret[1].(error) return ret0, ret1 } // TrieState indicates an expected call of TrieState. -func (mr *MockStorageStateMockRecorder) TrieState(root any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) TrieState(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrieState", reflect.TypeOf((*MockStorageState)(nil).TrieState), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrieState", reflect.TypeOf((*MockStorageState)(nil).TrieState), bhash) } // Unlock mocks base method. diff --git a/dot/core/service.go b/dot/core/service.go index 018953b984..53e0c69063 100644 --- a/dot/core/service.go +++ b/dot/core/service.go @@ -487,13 +487,7 @@ func (s *Service) maintainTransactionPool(block *types.Block, bestBlockHash comm s.transactionState.RemoveExtrinsic(ext) } - stateRoot, err := s.storageState.GetStateRootFromBlock(&bestBlockHash) - if err != nil { - logger.Errorf("could not get state root from block %s: %w", bestBlockHash, err) - return err - } - - ts, err := s.storageState.TrieState(stateRoot) + ts, err := s.storageState.TrieState(&bestBlockHash) if err != nil { logger.Errorf(err.Error()) return err @@ -586,12 +580,7 @@ func (s *Service) HandleSubmittedExtrinsic(ext types.Extrinsic) error { bestBlockHash := s.blockState.BestBlockHash() - stateRoot, err := s.storageState.GetStateRootFromBlock(&bestBlockHash) - if err != nil { - return fmt.Errorf("could not get state root from block %s: %w", bestBlockHash, err) - } - - ts, err := s.storageState.TrieState(stateRoot) + ts, err := s.storageState.TrieState(&bestBlockHash) if err != nil { return err } @@ -679,15 +668,7 @@ func (s *Service) buildExternalTransaction(rt runtime.Instance, ext types.Extrin func prepareRuntime(blockHash *common.Hash, storageState state.StorageState, blockState state.BlockState) (instance runtime.Instance, err error) { - var stateRootHash *common.Hash - if blockHash != nil { - stateRootHash, err = storageState.GetStateRootFromBlock(blockHash) - if err != nil { - return nil, fmt.Errorf("getting state root from block hash: %w", err) - } - } - - trieState, err := storageState.TrieState(stateRootHash) + trieState, err := storageState.TrieState(blockHash) if err != nil { return nil, fmt.Errorf("getting trie state: %w", err) } diff --git a/dot/core/service_integration_test.go b/dot/core/service_integration_test.go index f235df7085..fbb9adcfd1 100644 --- a/dot/core/service_integration_test.go +++ b/dot/core/service_integration_test.go @@ -589,9 +589,8 @@ func TestService_HandleRuntimeChanges(t *testing.T) { require.NoError(t, err) genesisBlockHash := genesisHeader.Hash() - genesisStateRoot := genesisHeader.StateRoot - ts, err := s.storageState.TrieState(&genesisStateRoot) // Pass genesis root + ts, err := s.storageState.TrieState(&genesisBlockHash) require.NoError(t, err) firstBlockHash := createBlockUsingOldRuntime(t, genesisBlockHash, ts, s.blockState) diff --git a/dot/core/service_test.go b/dot/core/service_test.go index 7065e250bd..81c8b2da03 100644 --- a/dot/core/service_test.go +++ b/dot/core/service_test.go @@ -651,7 +651,6 @@ func Test_Service_maintainTransactionPool(t *testing.T) { mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{1}).Return(&rtstorage.InMemoryTrieState{}, nil) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{1}).Return(&common.Hash{1}, nil) service := &Service{ transactionState: mockTxnState, blockState: mockBlockState, @@ -718,7 +717,6 @@ func Test_Service_maintainTransactionPool(t *testing.T) { mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{1}).Return(&rtstorage.InMemoryTrieState{}, nil) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{1}).Return(&common.Hash{1}, nil) service := &Service{ transactionState: mockTxnState, blockState: mockBlockStateOk, @@ -1158,23 +1156,10 @@ func TestServiceGetRuntimeVersion(t *testing.T) { assert.Equal(t, exp, res) } - t.Run("get_state_root_err", func(t *testing.T) { - t.Parallel() - ctrl := gomock.NewController(t) - mockStorageState := NewMockStorageState(ctrl) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(nil, errDummyErr) - service := &Service{ - storageState: mockStorageState, - } - const expectedErrMessage = "setting up runtime: getting state root from block hash: dummy error for testing" - execTest(t, service, &common.Hash{}, runtime.Version{}, errDummyErr, expectedErrMessage) - }) - t.Run("trie_state_err", func(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockStorageState := NewMockStorageState(ctrl) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(nil, errDummyErr) service := &Service{ storageState: mockStorageState, @@ -1187,7 +1172,6 @@ func TestServiceGetRuntimeVersion(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockStorageState := NewMockStorageState(ctrl) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(ts, nil).MaxTimes(2) mockBlockState := NewMockBlockState(ctrl) @@ -1204,7 +1188,6 @@ func TestServiceGetRuntimeVersion(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) mockStorageState := NewMockStorageState(ctrl) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil).MaxTimes(2) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(ts, nil).MaxTimes(2) runtimeMock := NewMockInstance(ctrl) @@ -1248,7 +1231,6 @@ func TestServiceHandleSubmittedExtrinsic(t *testing.T) { ctrl := gomock.NewController(t) mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(nil, errDummyErr) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockBlockState := NewMockBlockState(ctrl) mockBlockState.EXPECT().BestBlockHash().Return(common.Hash{}) @@ -1273,7 +1255,6 @@ func TestServiceHandleSubmittedExtrinsic(t *testing.T) { mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(&rtstorage.InMemoryTrieState{}, nil) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockTxnState := NewMockTransactionState(ctrl) mockTxnState.EXPECT().Exists(nil).MaxTimes(2) @@ -1297,7 +1278,6 @@ func TestServiceHandleSubmittedExtrinsic(t *testing.T) { mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(&rtstorage.InMemoryTrieState{}, nil) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockTxnState := NewMockTransactionState(ctrl) mockTxnState.EXPECT().Exists(types.Extrinsic{}) @@ -1354,7 +1334,6 @@ func TestServiceHandleSubmittedExtrinsic(t *testing.T) { mockStorageState := NewMockStorageState(ctrl) mockStorageState.EXPECT().TrieState(&common.Hash{}).Return(&rtstorage.InMemoryTrieState{}, nil) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(&common.Hash{}, nil) mockTxnState := NewMockTransactionState(ctrl) mockTxnState.EXPECT().Exists(types.Extrinsic{}).MaxTimes(2) @@ -1383,18 +1362,6 @@ func TestServiceGetMetadata(t *testing.T) { assert.Equal(t, exp, res) } - t.Run("get_state_root_error", func(t *testing.T) { - t.Parallel() - ctrl := gomock.NewController(t) - mockStorageState := NewMockStorageState(ctrl) - mockStorageState.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(nil, errDummyErr) - service := &Service{ - storageState: mockStorageState, - } - const expectedErrMessage = "setting up runtime: getting state root from block hash: dummy error for testing" - execTest(t, service, &common.Hash{}, nil, errDummyErr, expectedErrMessage) - }) - t.Run("trie_state_error", func(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) diff --git a/dot/node.go b/dot/node.go index d6ee8c4699..088edce771 100644 --- a/dot/node.go +++ b/dot/node.go @@ -525,7 +525,7 @@ func (nodeBuilder) loadRuntime(config *cfg.Config, ns *runtime.NodeStorage, runtimeCode := make(map[string]runtime.Instance) for i := range blocks { hash := &blocks[i] - code, err := stateSrvc.Storage.GetStorageByBlockHash(hash, []byte(":code")) + code, err := stateSrvc.Storage.GetStorage(hash, []byte(":code")) if err != nil { return err } diff --git a/dot/node_integration_test.go b/dot/node_integration_test.go index 39b0ea403a..7c9a497e39 100644 --- a/dot/node_integration_test.go +++ b/dot/node_integration_test.go @@ -197,7 +197,7 @@ func Test_nodeBuilder_loadRuntime(t *testing.T) { blocks := stateSrvc.Block.GetNonFinalisedBlocks() for i := range blocks { hash := &blocks[i] - code, err := stateSrvc.Storage.GetStorageByBlockHash(hash, []byte(":code")) + code, err := stateSrvc.Storage.GetStorage(hash, []byte(":code")) require.NoError(t, err) require.NotEmpty(t, code) } diff --git a/dot/rpc/interfaces.go b/dot/rpc/interfaces.go index cecffba680..ea6537b392 100644 --- a/dot/rpc/interfaces.go +++ b/dot/rpc/interfaces.go @@ -20,13 +20,11 @@ import ( // StorageAPI is the interface for the storage state type StorageAPI interface { - GetStorage(root *common.Hash, key []byte) ([]byte, error) - GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) - GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) - GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) - Entries(root *common.Hash) (map[string][]byte, error) - GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) - GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) + GetStorage(bhash *common.Hash, key []byte) ([]byte, error) + GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) + GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) + Entries(bhash *common.Hash) (map[string][]byte, error) + GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) RegisterStorageObserver(observer state.Observer) UnregisterStorageObserver(observer state.Observer) } diff --git a/dot/rpc/modules/api.go b/dot/rpc/modules/api.go index 9abc40a4d8..91c296b703 100644 --- a/dot/rpc/modules/api.go +++ b/dot/rpc/modules/api.go @@ -18,13 +18,11 @@ import ( // StorageAPI is the interface for the storage state type StorageAPI interface { - GetStorage(root *common.Hash, key []byte) ([]byte, error) - GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) - GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) - GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) - Entries(root *common.Hash) (map[string][]byte, error) - GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) - GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) + GetStorage(bhash *common.Hash, key []byte) ([]byte, error) + GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) + GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) + Entries(bhash *common.Hash) (map[string][]byte, error) + GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) RegisterStorageObserver(observer state.Observer) UnregisterStorageObserver(observer state.Observer) } diff --git a/dot/rpc/modules/api_mocks.go b/dot/rpc/modules/api_mocks.go index 931d14ec05..6f527c6b0e 100644 --- a/dot/rpc/modules/api_mocks.go +++ b/dot/rpc/modules/api_mocks.go @@ -18,11 +18,8 @@ func NewMockAnyStorageAPI(ctrl *gomock.Controller) *modulesmocks.MockStorageAPI m.EXPECT().GetStorageFromChild(gomock.Any(), gomock.Any(), gomock.Any()). Return(nil, nil).AnyTimes() m.EXPECT().Entries(gomock.Any()).Return(nil, nil).AnyTimes() - m.EXPECT().GetStorageByBlockHash(gomock.Any(), gomock.Any()). - Return(nil, nil).AnyTimes() m.EXPECT().RegisterStorageObserver(gomock.Any()).AnyTimes() m.EXPECT().UnregisterStorageObserver(gomock.Any()).AnyTimes() - m.EXPECT().GetStateRootFromBlock(gomock.Any()).Return(nil, nil).AnyTimes() m.EXPECT().GetKeysWithPrefix(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes() return m } diff --git a/dot/rpc/modules/childstate.go b/dot/rpc/modules/childstate.go index 270e2cb54b..1d88733b2a 100644 --- a/dot/rpc/modules/childstate.go +++ b/dot/rpc/modules/childstate.go @@ -53,20 +53,7 @@ func NewChildStateModule(s StorageAPI, b BlockAPI) *ChildStateModule { // GetKeys returns the keys from the specified child storage. The keys can also be filtered based on a prefix. func (cs *ChildStateModule) GetKeys(_ *http.Request, req *GetKeysRequest, res *[]string) error { - var hash common.Hash - - if req.Hash == nil { - hash = cs.blockAPI.BestBlockHash() - } else { - hash = *req.Hash - } - - stateRoot, err := cs.storageAPI.GetStateRootFromBlock(&hash) - if err != nil { - return err - } - - trie, err := cs.storageAPI.GetStorageChild(stateRoot, req.Key) + trie, err := cs.storageAPI.GetStorageChild(req.Hash, req.Key) if err != nil { return err } @@ -83,20 +70,7 @@ func (cs *ChildStateModule) GetKeys(_ *http.Request, req *GetKeysRequest, res *[ // GetStorageSize returns the size of a child storage entry. func (cs *ChildStateModule) GetStorageSize(_ *http.Request, req *GetChildStorageRequest, res *uint64) error { - var hash common.Hash - - if req.Hash == nil { - hash = cs.blockAPI.BestBlockHash() - } else { - hash = *req.Hash - } - - stateRoot, err := cs.storageAPI.GetStateRootFromBlock(&hash) - if err != nil { - return err - } - - item, err := cs.storageAPI.GetStorageFromChild(stateRoot, req.KeyChild, req.EntryKey) + item, err := cs.storageAPI.GetStorageFromChild(req.Hash, req.KeyChild, req.EntryKey) if err != nil { return err } @@ -110,20 +84,7 @@ func (cs *ChildStateModule) GetStorageSize(_ *http.Request, req *GetChildStorage // GetStorageHash returns the hash of a child storage entry func (cs *ChildStateModule) GetStorageHash(_ *http.Request, req *GetStorageHash, res *string) error { - var hash common.Hash - - if req.Hash == nil { - hash = cs.blockAPI.BestBlockHash() - } else { - hash = *req.Hash - } - - stateRoot, err := cs.storageAPI.GetStateRootFromBlock(&hash) - if err != nil { - return err - } - - item, err := cs.storageAPI.GetStorageFromChild(stateRoot, req.KeyChild, req.EntryKey) + item, err := cs.storageAPI.GetStorageFromChild(req.Hash, req.KeyChild, req.EntryKey) if err != nil { return err } @@ -138,24 +99,7 @@ func (cs *ChildStateModule) GetStorageHash(_ *http.Request, req *GetStorageHash, // GetStorage returns a child storage entry. func (cs *ChildStateModule) GetStorage( _ *http.Request, req *ChildStateStorageRequest, res *StateStorageResponse) error { - var ( - item []byte - err error - hash common.Hash - ) - - if req.Hash == nil { - hash = cs.blockAPI.BestBlockHash() - } else { - hash = *req.Hash - } - - stateRoot, err := cs.storageAPI.GetStateRootFromBlock(&hash) - if err != nil { - return err - } - - item, err = cs.storageAPI.GetStorageFromChild(stateRoot, req.ChildStorageKey, req.Key) + item, err := cs.storageAPI.GetStorageFromChild(req.Hash, req.ChildStorageKey, req.Key) if err != nil { return err } diff --git a/dot/rpc/modules/childstate_test.go b/dot/rpc/modules/childstate_test.go index 6e8ed3e759..a878b81281 100644 --- a/dot/rpc/modules/childstate_test.go +++ b/dot/rpc/modules/childstate_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" ) -func createTestTrieState(t *testing.T) (trie.Trie, common.Hash) { +func createTestTrieState(t *testing.T) trie.Trie { t.Helper() _, genesisTrie, _ := newWestendLocalGenesisWithTrieAndHeader(t) @@ -33,16 +33,13 @@ func createTestTrieState(t *testing.T) (trie.Trie, common.Hash) { err = tr.SetChildStorage([]byte(":child_storage_key"), []byte(":another_child"), []byte("value")) require.NoError(t, err) - stateRoot, err := tr.Root() - require.NoError(t, err) - - return genesisTrie, stateRoot + return genesisTrie } func TestChildStateModule_GetKeys(t *testing.T) { ctrl := gomock.NewController(t) - tr, sr := createTestTrieState(t) + tr := createTestTrieState(t) expKeys := tr.GetKeysWithPrefix([]byte{}) expHexKeys := make([]string, len(expKeys)) @@ -51,24 +48,29 @@ func TestChildStateModule_GetKeys(t *testing.T) { } mockStorageAPI := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI1 := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI2 := apimocks.NewMockStorageAPI(ctrl) - mockBlockAPI := apimocks.NewMockBlockAPI(ctrl) + mockErrorStorageAPI := apimocks.NewMockStorageAPI(ctrl) hash := common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") - mockBlockAPI.EXPECT().BestBlockHash().Return(hash).Times(2) - - mockStorageAPI.EXPECT().GetStateRootFromBlock(&hash).Return(&sr, nil).Times(2) - mockStorageAPI.EXPECT().GetStorageChild(&sr, []byte(":child_storage_key")). - Return(tr, nil).Times(2) - mockErrorStorageAPI1.EXPECT().GetStateRootFromBlock(&common.Hash{}).Return(nil, nil) - mockErrorStorageAPI1.EXPECT().GetStorageChild((*common.Hash)(nil), []byte(nil)). - Return(nil, errors.New("GetStorageChild error")) - - mockErrorStorageAPI2.EXPECT().GetStateRootFromBlock(&hash).Return(nil, errors.New("GetStateRootFromBlock error")) - - childStateModule := NewChildStateModule(mockStorageAPI, mockBlockAPI) + mockStorageAPI.EXPECT(). + GetStorageChild((*common.Hash)(nil), []byte(":child_storage_key")). + Return(tr, nil). + MaxTimes(2) + mockStorageAPI.EXPECT(). + GetStorageChild(&hash, []byte(":child_storage_key")). + Return(tr, nil). + MaxTimes(2) + + mockErrorStorageAPI.EXPECT(). + GetStorageChild((*common.Hash)(nil), []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) + mockErrorStorageAPI.EXPECT(). + GetStorageChild(&common.Hash{}, []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) + + childStateModule := NewChildStateModule(mockStorageAPI, nil) type fields struct { storageAPI StorageAPI blockAPI BlockAPI @@ -114,8 +116,8 @@ func TestChildStateModule_GetKeys(t *testing.T) { { name: "GetStorageChild_error", fields: fields{ - mockErrorStorageAPI1, - mockBlockAPI, + mockErrorStorageAPI, + nil, }, args: args{ req: &GetKeysRequest{ @@ -124,19 +126,6 @@ func TestChildStateModule_GetKeys(t *testing.T) { }, expErr: errors.New("GetStorageChild error"), }, - { - name: "GetStateRootFromBlock_error", - fields: fields{ - mockErrorStorageAPI2, - mockBlockAPI, - }, - args: args{ - req: &GetKeysRequest{ - Key: []byte(":child_storage_key"), - }, - }, - expErr: errors.New("GetStateRootFromBlock error"), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -159,25 +148,29 @@ func TestChildStateModule_GetKeys(t *testing.T) { func TestChildStateModule_GetStorageSize(t *testing.T) { ctrl := gomock.NewController(t) - _, sr := createTestTrieState(t) - mockStorageAPI := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI1 := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI2 := apimocks.NewMockStorageAPI(ctrl) + mockErrorStorageAPI := apimocks.NewMockStorageAPI(ctrl) mockBlockAPI := apimocks.NewMockBlockAPI(ctrl) hash := common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") - mockBlockAPI.EXPECT().BestBlockHash().Return(hash) - - mockStorageAPI.EXPECT().GetStateRootFromBlock(&hash).Return(&sr, nil).Times(2) - mockStorageAPI.EXPECT().GetStorageFromChild(&sr, []byte(":child_storage_key"), []byte(":child_first")). - Return([]byte(""), nil).Times(2) - - mockErrorStorageAPI1.EXPECT().GetStateRootFromBlock(&hash).Return(nil, nil) - mockErrorStorageAPI1.EXPECT().GetStorageFromChild((*common.Hash)(nil), []byte(nil), []byte(nil)). - Return(nil, errors.New("GetStorageChild error")) - mockErrorStorageAPI2.EXPECT().GetStateRootFromBlock(&hash).Return(nil, errors.New("GetStateRootFromBlock error")) + mockStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte(""), nil). + MaxTimes(2) + mockStorageAPI.EXPECT(). + GetStorageFromChild((*common.Hash)(nil), []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte(""), nil). + MaxTimes(2) + + mockErrorStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(nil), []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) + mockErrorStorageAPI.EXPECT(). + GetStorageFromChild((*common.Hash)(nil), []byte(nil), []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) childStateModule := NewChildStateModule(mockStorageAPI, mockBlockAPI) type fields struct { @@ -227,7 +220,7 @@ func TestChildStateModule_GetStorageSize(t *testing.T) { { name: "GetStorageChild_error", fields: fields{ - mockErrorStorageAPI1, + mockErrorStorageAPI, mockBlockAPI, }, args: args{ @@ -237,19 +230,6 @@ func TestChildStateModule_GetStorageSize(t *testing.T) { }, expErr: errors.New("GetStorageChild error"), }, - { - name: "GetStateRootFromBlock_error", - fields: fields{ - mockErrorStorageAPI2, - mockBlockAPI, - }, - args: args{ - req: &GetChildStorageRequest{ - Hash: &hash, - }, - }, - expErr: errors.New("GetStateRootFromBlock error"), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -272,25 +252,25 @@ func TestChildStateModule_GetStorageSize(t *testing.T) { func TestChildStateModule_GetStorageHash(t *testing.T) { ctrl := gomock.NewController(t) - _, sr := createTestTrieState(t) - mockStorageAPI := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI1 := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI2 := apimocks.NewMockStorageAPI(ctrl) + mockErrorStorageAPI := apimocks.NewMockStorageAPI(ctrl) mockBlockAPI := apimocks.NewMockBlockAPI(ctrl) hash := common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") - mockBlockAPI.EXPECT().BestBlockHash().Return(hash) - mockStorageAPI.EXPECT().GetStateRootFromBlock(&hash).Return(&sr, nil).Times(2) - mockStorageAPI.EXPECT().GetStorageFromChild(&sr, []byte(":child_storage_key"), []byte(":child_first")). - Return([]byte(""), nil).Times(2) + mockStorageAPI.EXPECT(). + GetStorageFromChild((*common.Hash)(nil), []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte(""), nil). + MaxTimes(2) + mockStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte(""), nil). + MaxTimes(2) - mockErrorStorageAPI1.EXPECT().GetStateRootFromBlock(&hash).Return(nil, nil) - mockErrorStorageAPI1.EXPECT().GetStorageFromChild((*common.Hash)(nil), []byte(nil), []byte(nil)). - Return(nil, errors.New("GetStorageChild error")) - - mockErrorStorageAPI2.EXPECT().GetStateRootFromBlock(&hash).Return(nil, errors.New("GetStateRootFromBlock error")) + mockErrorStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(nil), []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) childStateModule := NewChildStateModule(mockStorageAPI, mockBlockAPI) type fields struct { @@ -340,7 +320,7 @@ func TestChildStateModule_GetStorageHash(t *testing.T) { { name: "GetStorageChild_error", fields: fields{ - mockErrorStorageAPI1, + mockErrorStorageAPI, mockBlockAPI, }, args: args{ @@ -350,19 +330,6 @@ func TestChildStateModule_GetStorageHash(t *testing.T) { }, expErr: errors.New("GetStorageChild error"), }, - { - name: "GetStateRootFromBlock_error", - fields: fields{ - mockErrorStorageAPI2, - mockBlockAPI, - }, - args: args{ - req: &GetStorageHash{ - Hash: &hash, - }, - }, - expErr: errors.New("GetStateRootFromBlock error"), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -385,25 +352,25 @@ func TestChildStateModule_GetStorageHash(t *testing.T) { func TestChildStateModule_GetStorage(t *testing.T) { ctrl := gomock.NewController(t) - _, sr := createTestTrieState(t) - mockStorageAPI := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI1 := apimocks.NewMockStorageAPI(ctrl) - mockErrorStorageAPI2 := apimocks.NewMockStorageAPI(ctrl) + mockErrorStorageAPI := apimocks.NewMockStorageAPI(ctrl) mockBlockAPI := apimocks.NewMockBlockAPI(ctrl) hash := common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") - mockBlockAPI.EXPECT().BestBlockHash().Return(hash) - mockStorageAPI.EXPECT().GetStateRootFromBlock(&hash).Return(&sr, nil).Times(2) - mockStorageAPI.EXPECT().GetStorageFromChild(&sr, []byte(":child_storage_key"), []byte(":child_first")). - Return([]byte("test"), nil).Times(2) + mockStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte("test"), nil). + MaxTimes(2) + mockStorageAPI.EXPECT(). + GetStorageFromChild((*common.Hash)(nil), []byte(":child_storage_key"), []byte(":child_first")). + Return([]byte("test"), nil). + MaxTimes(2) - mockErrorStorageAPI1.EXPECT().GetStateRootFromBlock(&hash).Return(nil, nil) - mockErrorStorageAPI1.EXPECT().GetStorageFromChild((*common.Hash)(nil), []byte(nil), []byte(nil)). - Return(nil, errors.New("GetStorageChild error")) - - mockErrorStorageAPI2.EXPECT().GetStateRootFromBlock(&hash).Return(nil, errors.New("GetStateRootFromBlock error")) + mockErrorStorageAPI.EXPECT(). + GetStorageFromChild(&hash, []byte(nil), []byte(nil)). + Return(nil, errors.New("GetStorageChild error")). + MaxTimes(2) childStateModule := NewChildStateModule(mockStorageAPI, mockBlockAPI) type fields struct { @@ -453,7 +420,7 @@ func TestChildStateModule_GetStorage(t *testing.T) { { name: "GetStorageChild_error", fields: fields{ - mockErrorStorageAPI1, + mockErrorStorageAPI, mockBlockAPI, }, args: args{ @@ -463,19 +430,6 @@ func TestChildStateModule_GetStorage(t *testing.T) { }, expErr: errors.New("GetStorageChild error"), }, - { - name: "GetStateRootFromBlock_error", - fields: fields{ - mockErrorStorageAPI2, - mockBlockAPI, - }, - args: args{ - req: &ChildStateStorageRequest{ - Hash: &hash, - }, - }, - expErr: errors.New("GetStateRootFromBlock error"), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/dot/rpc/modules/mocks/mocks.go b/dot/rpc/modules/mocks/mocks.go index f951c97339..03ecaa06a6 100644 --- a/dot/rpc/modules/mocks/mocks.go +++ b/dot/rpc/modules/mocks/mocks.go @@ -50,108 +50,78 @@ func (m *MockStorageAPI) EXPECT() *MockStorageAPIMockRecorder { } // Entries mocks base method. -func (m *MockStorageAPI) Entries(root *common.Hash) (map[string][]byte, error) { +func (m *MockStorageAPI) Entries(bhash *common.Hash) (map[string][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Entries", root) + ret := m.ctrl.Call(m, "Entries", bhash) ret0, _ := ret[0].(map[string][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Entries indicates an expected call of Entries. -func (mr *MockStorageAPIMockRecorder) Entries(root any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) Entries(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageAPI)(nil).Entries), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageAPI)(nil).Entries), bhash) } // GetKeysWithPrefix mocks base method. -func (m *MockStorageAPI) GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) { +func (m *MockStorageAPI) GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetKeysWithPrefix", root, prefix) + ret := m.ctrl.Call(m, "GetKeysWithPrefix", bhash, prefix) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetKeysWithPrefix indicates an expected call of GetKeysWithPrefix. -func (mr *MockStorageAPIMockRecorder) GetKeysWithPrefix(root, prefix any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetKeysWithPrefix(bhash, prefix any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageAPI)(nil).GetKeysWithPrefix), root, prefix) -} - -// GetStateRootFromBlock mocks base method. -func (m *MockStorageAPI) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStateRootFromBlock", bhash) - ret0, _ := ret[0].(*common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStateRootFromBlock indicates an expected call of GetStateRootFromBlock. -func (mr *MockStorageAPIMockRecorder) GetStateRootFromBlock(bhash any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStateRootFromBlock", reflect.TypeOf((*MockStorageAPI)(nil).GetStateRootFromBlock), bhash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageAPI)(nil).GetKeysWithPrefix), bhash, prefix) } // GetStorage mocks base method. -func (m *MockStorageAPI) GetStorage(root *common.Hash, key []byte) ([]byte, error) { +func (m *MockStorageAPI) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorage", root, key) + ret := m.ctrl.Call(m, "GetStorage", bhash, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorage indicates an expected call of GetStorage. -func (mr *MockStorageAPIMockRecorder) GetStorage(root, key any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageAPI)(nil).GetStorage), root, key) -} - -// GetStorageByBlockHash mocks base method. -func (m *MockStorageAPI) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageByBlockHash", bhash, key) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStorageByBlockHash indicates an expected call of GetStorageByBlockHash. -func (mr *MockStorageAPIMockRecorder) GetStorageByBlockHash(bhash, key any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorage(bhash, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageByBlockHash", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageByBlockHash), bhash, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageAPI)(nil).GetStorage), bhash, key) } // GetStorageChild mocks base method. -func (m *MockStorageAPI) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) { +func (m *MockStorageAPI) GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageChild", root, keyToChild) + ret := m.ctrl.Call(m, "GetStorageChild", bhash, keyToChild) ret0, _ := ret[0].(trie.Trie) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageChild indicates an expected call of GetStorageChild. -func (mr *MockStorageAPIMockRecorder) GetStorageChild(root, keyToChild any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorageChild(bhash, keyToChild any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageChild), root, keyToChild) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageChild), bhash, keyToChild) } // GetStorageFromChild mocks base method. -func (m *MockStorageAPI) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) { +func (m *MockStorageAPI) GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageFromChild", root, keyToChild, key) + ret := m.ctrl.Call(m, "GetStorageFromChild", bhash, keyToChild, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageFromChild indicates an expected call of GetStorageFromChild. -func (mr *MockStorageAPIMockRecorder) GetStorageFromChild(root, keyToChild, key any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorageFromChild(bhash, keyToChild, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageFromChild), root, keyToChild, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageFromChild), bhash, keyToChild, key) } // RegisterStorageObserver mocks base method. diff --git a/dot/rpc/modules/mocks_test.go b/dot/rpc/modules/mocks_test.go index a7be064aba..cd7abaf76a 100644 --- a/dot/rpc/modules/mocks_test.go +++ b/dot/rpc/modules/mocks_test.go @@ -46,108 +46,78 @@ func (m *MockStorageAPI) EXPECT() *MockStorageAPIMockRecorder { } // Entries mocks base method. -func (m *MockStorageAPI) Entries(root *common.Hash) (map[string][]byte, error) { +func (m *MockStorageAPI) Entries(bhash *common.Hash) (map[string][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Entries", root) + ret := m.ctrl.Call(m, "Entries", bhash) ret0, _ := ret[0].(map[string][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Entries indicates an expected call of Entries. -func (mr *MockStorageAPIMockRecorder) Entries(root any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) Entries(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageAPI)(nil).Entries), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageAPI)(nil).Entries), bhash) } // GetKeysWithPrefix mocks base method. -func (m *MockStorageAPI) GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) { +func (m *MockStorageAPI) GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetKeysWithPrefix", root, prefix) + ret := m.ctrl.Call(m, "GetKeysWithPrefix", bhash, prefix) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetKeysWithPrefix indicates an expected call of GetKeysWithPrefix. -func (mr *MockStorageAPIMockRecorder) GetKeysWithPrefix(root, prefix any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetKeysWithPrefix(bhash, prefix any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageAPI)(nil).GetKeysWithPrefix), root, prefix) -} - -// GetStateRootFromBlock mocks base method. -func (m *MockStorageAPI) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStateRootFromBlock", bhash) - ret0, _ := ret[0].(*common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStateRootFromBlock indicates an expected call of GetStateRootFromBlock. -func (mr *MockStorageAPIMockRecorder) GetStateRootFromBlock(bhash any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStateRootFromBlock", reflect.TypeOf((*MockStorageAPI)(nil).GetStateRootFromBlock), bhash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageAPI)(nil).GetKeysWithPrefix), bhash, prefix) } // GetStorage mocks base method. -func (m *MockStorageAPI) GetStorage(root *common.Hash, key []byte) ([]byte, error) { +func (m *MockStorageAPI) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorage", root, key) + ret := m.ctrl.Call(m, "GetStorage", bhash, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorage indicates an expected call of GetStorage. -func (mr *MockStorageAPIMockRecorder) GetStorage(root, key any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageAPI)(nil).GetStorage), root, key) -} - -// GetStorageByBlockHash mocks base method. -func (m *MockStorageAPI) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageByBlockHash", bhash, key) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStorageByBlockHash indicates an expected call of GetStorageByBlockHash. -func (mr *MockStorageAPIMockRecorder) GetStorageByBlockHash(bhash, key any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorage(bhash, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageByBlockHash", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageByBlockHash), bhash, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageAPI)(nil).GetStorage), bhash, key) } // GetStorageChild mocks base method. -func (m *MockStorageAPI) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) { +func (m *MockStorageAPI) GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageChild", root, keyToChild) + ret := m.ctrl.Call(m, "GetStorageChild", bhash, keyToChild) ret0, _ := ret[0].(trie.Trie) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageChild indicates an expected call of GetStorageChild. -func (mr *MockStorageAPIMockRecorder) GetStorageChild(root, keyToChild any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorageChild(bhash, keyToChild any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageChild), root, keyToChild) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageChild), bhash, keyToChild) } // GetStorageFromChild mocks base method. -func (m *MockStorageAPI) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) { +func (m *MockStorageAPI) GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageFromChild", root, keyToChild, key) + ret := m.ctrl.Call(m, "GetStorageFromChild", bhash, keyToChild, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageFromChild indicates an expected call of GetStorageFromChild. -func (mr *MockStorageAPIMockRecorder) GetStorageFromChild(root, keyToChild, key any) *gomock.Call { +func (mr *MockStorageAPIMockRecorder) GetStorageFromChild(bhash, keyToChild, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageFromChild), root, keyToChild, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageAPI)(nil).GetStorageFromChild), bhash, keyToChild, key) } // RegisterStorageObserver mocks base method. diff --git a/dot/rpc/modules/state.go b/dot/rpc/modules/state.go index 742b023f6f..3cbaf81428 100644 --- a/dot/rpc/modules/state.go +++ b/dot/rpc/modules/state.go @@ -194,20 +194,8 @@ func NewStateModule(net NetworkAPI, storage StorageAPI, core CoreAPI, blockAPI B // GetPairs returns the keys with prefix, leave empty to get all the keys. func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *StatePairResponse) error { - var ( - stateRootHash *common.Hash - err error - ) - - if req.Bhash != nil { - stateRootHash, err = sm.storageAPI.GetStateRootFromBlock(req.Bhash) - if err != nil { - return err - } - } - if req.Prefix == nil || *req.Prefix == "" || *req.Prefix == "0x" { - pairs, err := sm.storageAPI.Entries(stateRootHash) + pairs, err := sm.storageAPI.Entries(req.Bhash) if err != nil { return err } @@ -222,7 +210,7 @@ func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *Sta if err != nil { return fmt.Errorf("cannot convert hex prefix %s to bytes: %w", *req.Prefix, err) } - keys, err := sm.storageAPI.GetKeysWithPrefix(stateRootHash, reqBytes) + keys, err := sm.storageAPI.GetKeysWithPrefix(req.Bhash, reqBytes) if err != nil { return err } @@ -234,7 +222,7 @@ func (sm *StateModule) GetPairs(_ *http.Request, req *StatePairRequest, res *Sta *res = make([]interface{}, len(keys)) for i, key := range keys { - val, err := sm.storageAPI.GetStorage(stateRootHash, key) + val, err := sm.storageAPI.GetStorage(req.Bhash, key) if err != nil { return err } @@ -362,24 +350,15 @@ func (sm *StateModule) GetRuntimeVersion( // GetStorage Returns a storage entry at a specific block's state. // If not block hash is provided, the latest value is returned. func (sm *StateModule) GetStorage( - _ *http.Request, req *StateStorageRequest, res *StateStorageResponse) error { - var ( - item []byte - err error - ) - + _ *http.Request, + req *StateStorageRequest, + res *StateStorageResponse, +) error { reqBytes, _ := common.HexToBytes(req.Key) // no need to catch error here - if req.Bhash != nil { - item, err = sm.storageAPI.GetStorageByBlockHash(req.Bhash, reqBytes) - if err != nil { - return err - } - } else { - item, err = sm.storageAPI.GetStorage(nil, reqBytes) - if err != nil { - return err - } + item, err := sm.storageAPI.GetStorage(req.Bhash, reqBytes) + if err != nil { + return err } if len(item) > 0 { @@ -392,24 +371,15 @@ func (sm *StateModule) GetStorage( // GetStorageHash returns the blake2b hash of a storage entry at a block's state. // If no block hash is provided, the latest value is returned. func (sm *StateModule) GetStorageHash( - _ *http.Request, req *StateStorageHashRequest, res *StateStorageHashResponse) error { - var ( - item []byte - err error - ) - + _ *http.Request, + req *StateStorageHashRequest, + res *StateStorageHashResponse, +) error { reqBytes, _ := common.HexToBytes(req.Key) - if req.Bhash != nil { - item, err = sm.storageAPI.GetStorageByBlockHash(req.Bhash, reqBytes) - if err != nil { - return err - } - } else { - item, err = sm.storageAPI.GetStorage(nil, reqBytes) - if err != nil { - return err - } + item, err := sm.storageAPI.GetStorage(req.Bhash, reqBytes) + if err != nil { + return err } hash, err := common.Blake2bHash(item) @@ -425,23 +395,11 @@ func (sm *StateModule) GetStorageHash( // If no block hash is provided, the latest value is used. func (sm *StateModule) GetStorageSize( _ *http.Request, req *StateStorageSizeRequest, res *StateStorageSizeResponse) error { - var ( - item []byte - err error - ) - reqBytes, _ := common.HexToBytes(req.Key) - if req.Bhash != nil { - item, err = sm.storageAPI.GetStorageByBlockHash(req.Bhash, reqBytes) - if err != nil { - return err - } - } else { - item, err = sm.storageAPI.GetStorage(nil, reqBytes) - if err != nil { - return err - } + item, err := sm.storageAPI.GetStorage(req.Bhash, reqBytes) + if err != nil { + return err } if len(item) > 0 { @@ -487,7 +445,7 @@ func (sm *StateModule) QueryStorage( changes := make([][2]*string, 0, len(req.Keys)) for j, key := range req.Keys { - value, err := sm.storageAPI.GetStorageByBlockHash(&blockHash, common.MustHexToBytes(key)) + value, err := sm.storageAPI.GetStorage(&blockHash, common.MustHexToBytes(key)) if err != nil { return fmt.Errorf("getting value by block hash: %w", err) } @@ -531,7 +489,7 @@ func (sm *StateModule) QueryStorageAt( changes := make([][2]*string, len(request.Keys)) for i, key := range request.Keys { - value, err := sm.storageAPI.GetStorageByBlockHash(&atBlockHash, common.MustHexToBytes(key)) + value, err := sm.storageAPI.GetStorage(&atBlockHash, common.MustHexToBytes(key)) if err != nil { return fmt.Errorf("getting value by block hash: %w", err) } diff --git a/dot/rpc/modules/state_integration_test.go b/dot/rpc/modules/state_integration_test.go index ec023f0107..3f1557cf5f 100644 --- a/dot/rpc/modules/state_integration_test.go +++ b/dot/rpc/modules/state_integration_test.go @@ -59,7 +59,7 @@ func TestStateModule_GetRuntimeVersion(t *testing.T) { TransactionVersion: 12, } - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -100,7 +100,7 @@ func TestStateModule_GetRuntimeVersion(t *testing.T) { } func TestStateModule_GetPairs(t *testing.T) { - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -179,7 +179,7 @@ func TestStateModule_GetPairs(t *testing.T) { } func TestStateModule_GetStorage(t *testing.T) { - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -229,7 +229,7 @@ func TestStateModule_GetStorage(t *testing.T) { } func TestStateModule_GetStorageHash(t *testing.T) { - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -277,7 +277,7 @@ func TestStateModule_GetStorageHash(t *testing.T) { } func TestStateModule_GetStorageSize(t *testing.T) { - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -379,11 +379,11 @@ func TestStateModule_QueryStorage(t *testing.T) { mockBlockAPI.EXPECT().GetHashByNumber(uint(4)).Return(common.Hash{3, 4}, nil) mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{1, 2}, []byte{144}).Return([]byte(`value`), nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{1, 2}, []byte{128}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{1, 2}, []byte{144}).Return([]byte(`value`), nil) + mockStorageAPI.EXPECT().GetStorage(&common.Hash{1, 2}, []byte{128}). Return([]byte(`another value`), nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3, 4}, []byte{144}).Return([]byte(`value`), nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3, 4}, []byte{128}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3, 4}, []byte{144}).Return([]byte(`value`), nil) + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3, 4}, []byte{128}). Return([]byte(`another value`), nil) module := new(StateModule) @@ -403,7 +403,7 @@ func TestStateModule_QueryStorage(t *testing.T) { func TestStateModule_GetMetadata(t *testing.T) { t.Skip() // TODO: update expected_metadata (#1026) - sm, hash, _ := setupStateModule(t) + sm, hash := setupStateModule(t) randomHash, err := common.HexToHash(RandomHash) require.NoError(t, err) @@ -444,7 +444,7 @@ func TestStateModule_GetMetadata(t *testing.T) { } func TestStateModule_GetKeysPaged(t *testing.T) { - sm, _, stateRootHash := setupStateModule(t) + sm, blockHash := setupStateModule(t) testCases := []struct { name string @@ -461,7 +461,7 @@ func TestStateModule_GetKeysPaged(t *testing.T) { {name: "allKeysTestBlockHash", params: StateStorageKeyRequest{ Qty: 10, - Block: stateRootHash, + Block: blockHash, }, expected: []string{ "0x3a6368696c645f73746f726167653a64656661756c743a3a6368696c6431", "0x3a6b657931", "0x3a6b657932"}}, @@ -557,7 +557,7 @@ func TestGetReadProof_WhenReturnsProof(t *testing.T) { require.Equal(t, res.Proof, expectedProof) } -func setupStateModule(t *testing.T) (*StateModule, *common.Hash, *common.Hash) { +func setupStateModule(t *testing.T) (*StateModule, *common.Hash) { // setup service net := newNetworkService(t) chain := newTestStateService(t) @@ -607,5 +607,5 @@ func setupStateModule(t *testing.T) (*StateModule, *common.Hash, *common.Hash) { require.NoError(t, err) core := newCoreService(t, chain) - return NewStateModule(net, chain.Storage, core, nil), &hash, &sr1 + return NewStateModule(net, chain.Storage, core, nil), &hash } diff --git a/dot/rpc/modules/state_test.go b/dot/rpc/modules/state_test.go index 3d6a6764eb..822908d404 100644 --- a/dot/rpc/modules/state_test.go +++ b/dot/rpc/modules/state_test.go @@ -43,32 +43,23 @@ func TestStateModuleGetPairs(t *testing.T) { m["b"] = []byte{23, 24} mockStorageAPI := mocks.NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPI.EXPECT().GetKeysWithPrefix(&hash, common.MustHexToBytes(str)).Return([][]byte{{1}, {1}}, nil) mockStorageAPI.EXPECT().GetStorage(&hash, []byte{1}).Return([]byte{21}, nil).Times(2) mockStorageAPINil := mocks.NewMockStorageAPI(ctrl) - mockStorageAPINil.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPINil.EXPECT().Entries(&hash).Return(m, nil) mockStorageAPIGetKeysEmpty := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIGetKeysEmpty.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPIGetKeysEmpty.EXPECT().GetKeysWithPrefix(&hash, common.MustHexToBytes(str)).Return([][]byte{}, nil) mockStorageAPIGetKeysErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIGetKeysErr.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPIGetKeysErr.EXPECT().GetKeysWithPrefix(&hash, common.MustHexToBytes(str)). Return(nil, errors.New("GetKeysWithPrefix Err")) mockStorageAPIEntriesErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIEntriesErr.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPIEntriesErr.EXPECT().Entries(&hash).Return(nil, errors.New("entries Err")) - mockStorageAPIErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIErr.EXPECT().GetStateRootFromBlock(&hash).Return(nil, errors.New("GetStateRootFromBlock Err")) - mockStorageAPIGetStorageErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIGetStorageErr.EXPECT().GetStateRootFromBlock(&hash).Return(&hash, nil) mockStorageAPIGetStorageErr.EXPECT().GetKeysWithPrefix(&hash, common.MustHexToBytes(str)). Return([][]byte{{2}, {2}}, nil) mockStorageAPIGetStorageErr.EXPECT().GetStorage(&hash, []byte{2}).Return(nil, errors.New("GetStorage Err")) @@ -93,16 +84,6 @@ func TestStateModuleGetPairs(t *testing.T) { expErr error exp StatePairResponse }{ - { - name: "GetStateRootFromBlock Error", - fields: fields{nil, mockStorageAPIErr, nil}, - args: args{ - req: &StatePairRequest{ - Bhash: &hash, - }, - }, - expErr: errors.New("GetStateRootFromBlock Err"), - }, { name: "Nil Prefix OK", fields: fields{nil, mockStorageAPINil, nil}, @@ -560,14 +541,16 @@ func TestStateModuleGetStorage(t *testing.T) { reqBytes := common.MustHexToBytes("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") mockStorageAPI := mocks.NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&hash, reqBytes).Return([]byte{21}, nil) - mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes).Return([]byte{21}, nil) + mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes).Return([]byte{21}, nil).AnyTimes() + mockStorageAPI.EXPECT().GetStorage(&hash, reqBytes).Return([]byte{21}, nil).AnyTimes() mockStorageAPIErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIErr.EXPECT().GetStorageByBlockHash(&hash, reqBytes). - Return(nil, errors.New("GetStorageByBlockHash Error")) mockStorageAPIErr.EXPECT().GetStorage((*common.Hash)(nil), reqBytes). - Return(nil, errors.New("GetStorage Error")) + Return(nil, errors.New("GetStorage Error")). + AnyTimes() + mockStorageAPIErr.EXPECT().GetStorage(&hash, reqBytes). + Return(nil, errors.New("GetStorage Error")). + AnyTimes() type fields struct { networkAPI NetworkAPI @@ -615,7 +598,7 @@ func TestStateModuleGetStorage(t *testing.T) { Bhash: &hash, }, }, - expErr: errors.New("GetStorageByBlockHash Error"), + expErr: errors.New("GetStorage Error"), }, { name: "bHash Nil Err", @@ -654,15 +637,16 @@ func TestStateModuleGetStorageHash(t *testing.T) { reqBytes := common.MustHexToBytes("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") mockStorageAPI := mocks.NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&hash, reqBytes).Return([]byte{21}, nil) - mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes). - Return([]byte{21}, nil) + mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes).Return([]byte{21}, nil).AnyTimes() + mockStorageAPI.EXPECT().GetStorage(&hash, reqBytes).Return([]byte{21}, nil).AnyTimes() mockStorageAPIErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIErr.EXPECT().GetStorageByBlockHash(&hash, reqBytes). - Return(nil, errors.New("GetStorageByBlockHash Error")) mockStorageAPIErr.EXPECT().GetStorage((*common.Hash)(nil), reqBytes). - Return(nil, errors.New("GetStorage Error")) + Return(nil, errors.New("GetStorage Error")). + AnyTimes() + mockStorageAPIErr.EXPECT().GetStorage(&hash, reqBytes). + Return(nil, errors.New("GetStorage Error")). + AnyTimes() type fields struct { networkAPI NetworkAPI @@ -710,7 +694,7 @@ func TestStateModuleGetStorageHash(t *testing.T) { Bhash: &hash, }, }, - expErr: errors.New("GetStorageByBlockHash Error"), + expErr: errors.New("GetStorage Error"), }, { name: "bHash Nil Err", @@ -749,14 +733,16 @@ func TestStateModuleGetStorageSize(t *testing.T) { reqBytes := common.MustHexToBytes("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a") mockStorageAPI := mocks.NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&hash, reqBytes).Return([]byte{21}, nil) - mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes).Return([]byte{21}, nil) + mockStorageAPI.EXPECT().GetStorage((*common.Hash)(nil), reqBytes).Return([]byte{21}, nil).AnyTimes() + mockStorageAPI.EXPECT().GetStorage(&hash, reqBytes).Return([]byte{21}, nil).AnyTimes() mockStorageAPIErr := mocks.NewMockStorageAPI(ctrl) - mockStorageAPIErr.EXPECT().GetStorageByBlockHash(&hash, reqBytes). - Return(nil, errors.New("GetStorageByBlockHash Error")) mockStorageAPIErr.EXPECT().GetStorage((*common.Hash)(nil), reqBytes). - Return(nil, errors.New("GetStorage Error")) + Return(nil, errors.New("GetStorage Error")). + AnyTimes() + mockStorageAPIErr.EXPECT().GetStorage(&hash, reqBytes). + Return(nil, errors.New("GetStorage Error")). + AnyTimes() type fields struct { networkAPI NetworkAPI @@ -804,7 +790,7 @@ func TestStateModuleGetStorageSize(t *testing.T) { Bhash: &hash, }, }, - expErr: errors.New("GetStorageByBlockHash Error"), + expErr: errors.New("GetStorage Error"), }, { name: "bHash Nil Err", @@ -893,17 +879,17 @@ func TestStateModuleQueryStorage(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) StorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}). Return([]byte{1, 1, 1}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{9, 9, 9}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{9, 9, 9}). Return([]byte{9, 9, 9, 9}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3}, []byte{1, 2, 4}). Return([]byte{2, 2, 2}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3}, []byte{9, 9, 9}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3}, []byte{9, 9, 9}). Return([]byte{9, 9, 9, 9}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{4}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{4}, []byte{1, 2, 4}). Return([]byte{3, 3, 3}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{4}, []byte{9, 9, 9}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{4}, []byte{9, 9, 9}). Return([]byte{9, 9, 9, 9}, nil) return mockStorageAPI }, @@ -951,13 +937,13 @@ func TestStateModuleQueryStorage(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) StorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{1}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{1}, []byte{1, 2, 4}). Return([]byte{1, 1, 1}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}). Return([]byte(nil), nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3}, []byte{1, 2, 4}). Return([]byte{}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{4}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{4}, []byte{1, 2, 4}). Return([]byte{3, 3, 3}, nil) return mockStorageAPI }, @@ -1011,9 +997,9 @@ func TestStateModuleQueryStorage(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) StorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}). Return([]byte{1, 1, 1}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{3}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{3}, []byte{1, 2, 4}). Return([]byte{1, 1, 1}, nil) return mockStorageAPI }, @@ -1098,7 +1084,7 @@ func TestStateModuleQueryStorage(t *testing.T) { "start_block/end_block/error_get_storage_by_block_hash": { fields: fields{func(ctrl *gomock.Controller) StorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}).Return(nil, errTest) + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}).Return(nil, errTest) return mockStorageAPI }, func(ctrl *gomock.Controller) BlockAPI { @@ -1164,7 +1150,7 @@ func TestStateModuleQueryStorageAt(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) *MockStorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 3}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 3}). Return([]byte{1, 1, 1}, nil) return mockStorageAPI }, @@ -1189,7 +1175,7 @@ func TestStateModuleQueryStorageAt(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) *MockStorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{1}, []byte{1, 2, 3}).Return(nil, errTest) + mockStorageAPI.EXPECT().GetStorage(&common.Hash{1}, []byte{1, 2, 3}).Return(nil, errTest) return mockStorageAPI }, blockAPIBuilder: func(ctrl *gomock.Controller) *MockBlockAPI { @@ -1206,11 +1192,11 @@ func TestStateModuleQueryStorageAt(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) *MockStorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{8, 8, 8}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{8, 8, 8}). Return([]byte{8, 8, 8, 8}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}). Return([]byte{}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{9, 9, 9}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{9, 9, 9}). Return([]byte(nil), nil) return mockStorageAPI }, @@ -1236,9 +1222,9 @@ func TestStateModuleQueryStorageAt(t *testing.T) { fields: fields{ storageAPIBuilder: func(ctrl *gomock.Controller) *MockStorageAPI { mockStorageAPI := NewMockStorageAPI(ctrl) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{1, 2, 4}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{1, 2, 4}). Return([]byte{1, 1, 1}, nil) - mockStorageAPI.EXPECT().GetStorageByBlockHash(&common.Hash{2}, []byte{9, 9, 9}). + mockStorageAPI.EXPECT().GetStorage(&common.Hash{2}, []byte{9, 9, 9}). Return([]byte{9, 9, 9, 9}, nil) return mockStorageAPI }, diff --git a/dot/state/initialize.go b/dot/state/initialize.go index 4760b37bd2..6a2369b724 100644 --- a/dot/state/initialize.go +++ b/dot/state/initialize.go @@ -108,7 +108,7 @@ func (s *Service) Initialise(gen *genesis.Genesis, header *types.Header, t trie. return fmt.Errorf("failed to close database: %s", err) } - logger.Infof("block state hash genesis hash: %s", blockState.genesisHash) + logger.Infof("block state genesis hash: %s", blockState.genesisHash) return nil } diff --git a/dot/state/inmemory_storage.go b/dot/state/inmemory_storage.go index 86d205141a..3439740caf 100644 --- a/dot/state/inmemory_storage.go +++ b/dot/state/inmemory_storage.go @@ -23,7 +23,7 @@ var storagePrefix = "storage" var codeKey = common.CodeKey // ErrTrieDoesNotExist is returned when attempting to interact with a trie that is not stored in the StorageState -var ErrTrieDoesNotExist = errors.New("trie with given root does not exist") +var ErrTrieDoesNotExist = errors.New("trie for given state root does not exist") func errTrieDoesNotExist(hash common.Hash) error { return fmt.Errorf("%w: %s", ErrTrieDoesNotExist, hash) @@ -98,31 +98,37 @@ func (s *InmemoryStorageState) StoreTrie(ts storage.TrieState, header *types.Hea } } - go s.notifyAll(root) + var bhash *common.Hash + if header != nil { + h := header.Hash() + bhash = &h + } + + go s.notifyAll(root, bhash) return nil } -// TrieState returns the TrieState for a given state root. -// If no state root is provided, it returns the TrieState for the current chain head. -func (s *InmemoryStorageState) TrieState(root *common.Hash) (storage.TrieState, error) { - if root == nil { - header, err := s.blockState.BestBlockHeader() - if err != nil { - return nil, fmt.Errorf("while getting best block state root: %w", err) - } - root = &header.StateRoot +// TrieState returns the TrieState for a given block hash. +// If no block hash is provided, it returns the TrieState for the current chain head. +func (s *InmemoryStorageState) TrieState(bhash *common.Hash) (storage.TrieState, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, fmt.Errorf("getting state root for block hash %s: %w", bhash.String(), err) } + return s.trieStateByRoot(*root) +} - t := s.tries.get(*root) +func (s *InmemoryStorageState) trieStateByRoot(root common.Hash) (storage.TrieState, error) { + t := s.tries.get(root) if t == nil { var err error - t, err = s.LoadFromDB(*root) + t, err = s.LoadFromDB(root) if err != nil { return nil, fmt.Errorf("while loading from database: %w", err) } - s.tries.softSet(*root, t) - } else if t.MustHash() != *root { + s.tries.softSet(root, t) + } else if t.MustHash() != root { panic("trie does not have expected root") } @@ -169,22 +175,19 @@ func (s *InmemoryStorageState) loadTrie(root *common.Hash) (trie.Trie, error) { return tr, nil } -// ExistsStorage check if the key exists in the storage trie with the given storage hash +// ExistsStorage check if the key exists in the storage trie for the given block hash // If no hash is provided, the current chain head is used -func (s *InmemoryStorageState) ExistsStorage(root *common.Hash, key []byte) (bool, error) { - val, err := s.GetStorage(root, key) +func (s *InmemoryStorageState) ExistsStorage(bhash *common.Hash, key []byte) (bool, error) { + val, err := s.GetStorage(bhash, key) return val != nil, err } -// GetStorage gets the object from the trie using the given key and storage hash +// GetStorage gets the object from the trie using the given key and block hash // If no hash is provided, the current chain head is used -func (s *InmemoryStorageState) GetStorage(root *common.Hash, key []byte) ([]byte, error) { - if root == nil { - header, err := s.blockState.BestBlockHeader() - if err != nil { - return nil, err - } - root = &header.StateRoot +func (s *InmemoryStorageState) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, err } t := s.tries.get(*root) @@ -196,32 +199,8 @@ func (s *InmemoryStorageState) GetStorage(root *common.Hash, key []byte) ([]byte return inmemory_trie.GetFromDB(s.db, *root, key) } -// GetStorageByBlockHash returns the value at the given key at the given block hash -func (s *InmemoryStorageState) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) { - var ( - root common.Hash - err error - ) - - if bhash != nil { - header, err := s.blockState.GetHeader(*bhash) - if err != nil { - return nil, err - } - - root = header.StateRoot - } else { - root, err = s.StorageRoot() - if err != nil { - return nil, err - } - } - - return s.GetStorage(&root, key) -} - -// GetStateRootFromBlock returns the state root hash of a given block hash -func (s *InmemoryStorageState) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { +// getStateRootFromBlock returns the state root hash of a given block hash +func (s *InmemoryStorageState) getStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { if bhash == nil { b := s.blockState.BestBlockHash() bhash = &b @@ -245,8 +224,13 @@ func (s *InmemoryStorageState) StorageRoot() (common.Hash, error) { return header.StateRoot, nil } -// Entries returns Entries from the trie with the given state root -func (s *InmemoryStorageState) Entries(root *common.Hash) (map[string][]byte, error) { +// Entries returns Entries from the trie for the given block hash +func (s *InmemoryStorageState) Entries(bhash *common.Hash) (map[string][]byte, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, err + } + tr, err := s.loadTrie(root) if err != nil { return nil, err @@ -256,8 +240,13 @@ func (s *InmemoryStorageState) Entries(root *common.Hash) (map[string][]byte, er } // GetKeysWithPrefix returns all that match the given prefix for the given hash -// (or best block state root if hash is nil) in lexicographic order -func (s *InmemoryStorageState) GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) { +// (or best block if hash is nil) in lexicographic order +func (s *InmemoryStorageState) GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, err + } + tr, err := s.loadTrie(root) if err != nil { return nil, err @@ -267,7 +256,12 @@ func (s *InmemoryStorageState) GetKeysWithPrefix(root *common.Hash, prefix []byt } // GetStorageChild returns a child trie, if it exists -func (s *InmemoryStorageState) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) { +func (s *InmemoryStorageState) GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, err + } + tr, err := s.loadTrie(root) if err != nil { return nil, err @@ -277,7 +271,12 @@ func (s *InmemoryStorageState) GetStorageChild(root *common.Hash, keyToChild []b } // GetStorageFromChild get a value from a child trie -func (s *InmemoryStorageState) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) { +func (s *InmemoryStorageState) GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) { + root, err := s.getStateRootFromBlock(bhash) + if err != nil { + return nil, err + } + tr, err := s.loadTrie(root) if err != nil { return nil, err @@ -287,13 +286,13 @@ func (s *InmemoryStorageState) GetStorageFromChild(root *common.Hash, keyToChild } // LoadCode returns the runtime code (located at :code) -func (s *InmemoryStorageState) LoadCode(hash *common.Hash) ([]byte, error) { - return s.GetStorage(hash, codeKey) +func (s *InmemoryStorageState) LoadCode(bhash *common.Hash) ([]byte, error) { + return s.GetStorage(bhash, codeKey) } // LoadCodeHash returns the hash of the runtime code (located at :code) -func (s *InmemoryStorageState) LoadCodeHash(hash *common.Hash) (common.Hash, error) { - code, err := s.LoadCode(hash) +func (s *InmemoryStorageState) LoadCodeHash(bhash *common.Hash) (common.Hash, error) { + code, err := s.LoadCode(bhash) if err != nil { return common.NewHash([]byte{}), err } diff --git a/dot/state/inmemory_storage_test.go b/dot/state/inmemory_storage_test.go index 3972d3e80c..282293697b 100644 --- a/dot/state/inmemory_storage_test.go +++ b/dot/state/inmemory_storage_test.go @@ -12,7 +12,6 @@ import ( "github.com/ChainSafe/gossamer/internal/database" "github.com/ChainSafe/gossamer/lib/common" runtime "github.com/ChainSafe/gossamer/lib/runtime/storage" - "github.com/ChainSafe/gossamer/pkg/trie" "go.uber.org/mock/gomock" "github.com/stretchr/testify/require" @@ -31,7 +30,7 @@ func newTestStorageState(t *testing.T) *InmemoryStorageState { func TestStorage_StoreAndLoadTrie(t *testing.T) { storage := newTestStorageState(t) - ts, err := storage.TrieState(&trie.EmptyHash) + ts, err := storage.TrieState(nil) require.NoError(t, err) root, err := ts.Root() @@ -49,14 +48,14 @@ func TestStorage_StoreAndLoadTrie(t *testing.T) { require.Equal(t, trie.MustHash(), ts2Root) } -func TestStorage_GetStorageByBlockHash(t *testing.T) { +func TestStorage_GetStorage(t *testing.T) { storage := newTestStorageState(t) - ts, err := storage.TrieState(&trie.EmptyHash) + ts, err := storage.TrieState(nil) require.NoError(t, err) key := []byte("testkey") value := []byte("testvalue") - ts.Put(key, value) + require.NoError(t, ts.Put(key, value)) root, err := ts.Root() require.NoError(t, err) @@ -79,41 +78,14 @@ func TestStorage_GetStorageByBlockHash(t *testing.T) { require.NoError(t, err) hash := block.Header.Hash() - res, err := storage.GetStorageByBlockHash(&hash, key) + res, err := storage.GetStorage(&hash, key) require.NoError(t, err) require.Equal(t, value, res) } -func TestStorage_TrieState(t *testing.T) { - storage := newTestStorageState(t) - ts, err := storage.TrieState(&trie.EmptyHash) - require.NoError(t, err) - ts.Put([]byte("noot"), []byte("washere")) - - root, err := ts.Root() - require.NoError(t, err) - err = storage.StoreTrie(ts, nil) - require.NoError(t, err) - - time.Sleep(time.Millisecond * 100) - - // get trie from db - storage.blockState.GetTries().delete(root) - ts3, err := storage.TrieState(&root) - require.NoError(t, err) - - tsRoot, err := ts.Root() - require.NoError(t, err) - - ts3Root, err := ts3.Root() - require.NoError(t, err) - - require.Equal(t, tsRoot, ts3Root) -} - func TestStorage_LoadFromDB(t *testing.T) { storage := newTestStorageState(t) - ts, err := storage.TrieState(&trie.EmptyHash) + ts, err := storage.TrieState(nil) require.NoError(t, err) trieKV := []struct { @@ -134,33 +106,51 @@ func TestStorage_LoadFromDB(t *testing.T) { root, err := ts.Root() require.NoError(t, err) + // Create a block associated with the trie. + body, err := types.NewBodyFromBytes([]byte{}) + require.NoError(t, err) + + block := &types.Block{ + Header: types.Header{ + ParentHash: testGenesisHeader.Hash(), + Number: 1, + StateRoot: root, + Digest: createPrimaryBABEDigest(t), + }, + Body: *body, + } + // Write trie to disk. - err = storage.StoreTrie(ts, nil) + err = storage.StoreTrie(ts, &block.Header) require.NoError(t, err) + // Add the block to allow lookup by block hash. + require.NoError(t, storage.blockState.AddBlock(block, nil, nil)) + // Clear trie from cache and fetch data from disk. storage.blockState.GetTries().delete(root) - data, err := storage.GetStorage(&root, trieKV[0].key) + hash := block.Header.Hash() + data, err := storage.GetStorage(&hash, trieKV[0].key) require.NoError(t, err) require.Equal(t, trieKV[0].value, data) storage.blockState.GetTries().delete(root) - prefixKeys, err := storage.GetKeysWithPrefix(&root, []byte("ke")) + prefixKeys, err := storage.GetKeysWithPrefix(&hash, []byte("ke")) require.NoError(t, err) require.Equal(t, 2, len(prefixKeys)) storage.blockState.GetTries().delete(root) - entries, err := storage.Entries(&root) + entries, err := storage.Entries(&hash) require.NoError(t, err) require.Equal(t, 5, len(entries)) } func TestStorage_StoreTrie_NotSyncing(t *testing.T) { storage := newTestStorageState(t) - ts, err := storage.TrieState(&trie.EmptyHash) + ts, err := storage.TrieState(nil) require.NoError(t, err) key := []byte("testkey") @@ -205,24 +195,29 @@ func TestGetStorageChildAndGetStorageFromChild(t *testing.T) { trieState := runtime.NewInMemoryTrieState(genTrie) header := types.NewHeader(blockState.GenesisHash(), trieState.Trie().MustHash(), - common.Hash{}, 1, types.NewDigest()) + common.Hash{}, 1, createPrimaryBABEDigest(t)) err = storage.StoreTrie(trieState, header) require.NoError(t, err) - rootHash, err := genTrie.Hash() + body, err := types.NewBodyFromBytes([]byte{}) require.NoError(t, err) + require.NoError(t, blockState.AddBlock(&types.Block{Header: *header, Body: *body}, nil, nil)) - _, err = storage.GetStorageChild(&rootHash, []byte("keyToChild")) + blockHash := header.Hash() + _, err = storage.GetStorageChild(&blockHash, []byte("keyToChild")) + require.NoError(t, err) + + rootHash, err := genTrie.Hash() require.NoError(t, err) // Clear trie from cache and fetch data from disk. storage.blockState.GetTries().delete(rootHash) - _, err = storage.GetStorageChild(&rootHash, []byte("keyToChild")) + _, err = storage.GetStorageChild(&blockHash, []byte("keyToChild")) require.NoError(t, err) - value, err := storage.GetStorageFromChild(&rootHash, []byte("keyToChild"), []byte("keyInsidechild")) + value, err := storage.GetStorageFromChild(&blockHash, []byte("keyToChild"), []byte("keyInsidechild")) require.NoError(t, err) require.Equal(t, []byte("voila"), value) diff --git a/dot/state/storage_notify.go b/dot/state/storage_notify.go index 142769dbbe..1f76d42981 100644 --- a/dot/state/storage_notify.go +++ b/dot/state/storage_notify.go @@ -58,7 +58,8 @@ func (s *InmemoryStorageState) RegisterStorageObserver(o Observer) { return } go func() { - if err := s.notifyObserver(header.StateRoot, o); err != nil { + bhash := header.Hash() + if err := s.notifyObserver(header.StateRoot, &bhash, o); err != nil { logger.Warnf("failed to notify storage subscriptions: %s", err) } }() @@ -72,19 +73,19 @@ func (s *InmemoryStorageState) UnregisterStorageObserver(o Observer) { s.observerList = s.removeFromSlice(s.observerList, o) } -func (s *InmemoryStorageState) notifyAll(root common.Hash) { +func (s *InmemoryStorageState) notifyAll(root common.Hash, bhash *common.Hash) { s.observerListMutex.RLock() defer s.observerListMutex.RUnlock() for _, observer := range s.observerList { - err := s.notifyObserver(root, observer) + err := s.notifyObserver(root, bhash, observer) if err != nil { logger.Warnf("failed to notify storage subscriptions: %s", err) } } } -func (s *InmemoryStorageState) notifyObserver(root common.Hash, o Observer) error { - t, err := s.TrieState(&root) +func (s *InmemoryStorageState) notifyObserver(root common.Hash, bhash *common.Hash, o Observer) error { + t, err := s.trieStateByRoot(root) if err != nil { return err } @@ -93,8 +94,12 @@ func (s *InmemoryStorageState) notifyObserver(root common.Hash, o Observer) erro return errTrieDoesNotExist(root) } + if bhash == nil { + bhash = &common.EmptyHash + } + subRes := &SubscriptionResult{ - Hash: root, + Hash: *bhash, } if len(o.GetFilter()) == 0 { // no filter, so send all changes diff --git a/dot/state/storage_notify_test.go b/dot/state/storage_notify_test.go index 1597a831d1..df62afaace 100644 --- a/dot/state/storage_notify_test.go +++ b/dot/state/storage_notify_test.go @@ -44,9 +44,8 @@ func TestStorageState_RegisterStorageObserver(t *testing.T) { ss.RegisterStorageObserver(mockobs) defer ss.UnregisterStorageObserver(mockobs) - ts.Put([]byte("mackcom"), []byte("wuz here")) - err = ss.StoreTrie(ts, nil) - require.NoError(t, err) + require.NoError(t, ts.Put([]byte("mackcom"), []byte("wuz here"))) + require.NoError(t, ss.StoreTrie(ts, nil)) // We need to wait since GetFilter and Update are called // in fire and forget goroutines. Not ideal, but it's out of scope diff --git a/dot/state/storage_state.go b/dot/state/storage_state.go index ef14dca0f3..bda075bd82 100644 --- a/dot/state/storage_state.go +++ b/dot/state/storage_state.go @@ -13,21 +13,19 @@ import ( ) type StorageState interface { - TrieState(root *common.Hash) (rtstorage.TrieState, error) + TrieState(bhash *common.Hash) (rtstorage.TrieState, error) StoreTrie(rtstorage.TrieState, *types.Header) error - GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) GenerateTrieProof(stateRoot common.Hash, keys [][]byte) ([][]byte, error) - GetStorage(root *common.Hash, key []byte) ([]byte, error) - GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) + GetStorage(bhash *common.Hash, key []byte) ([]byte, error) StorageRoot() (common.Hash, error) - Entries(root *common.Hash) (map[string][]byte, error) // should be overhauled to iterate - GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) - GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) - GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) + Entries(bhash *common.Hash) (map[string][]byte, error) // should be overhauled to iterate + GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) + GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) + GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) - LoadCode(hash *common.Hash) ([]byte, error) - LoadCodeHash(hash *common.Hash) (common.Hash, error) + LoadCode(bhash *common.Hash) ([]byte, error) + LoadCodeHash(bhash *common.Hash) (common.Hash, error) RegisterStorageObserver(o Observer) UnregisterStorageObserver(o Observer) diff --git a/dot/sync/block_importer.go b/dot/sync/block_importer.go index 63abc89279..a6c4ec8213 100644 --- a/dot/sync/block_importer.go +++ b/dot/sync/block_importer.go @@ -4,7 +4,6 @@ package sync import ( - "bytes" "encoding/json" "errors" "fmt" @@ -194,7 +193,8 @@ func (b *blockImporter) handleBlock(block *types.Block) error { b.storageState.Lock() defer b.storageState.Unlock() - ts, err := b.storageState.TrieState(&parent.StateRoot) + parentHash := parent.Hash() + ts, err := b.storageState.TrieState(&parentHash) if err != nil { return err } @@ -204,7 +204,7 @@ func (b *blockImporter) handleBlock(block *types.Block) error { return err } - if !bytes.Equal(parent.StateRoot[:], root[:]) { + if parent.StateRoot != root { panic("parent state root does not match snapshot state root") } diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index cfd4a93528..872c573bd8 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -614,8 +614,17 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) Pause() error { panic("unimplemented") } -func (ca *ClientAdapter[H, Hasher, N, E, Header]) TrieState(root *common.Hash) (rtstorage.TrieState, error) { - stateAt, err := ca.getStateByStateRoot(root) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) TrieState(bhash *common.Hash) (rtstorage.TrieState, error) { + var hash H + + if bhash == nil { + hash = ca.client.Info().BestHash + } else { + hasher := *new(Hasher) + hash = hasher.NewHash(bhash.ToBytes()) + } + + stateAt, err := ca.client.StateAt(hash) if err != nil { return nil, err } diff --git a/lib/babe/babe.go b/lib/babe/babe.go index 77fa395264..80f9c369bc 100644 --- a/lib/babe/babe.go +++ b/lib/babe/babe.go @@ -433,9 +433,11 @@ func (b *Service) handleSlot(epoch uint64, slot Slot, // set runtime trie before building block // if block building is successful, store the resulting trie in the storage state - ts, err := b.storageState.TrieState(&parent.StateRoot) + parentHash := parent.Hash() + ts, err := b.storageState.TrieState(&parentHash) if err != nil || ts == nil { - logger.Errorf("failed to get parent trie with parent state root %s: %s", parent.StateRoot, err) + err = fmt.Errorf("failed to get parent trie for block hash %s: %w", parentHash.String(), err) + logger.Error(err.Error()) return err } diff --git a/lib/babe/mock_storage_state_test.go b/lib/babe/mock_storage_state_test.go index 7af63f9ea1..ae954aabba 100644 --- a/lib/babe/mock_storage_state_test.go +++ b/lib/babe/mock_storage_state_test.go @@ -45,18 +45,18 @@ func (m *MockStorageState) EXPECT() *MockStorageStateMockRecorder { } // Entries mocks base method. -func (m *MockStorageState) Entries(root *common.Hash) (map[string][]byte, error) { +func (m *MockStorageState) Entries(bhash *common.Hash) (map[string][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Entries", root) + ret := m.ctrl.Call(m, "Entries", bhash) ret0, _ := ret[0].(map[string][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Entries indicates an expected call of Entries. -func (mr *MockStorageStateMockRecorder) Entries(root any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) Entries(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageState)(nil).Entries), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entries", reflect.TypeOf((*MockStorageState)(nil).Entries), bhash) } // GenerateTrieProof mocks base method. @@ -75,123 +75,93 @@ func (mr *MockStorageStateMockRecorder) GenerateTrieProof(stateRoot, keys any) * } // GetKeysWithPrefix mocks base method. -func (m *MockStorageState) GetKeysWithPrefix(root *common.Hash, prefix []byte) ([][]byte, error) { +func (m *MockStorageState) GetKeysWithPrefix(bhash *common.Hash, prefix []byte) ([][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetKeysWithPrefix", root, prefix) + ret := m.ctrl.Call(m, "GetKeysWithPrefix", bhash, prefix) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetKeysWithPrefix indicates an expected call of GetKeysWithPrefix. -func (mr *MockStorageStateMockRecorder) GetKeysWithPrefix(root, prefix any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetKeysWithPrefix(bhash, prefix any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageState)(nil).GetKeysWithPrefix), root, prefix) -} - -// GetStateRootFromBlock mocks base method. -func (m *MockStorageState) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStateRootFromBlock", bhash) - ret0, _ := ret[0].(*common.Hash) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStateRootFromBlock indicates an expected call of GetStateRootFromBlock. -func (mr *MockStorageStateMockRecorder) GetStateRootFromBlock(bhash any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStateRootFromBlock", reflect.TypeOf((*MockStorageState)(nil).GetStateRootFromBlock), bhash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeysWithPrefix", reflect.TypeOf((*MockStorageState)(nil).GetKeysWithPrefix), bhash, prefix) } // GetStorage mocks base method. -func (m *MockStorageState) GetStorage(root *common.Hash, key []byte) ([]byte, error) { +func (m *MockStorageState) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorage", root, key) + ret := m.ctrl.Call(m, "GetStorage", bhash, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorage indicates an expected call of GetStorage. -func (mr *MockStorageStateMockRecorder) GetStorage(root, key any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageState)(nil).GetStorage), root, key) -} - -// GetStorageByBlockHash mocks base method. -func (m *MockStorageState) GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageByBlockHash", bhash, key) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStorageByBlockHash indicates an expected call of GetStorageByBlockHash. -func (mr *MockStorageStateMockRecorder) GetStorageByBlockHash(bhash, key any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorage(bhash, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageByBlockHash", reflect.TypeOf((*MockStorageState)(nil).GetStorageByBlockHash), bhash, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorage", reflect.TypeOf((*MockStorageState)(nil).GetStorage), bhash, key) } // GetStorageChild mocks base method. -func (m *MockStorageState) GetStorageChild(root *common.Hash, keyToChild []byte) (trie.Trie, error) { +func (m *MockStorageState) GetStorageChild(bhash *common.Hash, keyToChild []byte) (trie.Trie, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageChild", root, keyToChild) + ret := m.ctrl.Call(m, "GetStorageChild", bhash, keyToChild) ret0, _ := ret[0].(trie.Trie) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageChild indicates an expected call of GetStorageChild. -func (mr *MockStorageStateMockRecorder) GetStorageChild(root, keyToChild any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorageChild(bhash, keyToChild any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageChild), root, keyToChild) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageChild), bhash, keyToChild) } // GetStorageFromChild mocks base method. -func (m *MockStorageState) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ([]byte, error) { +func (m *MockStorageState) GetStorageFromChild(bhash *common.Hash, keyToChild, key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStorageFromChild", root, keyToChild, key) + ret := m.ctrl.Call(m, "GetStorageFromChild", bhash, keyToChild, key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // GetStorageFromChild indicates an expected call of GetStorageFromChild. -func (mr *MockStorageStateMockRecorder) GetStorageFromChild(root, keyToChild, key any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) GetStorageFromChild(bhash, keyToChild, key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageFromChild), root, keyToChild, key) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageFromChild", reflect.TypeOf((*MockStorageState)(nil).GetStorageFromChild), bhash, keyToChild, key) } // LoadCode mocks base method. -func (m *MockStorageState) LoadCode(hash *common.Hash) ([]byte, error) { +func (m *MockStorageState) LoadCode(bhash *common.Hash) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCode", hash) + ret := m.ctrl.Call(m, "LoadCode", bhash) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCode indicates an expected call of LoadCode. -func (mr *MockStorageStateMockRecorder) LoadCode(hash any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCode(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCode", reflect.TypeOf((*MockStorageState)(nil).LoadCode), bhash) } // LoadCodeHash mocks base method. -func (m *MockStorageState) LoadCodeHash(hash *common.Hash) (common.Hash, error) { +func (m *MockStorageState) LoadCodeHash(bhash *common.Hash) (common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadCodeHash", hash) + ret := m.ctrl.Call(m, "LoadCodeHash", bhash) ret0, _ := ret[0].(common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadCodeHash indicates an expected call of LoadCodeHash. -func (mr *MockStorageStateMockRecorder) LoadCodeHash(hash any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) LoadCodeHash(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), hash) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadCodeHash", reflect.TypeOf((*MockStorageState)(nil).LoadCodeHash), bhash) } // Lock mocks base method. @@ -248,18 +218,18 @@ func (mr *MockStorageStateMockRecorder) StoreTrie(arg0, arg1 any) *gomock.Call { } // TrieState mocks base method. -func (m *MockStorageState) TrieState(root *common.Hash) (storage.TrieState, error) { +func (m *MockStorageState) TrieState(bhash *common.Hash) (storage.TrieState, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TrieState", root) + ret := m.ctrl.Call(m, "TrieState", bhash) ret0, _ := ret[0].(storage.TrieState) ret1, _ := ret[1].(error) return ret0, ret1 } // TrieState indicates an expected call of TrieState. -func (mr *MockStorageStateMockRecorder) TrieState(root any) *gomock.Call { +func (mr *MockStorageStateMockRecorder) TrieState(bhash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrieState", reflect.TypeOf((*MockStorageState)(nil).TrieState), root) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TrieState", reflect.TypeOf((*MockStorageState)(nil).TrieState), bhash) } // Unlock mocks base method. From 902651028f27014f326448ea0be84f2d2ed2b5bc Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 5 Jul 2025 13:01:03 +0700 Subject: [PATCH 22/23] update StorageState impl on ClientAdapter After #4792, StorageState methods that expected a state root hash now take a block hash. This updates all affected StorageState methods on ClientAdapter and simplifies their implementation. --- internal/client/adapter/client_adapter.go | 137 +++++--------- .../client/adapter/client_adapter_test.go | 174 ++---------------- 2 files changed, 60 insertions(+), 251 deletions(-) diff --git a/internal/client/adapter/client_adapter.go b/internal/client/adapter/client_adapter.go index 872c573bd8..57aa57fe6d 100644 --- a/internal/client/adapter/client_adapter.go +++ b/internal/client/adapter/client_adapter.go @@ -615,16 +615,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) Pause() error { } func (ca *ClientAdapter[H, Hasher, N, E, Header]) TrieState(bhash *common.Hash) (rtstorage.TrieState, error) { - var hash H - - if bhash == nil { - hash = ca.client.Info().BestHash - } else { - hasher := *new(Hasher) - hash = hasher.NewHash(bhash.ToBytes()) - } - - stateAt, err := ca.client.StateAt(hash) + stateAt, err := ca.stateAt(bhash) if err != nil { return nil, err } @@ -640,15 +631,7 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StoreTrie(rtstorage.TrieState, // GetStateRootFromBlock returns the state root of the block with the given hash. // Uses the best block hash when called with `nil`. func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) { - var hash H - - if bhash == nil { - hash = ca.client.Info().BestHash - } else { - hasher := *new(Hasher) - hash = hasher.NewHash(bhash.ToBytes()) - } - + hash := ca.hashToGeneric(bhash) header, err := ca.client.Header(hash) if err != nil { return nil, err @@ -676,59 +659,8 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GenerateTrieProof(stateRoot co } // GetStorage queries the state that corresponds to the given state root hash for the data at the given key. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorage(root *common.Hash, key []byte) ([]byte, error) { - stateAt, err := ca.getStateByStateRoot(root) - if err != nil { - return nil, err - } - - return stateAt.Storage(key) -} - -const maxSearchDepth = 1000 - -func (ca *ClientAdapter[H, Hasher, N, E, Header]) getStateByStateRoot( - root *common.Hash, -) (statemachine.Backend[H, Hasher], error) { - currentHash := ca.client.Info().BestHash - - if root == nil { - return ca.client.StateAt(currentHash) - } - - targetRoot := (*new(Hasher)).NewHash(root.ToBytes()) - - for i := 0; i < maxSearchDepth; i++ { - header, err := ca.client.Header(currentHash) - if err != nil { - return nil, err - } - if header == nil { - return nil, fmt.Errorf("no block header found for hash %s", currentHash.String()) - } - - if (*header).StateRoot() == targetRoot { - return ca.client.StateAt(currentHash) - } - - currentHash = (*header).ParentHash() - } - - return nil, fmt.Errorf("max search depth exceeded without finding storage root %s", targetRoot.String()) -} - -// GetStorageByBlockHash queries the state that at the given block hash for the data at the given key. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageByBlockHash(bhash *common.Hash, key []byte) ( - []byte, error) { - var hash H - if bhash == nil { - hash = ca.client.Info().BestHash - } else { - hasher := *new(Hasher) - hash = hasher.NewHash(bhash.ToBytes()) - } - - return ca.client.Storage(hash, key) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorage(bhash *common.Hash, key []byte) ([]byte, error) { + return ca.client.Storage(ca.hashToGeneric(bhash), key) } func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageRoot() (common.Hash, error) { @@ -740,8 +672,8 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) StorageRoot() (common.Hash, er return common.NewHashFromGeneric((*header).StateRoot()), nil } -func (ca *ClientAdapter[H, Hasher, N, E, Header]) Entries(root *common.Hash) (map[string][]byte, error) { - stateAt, err := ca.getStateByStateRoot(root) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) Entries(bhash *common.Hash) (map[string][]byte, error) { + stateAt, err := ca.stateAt(bhash) if err != nil { return nil, err } @@ -763,10 +695,12 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) Entries(root *common.Hash) (ma } // GetKeysWithPrefix returns all keys with the given prefix from the state -// that corresponds to the given state root hash. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetKeysWithPrefix(root *common.Hash, prefix []byte) ( - [][]byte, error) { - stateAt, err := ca.getStateByStateRoot(root) +// that corresponds to the given block hash. +func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetKeysWithPrefix( + bhash *common.Hash, + prefix []byte, +) ([][]byte, error) { + stateAt, err := ca.stateAt(bhash) if err != nil { return nil, err } @@ -787,9 +721,11 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetKeysWithPrefix(root *common return res, nil } -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageChild(root *common.Hash, keyToChild []byte) ( - trie.Trie, error) { - stateAt, err := ca.getStateByStateRoot(root) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageChild( + bhash *common.Hash, + keyToChild []byte, +) (trie.Trie, error) { + stateAt, err := ca.stateAt(bhash) if err != nil { return nil, err } @@ -819,27 +755,25 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageChild(root *common.H return storageTrie, nil } -func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageFromChild(root *common.Hash, keyToChild, key []byte) ( - []byte, error) { - stateAt, err := ca.getStateByStateRoot(root) - if err != nil { - return nil, err - } - +func (ca *ClientAdapter[H, Hasher, N, E, Header]) GetStorageFromChild( + bhash *common.Hash, + keyToChild []byte, + key []byte, +) ([]byte, error) { + hash := ca.hashToGeneric(bhash) info := storage.NewDefaultChildInfo(keyToChild) - return stateAt.ChildStorage(info, key) + + return ca.client.ChildStorage(hash, info, key) } // LoadCode returns the runtime blob for the given block hash. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCode(hash *common.Hash) ([]byte, error) { - // InmemoryStorageState.LoadCode() calls GetStorage() but I'm pretty sure `hash` is meant to be a block hash, - // not a state root hash. 🤔 - return ca.GetStorageByBlockHash(hash, common.CodeKey) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCode(bhash *common.Hash) ([]byte, error) { + return ca.GetStorage(bhash, common.CodeKey) } // LoadCodeHash returns the hash of the runtime blob for the given block hash. -func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCodeHash(hash *common.Hash) (common.Hash, error) { - code, err := ca.LoadCode(hash) +func (ca *ClientAdapter[H, Hasher, N, E, Header]) LoadCodeHash(bhash *common.Hash) (common.Hash, error) { + code, err := ca.LoadCode(bhash) if err != nil { return common.Hash{}, err } @@ -862,6 +796,19 @@ func (ca *ClientAdapter[H, Hasher, N, E, Header]) SetBlockTree(blocktree *blockt panic("unimplemented") } +func (ca *ClientAdapter[H, Hasher, N, E, Header]) stateAt(bhash *common.Hash) (statemachine.Backend[H, Hasher], error) { + return ca.client.StateAt(ca.hashToGeneric(bhash)) +} + +func (ca *ClientAdapter[H, Hasher, N, E, Header]) hashToGeneric(bhash *common.Hash) H { + if bhash == nil { + return ca.client.Info().BestHash + } + + hasher := *new(Hasher) + return hasher.NewHash(bhash.ToBytes()) +} + func prefixKey(hash common.Hash, prefix []byte) []byte { return append(prefix, hash.ToBytes()...) } diff --git a/internal/client/adapter/client_adapter_test.go b/internal/client/adapter/client_adapter_test.go index 3e704456f8..a51d140145 100644 --- a/internal/client/adapter/client_adapter_test.go +++ b/internal/client/adapter/client_adapter_test.go @@ -5,7 +5,6 @@ package adapter import ( "errors" - "fmt" "testing" "github.com/ChainSafe/gossamer/dot/state" @@ -785,132 +784,6 @@ func TestGetStateRootFromBlock(t *testing.T) { } func TestGetStorage(t *testing.T) { - t.Run("error", func(t *testing.T) { - client, _, _, adapter := setupTest(t) - - expectedError := errors.New("kaput") - client.EXPECT().StateAt(header.Hash()).Return(nil, expectedError) - client.EXPECT().Info().Return(blockchainInfo) - client.EXPECT().Header(header.Hash()).Return(&header, nil) - - root := common.NewHashFromGeneric(header.StateRoot()) - - value, err := adapter.GetStorage(&root, []byte("key")) - require.ErrorIs(t, err, expectedError) - require.Nil(t, value) - }) - t.Run("ok", func(t *testing.T) { - client, _, _, adapter := setupTest(t) - - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) - - client.EXPECT().StateAt(header.Hash()).Return(backend, nil) - client.EXPECT().Info().Return(blockchainInfo) - client.EXPECT().Header(header.Hash()).Return(&header, nil) - - root := common.NewHashFromGeneric(header.StateRoot()) - - value, err := adapter.GetStorage(&root, []byte("key")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) - }) - t.Run("root_nil", func(t *testing.T) { - client, _, _, adapter := setupTest(t) - - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) - - client.EXPECT().StateAt(blockchainInfo.BestHash).Return(backend, nil) - client.EXPECT().Info().Return(blockchainInfo) - - value, err := adapter.GetStorage(nil, []byte("key")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) - }) - t.Run("search_succeeds", func(t *testing.T) { - client, _, _, adapter := setupTest(t) - - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - backend.EXPECT().Storage([]byte("key")).Return([]byte("value"), nil) - - length := min(maxSearchDepth-1, 10) - genesisHeader := makeHeaderChain(t, client, uint16(length)) - client.EXPECT().StateAt(genesisHeader.Hash()).Return(backend, nil) - - root := common.NewHashFromGeneric(genesisHeader.StateRoot()) - - value, err := adapter.GetStorage(&root, []byte("key")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) - }) - t.Run("search_fails", func(t *testing.T) { - client, _, _, adapter := setupTest(t) - - backend := mocks.NewStatemachineBackend[Hash, Hasher](t) - - backend.EXPECT(). - Storage([]byte("key")). - Maybe(). - Return([]byte("value"), nil) - - genesisHeader := makeHeaderChain(t, client, maxSearchDepth+1) - client.EXPECT().StateAt(genesisHeader.Hash()).Maybe().Return(backend, nil) - - root := common.NewHashFromGeneric(genesisHeader.StateRoot()) - - value, err := adapter.GetStorage(&root, []byte("key")) - require.Error(t, err) - require.Nil(t, value) - }) -} - -// makeHeaderChain creates a chain of headers and returns the header of the genesis block. -// -// The given client is configured to return them from Header() by their hash and to return -// [blockchain.Info] with appropriate values from Info(). -func makeHeaderChain( - t *testing.T, - client *mocks.Client[Hash, Hasher, Number, Extrinsic, Header], - length uint16, -) (genesisHeader Header) { - t.Helper() - - chain := make([]Header, length) - hasher := new(Hasher) - - for i := 0; i < int(length); i++ { - parentHash := hash.NewRandomH256() - if i > 0 { - parentHash = chain[i-1].Hash() - } - - h := generic.NewHeader[Number, Hash, Hasher]( - Number(i), - hash.NewRandomH256(), - hasher.Hash([]byte(fmt.Sprintf("header%d", i))), - parentHash, - runtime.Digest{}, - ) - - chain[i] = *h - client.EXPECT().Header(h.Hash()).Maybe().Return(h, nil) - } - - info := blockchain.Info[Hash, Number]{ - GenesisHash: genesisHeader.Hash(), - BestHash: chain[length-1].Hash(), - BestNumber: chain[length-1].Number(), - FinalizedHash: chain[length-1].Hash(), - FinalizedNumber: chain[length-1].Number(), - } - - client.EXPECT().Info().Return(info) - - return chain[0] -} - -func TestGetStorageByBlockHash(t *testing.T) { t.Run("error", func(t *testing.T) { client, _, _, adapter := setupTest(t) @@ -928,7 +801,7 @@ func TestGetStorageByBlockHash(t *testing.T) { bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) - value, err := adapter.GetStorageByBlockHash(&bhash, []byte("key")) + value, err := adapter.GetStorage(&bhash, []byte("key")) require.ErrorIs(t, err, expectedError) require.Nil(t, value) }) @@ -947,7 +820,7 @@ func TestGetStorageByBlockHash(t *testing.T) { bhash := common.NewHashFromGeneric(blockchainInfo.FinalizedHash) - value, err := adapter.GetStorageByBlockHash(&bhash, storage.StorageKey("key")) + value, err := adapter.GetStorage(&bhash, storage.StorageKey("key")) require.NoError(t, err) require.Equal(t, []byte("value"), value) }) @@ -966,7 +839,7 @@ func TestGetStorageByBlockHash(t *testing.T) { client.EXPECT().Info().Return(blockchainInfo) - value, err := adapter.GetStorageByBlockHash(nil, []byte("key")) + value, err := adapter.GetStorage(nil, []byte("key")) require.NoError(t, err) require.Equal(t, []byte("value"), value) }) @@ -984,14 +857,12 @@ func Test_GetKeysWithPrefix_Entries(t *testing.T) { } backend := statemachine.NewMemoryDBTrieBackendFromMap[Hash, Hasher](entries, storage.StateVersionV1) - client.EXPECT().Header(header.Hash()).Return(&header, nil) client.EXPECT().StateAt(header.Hash()).Return(backend, nil) - client.EXPECT().Info().Return(blockchainInfo) - root := common.NewHashFromGeneric(header.StateRoot()) + bhash := common.NewHashFromGeneric(header.Hash()) t.Run("GetKeysWithPrefix", func(t *testing.T) { - keys, err := adapter.GetKeysWithPrefix(&root, []byte("ke")) + keys, err := adapter.GetKeysWithPrefix(&bhash, []byte("ke")) require.NoError(t, err) require.Len(t, keys, 2) @@ -999,8 +870,8 @@ func Test_GetKeysWithPrefix_Entries(t *testing.T) { require.Contains(t, keys, []byte("key2")) }) - t.Run("GetKeysWithPrefix", func(t *testing.T) { - result, err := adapter.Entries(&root) + t.Run("Entries", func(t *testing.T) { + result, err := adapter.Entries(&bhash) require.NoError(t, err) require.Equal(t, entries, result) @@ -1070,7 +941,7 @@ func TestGetFirstNonOriginSlotNumber(t *testing.T) { }) } -func Test_GetStorageFromChild_GetStorageChild(t *testing.T) { +func Test_GetStorageChild(t *testing.T) { client, _, _, adapter := setupTest(t) childInfo := storage.NewDefaultChildInfo([]byte("child1")) @@ -1106,27 +977,18 @@ func Test_GetStorageFromChild_GetStorageChild(t *testing.T) { ) client.EXPECT().StateAt(header.Hash()).Return(backend, nil) - t.Run("GetStorageFromChild", func(t *testing.T) { - value, err := adapter.GetStorageFromChild(nil, []byte("child1"), []byte("key")) + storageChild, err := adapter.GetStorageChild(nil, []byte("child1")) - require.NoError(t, err) - require.Equal(t, []byte("value"), value) - }) - - t.Run("GetStorageChild", func(t *testing.T) { - storageChild, err := adapter.GetStorageChild(nil, []byte("child1")) - - require.NoError(t, err) + require.NoError(t, err) - require.Equal( - t, - map[string][]byte{ - "key": []byte("value"), - "anotherkey": []byte("anothervalue"), - }, - storageChild.Entries(), - ) - }) + require.Equal( + t, + map[string][]byte{ + "key": []byte("value"), + "anotherkey": []byte("anothervalue"), + }, + storageChild.Entries(), + ) } func TestAddBlock_MissingParams(t *testing.T) { From f7fc05e256ef9b9f3adf0009b2f4c920843e6e2a Mon Sep 17 00:00:00 2001 From: Haiko Schol Date: Sat, 5 Jul 2025 13:04:59 +0700 Subject: [PATCH 23/23] remove duplicate StorageProvider definition --- internal/client/api/backend.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index 6a7a0a5bb0..4338f0057d 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -255,12 +255,6 @@ type AuxStore interface { GetAux(key []byte) ([]byte, error) } -// StorageProvider provides access to storage primitives -type StorageProvider[H runtime.Hash, N runtime.Number, Hasher runtime.Hasher[H]] interface { - // Given a block hash and a key, return the value under the key in that block. - Storage(hash H, key storage.StorageKey) (storage.StorageData, error) -} - // Backend is the client backend. // // Manages the data layer.