diff --git a/dot/state/interfaces.go b/dot/state/interfaces.go index 513b9c5ff5..9042358003 100644 --- a/dot/state/interfaces.go +++ b/dot/state/interfaces.go @@ -5,15 +5,9 @@ package state import ( "encoding/json" - "sync" - "time" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/database" - "github.com/ChainSafe/gossamer/lib/common" - "github.com/ChainSafe/gossamer/lib/runtime" - rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage" - "github.com/ChainSafe/gossamer/pkg/trie" ) type GrandpaDatabase interface { @@ -82,128 +76,3 @@ type BabeConfigurer interface { type Telemetry interface { SendMessage(msg json.Marshaler) } - -type blockState interface { - AddBlock(*types.Block) error - AddBlockWithArrivalTime(block *types.Block, arrivalTime time.Time) error - - BestBlock() (*types.Block, error) // can be achieved by calling blockchainDB.Info() fulfills blockchain.HeaderBackend - BestBlockHash() common.Hash - BestBlockHeader() (*types.Header, error) - BestBlockNumber() (number uint, err error) - BestBlockStateRoot() (common.Hash, error) // only used within dot/state; can be removed - GenesisHash() common.Hash - - GetAllDescendants(hash common.Hash) ([]common.Hash, error) // only used within dot/state; can be removed - GetAllBlocksAtNumber(num uint) ([]common.Hash, error) // can be removed - GetBlockBody(hash common.Hash) (*types.Body, error) - GetBlockStateRoot(bhash common.Hash) (common.Hash, error) - GetBlockByHash(common.Hash) (*types.Block, error) - GetBlockByNumber(blockNumber uint) (*types.Block, error) - GetBlockHashesBySlot(slot uint64) (blockHashes []common.Hash, err error) // can be removed - GetFinalisedHeader(round, setID uint64) (*types.Header, error) - GetFinalisedHash(round, setID uint64) (common.Hash, error) - GetHashesByNumber(blockNumber uint) ([]common.Hash, error) // not sure why we need this, use `GetHashByNumber`? - GetHashByNumber(blockNumber uint) (common.Hash, error) // can be retrieved by from HeaderBackend.Hash() - GetHeader(bhash common.Hash) (*types.Header, error) - GetHeaderByNumber(num uint) (*types.Header, error) - GetHighestFinalisedHeader() (*types.Header, error) - GetHighestFinalisedHash() (common.Hash, error) - GetHighestRoundAndSetID() (uint64, uint64, error) - GetJustification(common.Hash) ([]byte, error) - - GetNonFinalisedBlocks() []common.Hash // can probably be achieved by getting last finalized, then traversing children - GetRoundAndSetID() (uint64, uint64) // not called, can be removed - GetSlotForBlock(common.Hash) (uint64, error) - - HasFinalisedBlock(round, setID uint64) (bool, error) - HasHeader(hash common.Hash) (bool, error) - HasJustification(hash common.Hash) (bool, error) - HasHeaderInDatabase(hash common.Hash) (bool, error) // can probably just use `HasHeader` - - SetFinalisedHash(hash common.Hash, round uint64, setID uint64) error - SetHeader(header *types.Header) error - SetJustification(hash common.Hash, data []byte) error - - GetRuntime(blockHash common.Hash) (instance runtime.Instance, err error) // can be achieved by retrieving digest from block and decoding - HandleRuntimeChanges(newState *rtstorage.TrieState, in runtime.Instance, bHash common.Hash) error // will have to be recreated - - CompareAndSetBlockData(bd *types.BlockData) error - SetReceipt(hash common.Hash, data []byte) error // aux store functionality? - HasReceipt(hash common.Hash) (bool, error) - GetReceipt(common.Hash) ([]byte, error) // pretty sure this is just block data? - HasMessageQueue(hash common.Hash) (bool, error) // won't be needed if CompareAndSetBlockData is replaced - SetMessageQueue(hash common.Hash, data []byte) error // won't be needed if CompareAndSetBlockData is replaced - GetMessageQueue(common.Hash) ([]byte, error) // won't be needed if CompareAndSetBlockData is replaced - - IsDescendantOf(parent, child common.Hash) (bool, error) // use client/api/utils.IsDescendantOf - LowestCommonAncestor(a, b common.Hash) (common.Hash, error) // use primitives/blockchain.LowestCommonAncestor - Leaves() []common.Hash // don't think this is called - NumberIsFinalised(blockNumber uint) (bool, error) - - Range(startHash, endHash common.Hash) (hashes []common.Hash, err error) // should be able to use primitives/blockchain.TreeRoute - RangeInMemory(start, end common.Hash) ([]common.Hash, error) // should be able to use primitives/blockchain.TreeRoute - - StoreRuntime(blockHash common.Hash, runtime runtime.Instance) - - FreeImportedBlockNotifierChannel(ch chan *types.Block) - GetImportedBlockNotifierChannel() chan *types.Block - FreeFinalisedNotifierChannel(ch chan *types.FinalisationInfo) - GetFinalisedNotifierChannel() chan *types.FinalisationInfo - - RegisterRuntimeUpdatedChannel(ch chan<- runtime.Version) (uint32, error) // will need extra work to listen on import events and pass along. Since it's RPC related we can deprioritize - - IsPaused() bool - Pause() error -} - -var _ blockState = &BlockState{} - -type storageState interface { - TrieState(root *common.Hash) (*rtstorage.TrieState, error) - // rtstorage.TrieState is where all the mutations are held in 'storageDiffs" - // TrieState is called like 90% of the time just to pass it into rt.SetContextStorage - // TrieState has a Trie interface attribute where it's just used to get the hash - // TrieState also is the type that the runtime host functions interact with to query/store storage changes, - // iterate through top trie and child trie keys, start and rollback transactions - - // impl: recreate sp_statemachine.OverlayedChanges - // call backend.StateAt() to get current state, pass in overlayed changes to handle changes - // create an interface that represents the public API of TrieState - // fulfill that interface with something that combines TrieBackend and OverlayedCHanges for a given hash - - // substrate notes: - // sp_externalities::Externalities is the trait that represents the host functionality required by the runtime - // sp_statemachine::Ext is type that implements sp_externalities::Externalities which raps Overlayed changed, read only backend - // the #[runtime_interface] macro is used to wrap traits with default implementations where `self` is `sp_statemachine::Ext` - - StoreTrie(*rtstorage.TrieState, *types.Header) error - // StoreTrie should be deprecated, since it's only used in dot/core/service.go in handleBlock function - // The trie backend will be updated by adding the block to the client - - GenerateTrieProof(stateRoot common.Hash, keys [][]byte) ([][]byte, error) - // only used by RPC at the moment, will need to recreate sp_api::CallExecutor::contextual_call - // which will read the keys and generate a proof. - - GetStorage(root *common.Hash, key []byte) ([]byte, error) - GetStorageByBlockHash(bhash *common.Hash, key []byte) ([]byte, error) - 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) - GetStateRootFromBlock(bhash *common.Hash) (*common.Hash, error) - StorageRoot() (common.Hash, error) // best block state root, use HeaderBackend - - Entries(root *common.Hash) (map[string][]byte, error) // should be overhauled to iterate through the keys instead of loading everything into memory - - LoadCode(hash *common.Hash) ([]byte, error) - LoadCodeHash(hash *common.Hash) (common.Hash, error) - - RegisterStorageObserver(o Observer) - UnregisterStorageObserver(o Observer) - - sync.Locker -} - -var _ storageState = &InmemoryStorageState{} - -// look into rtstroage.TrieState, you will need to make this an interface diff --git a/internal/client/api/backend.go b/internal/client/api/backend.go index 8e78643ea6..9c8e4c7da7 100644 --- a/internal/client/api/backend.go +++ b/internal/client/api/backend.go @@ -83,7 +83,7 @@ type ClientImportOperation[ } // NewBlockState is the state of a new block. -type NewBlockState uint +type NewBlockState uint8 const ( // NewBlockStateNormal is a normal block. diff --git a/internal/client/api/client.go b/internal/client/api/client.go index b1e5c84e7b..038383f37c 100644 --- a/internal/client/api/client.go +++ b/internal/client/api/client.go @@ -163,12 +163,13 @@ type BlockImportNotification[ N runtime.Number, Header runtime.Header[N, H], ] struct { - Hash H // Imported block header hash. - Origin consensus.BlockOrigin // Imported block origin. - Header Header // Imported block header. - IsNewBest bool // Is this the new best block. - TreeRoute *blockchain.TreeRoute[H, N] // Tree route from old best to new best. If nil, there was no re-org while importing. - unpinHandle UnpinHandle[H] // Handle to unpin the block this notification is associated with. + Hash H // Imported block header hash. + Origin consensus.BlockOrigin // Imported block origin. + Header Header // Imported block header. + IsNewBest bool // Is this the new best block. + // TreeRoute from old best to new best. If nil, there was no re-org while importing. + TreeRoute *blockchain.TreeRoute[H, N] + unpinHandle UnpinHandle[H] // Handle to unpin the block this notification is associated with. } // Drop will unpin the block from the backend. diff --git a/internal/client/api/notifications.go b/internal/client/api/notifications.go index 7468a2b591..7e47550ec3 100644 --- a/internal/client/api/notifications.go +++ b/internal/client/api/notifications.go @@ -70,7 +70,10 @@ func (s StorageNotifications[H]) Trigger(hash H, changeset []StorageChange, chil } // Listen will start listening for particular storage keys. -func (s StorageNotifications[H]) Listen(filterKeys []storage.StorageKey, filterChildKeys []ChildFilterKeys) StorageEventStream[H] { +func (s StorageNotifications[H]) Listen( + filterKeys []storage.StorageKey, + filterChildKeys []ChildFilterKeys, +) StorageEventStream[H] { receiver := s.Hub.Subscribe(SubscribeOp{ FilterKeys: filterKeys, FilterChildKeys: filterChildKeys, diff --git a/internal/client/api/registry.go b/internal/client/api/registry.go index 3a8321e0f4..7cff3323f3 100644 --- a/internal/client/api/registry.go +++ b/internal/client/api/registry.go @@ -153,7 +153,12 @@ func (r *registry[H]) removeSubscriber(subscriber uint64) *struct { } } -func (r *registry[H]) removeSubscriberFrom(subscriber uint64, filters Keys, listeners map[string]map[uint64]any, wildcards map[uint64]any) { +func (r *registry[H]) removeSubscriberFrom( + subscriber uint64, + filters Keys, + listeners map[string]map[uint64]any, + wildcards map[uint64]any, +) { if filters == nil { delete(wildcards, subscriber) } else { @@ -200,7 +205,12 @@ func (r *registry[H]) Dispatch(message SubscriberMessage[H], dispatch func(uint6 r.trigger(message.Hash, message.ChangeSet, message.ChildChangeSet, dispatch) } -func (r *registry[H]) trigger(hash H, changeset []StorageChange, childChangeSet []StorageChildChange, dispatch func(uint64, StorageNotification[H])) { +func (r *registry[H]) trigger( //nolint:gocyclo + hash H, + changeset []StorageChange, + childChangeSet []StorageChildChange, + dispatch func(uint64, StorageNotification[H]), +) { hasWildcard := len(r.wildcardListeners) != 0 // early exit if no listeners diff --git a/internal/client/client.go b/internal/client/client.go index 6a5133ff21..e55e131264 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -85,7 +85,9 @@ func (c *Client[H, Hasher, N, E, Header]) unpin(message api.Unpin[H]) error { } } -func (c *Client[H, Hasher, N, E, Header]) LockImportRun(f func(*api.ClientImportOperation[H, Hasher, N, Header, E]) error) error { +func (c *Client[H, Hasher, N, E, Header]) LockImportRun( + f func(*api.ClientImportOperation[H, Hasher, N, Header, E]) error, +) error { var inner = func() error { c.backend.GetImportLock().Lock() defer c.backend.GetImportLock().Unlock() @@ -196,7 +198,7 @@ func (c *Client[H, Hasher, N, E, Header]) LockImportRun(f func(*api.ClientImport return err } -const notifyFinalizedTimeout = time.Duration(5 * time.Second) +const notifyFinalizedTimeout = 5 * time.Second const notifyBlockImportTimout = notifyFinalizedTimeout func (c *Client[H, Hasher, N, E, Header]) notifyFinalized(notification *api.FinalityNotification[H, N, Header]) error { @@ -353,7 +355,9 @@ func (c *Client[H, Hasher, N, E, Header]) RegisterImportNotificationStream() api return ch } -func (c *Client[H, Hasher, N, E, Header]) UnregisterImportNotificationStream(ch api.ImportNotifications[H, N, Header]) { +func (c *Client[H, Hasher, N, E, Header]) UnregisterImportNotificationStream( + ch api.ImportNotifications[H, N, Header], +) { c.importNotificationChansMtx.Lock() defer c.importNotificationChansMtx.Unlock() _, ok := c.importNotificationChans[ch] @@ -363,7 +367,7 @@ func (c *Client[H, Hasher, N, E, Header]) UnregisterImportNotificationStream(ch delete(c.importNotificationChans, ch) } -func (c *Client[H, Hasher, N, E, Header]) RegisterEveryImportNotificationStream() api.ImportNotifications[H, N, Header] { +func (c *Client[H, _, N, E, Header]) RegisterEveryImportNotificationStream() api.ImportNotifications[H, N, Header] { ch := make(chan api.BlockImportNotification[H, N, Header]) c.everyImportNotificationChansMtx.Lock() defer c.everyImportNotificationChansMtx.Unlock() @@ -371,7 +375,9 @@ func (c *Client[H, Hasher, N, E, Header]) RegisterEveryImportNotificationStream( return ch } -func (c *Client[H, Hasher, N, E, Header]) UnregisterEveryImportNotificationStream(ch api.ImportNotifications[H, N, Header]) { +func (c *Client[H, Hasher, N, E, Header]) UnregisterEveryImportNotificationStream( + ch api.ImportNotifications[H, N, Header], +) { c.everyImportNotificationChansMtx.Lock() defer c.everyImportNotificationChansMtx.Unlock() _, ok := c.everyImportNotificationChans[ch] @@ -381,7 +387,7 @@ func (c *Client[H, Hasher, N, E, Header]) UnregisterEveryImportNotificationStrea delete(c.everyImportNotificationChans, ch) } -func (c *Client[H, Hasher, N, E, Header]) RegisterFinalityNotificationStream() api.FinalityNotifications[H, N, Header] { +func (c *Client[H, _, N, E, Header]) RegisterFinalityNotificationStream() api.FinalityNotifications[H, N, Header] { ch := make(chan api.FinalityNotification[H, N, Header]) c.finalityNotificationChansMtx.Lock() defer c.finalityNotificationChansMtx.Unlock() @@ -389,7 +395,9 @@ func (c *Client[H, Hasher, N, E, Header]) RegisterFinalityNotificationStream() a return ch } -func (c *Client[H, Hasher, N, E, Header]) UnregisterFinalityNotificationStream(ch api.FinalityNotifications[H, N, Header]) { +func (c *Client[H, Hasher, N, E, Header]) UnregisterFinalityNotificationStream( + ch api.FinalityNotifications[H, N, Header], +) { c.finalityNotificationChansMtx.Lock() defer c.finalityNotificationChansMtx.Unlock() _, ok := c.finalityNotificationChans[ch] @@ -399,6 +407,9 @@ func (c *Client[H, Hasher, N, E, Header]) UnregisterFinalityNotificationStream(c delete(c.finalityNotificationChans, ch) } -func (c *Client[H, Hasher, N, E, Header]) StorageChangesNotificationStream(filterKeys []storage.StorageKey, childFilterKeys []api.ChildFilterKeys) api.StorageEventStream[H] { +func (c *Client[H, Hasher, N, E, Header]) StorageChangesNotificationStream( + filterKeys []storage.StorageKey, + childFilterKeys []api.ChildFilterKeys, +) api.StorageEventStream[H] { return c.storageNotifications.Listen(filterKeys, childFilterKeys) } diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 52d57b638d..90b5343aab 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -16,6 +16,8 @@ func (noopExtrinsic) IsSigned() *bool { return nil } +var _ runtime.Extrinsic = noopExtrinsic{} + type TestClient struct { Client[ hash.H256, runtime.BlakeTwo256, uint64, noopExtrinsic, *generic.Header[uint64, hash.H256, runtime.BlakeTwo256], diff --git a/internal/client/utils/pubsub/pubsub.go b/internal/client/utils/pubsub/pubsub.go index 3bb62976d9..82c2d20545 100644 --- a/internal/client/utils/pubsub/pubsub.go +++ b/internal/client/utils/pubsub/pubsub.go @@ -71,7 +71,7 @@ type Hub[K, M, Item any, R Registry[K, M, Item]] struct { shared[Item, R] } -// NewHub creates a new instance of Hub over the initialized Registry. +// NewHub creates a new instance of Hub over the initialised Registry. func NewHub[K any, M, Item any, R Registry[K, M, Item]](tracingKey string, registry R) *Hub[K, M, Item, R] { return &Hub[K, M, Item, R]{ tracingKey: tracingKey,