Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce revised BlockState and StorageState interface for entire public API #4459

Open
timwu20 opened this issue Jan 14, 2025 · 0 comments

Comments

@timwu20
Copy link
Contributor

timwu20 commented Jan 14, 2025

Issue Summary

From design doc:

Currently the state.BlockState type is essentially used to store block history and to set finalization for stored blocks. The type state.BlockState does not have a corresponding interface that represents the entire public API of the type. After looking through the code, I've compiled the entire public interface of state.BlockState that is called by other packages. The interface is as follows:

type BlockState interface {
	AddBlock(*types.Block) error
	AddBlockWithArrivalTime(block *types.Block, arrivalTime time.Time) error

	BestBlock() (*types.Block, error) 
	BestBlockHash() common.Hash
	BestBlockHeader() (*types.Header, error)
	BestBlockNumber() (number uint, err error)
	GenesisHash() common.Hash

	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)
	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)
	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
	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
	
	IsDescendantOf(parent, child common.Hash) (bool, error)
	LowestCommonAncestor(a, b common.Hash) (common.Hash, error)
	NumberIsFinalised(blockNumber uint) (bool, error)

	Range(startHash, endHash common.Hash) (hashes []common.Hash, err error)
	RangeInMemory(start, end common.Hash) ([]common.Hash, error)

	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)

	IsPaused() bool
	Pause() error
}

StorageState is an interface that is locally defined in a number of packages. It represents the functionality regarding accessing the current TrieState which gives access to the underlying in memory state trie (canonically known as "storage") for a given hash. Generation of storage trie proofs is part of this interface as well. The interface with largest amount of methods is defined in dot/core. The implementation of these StorageState interfaces is implemented by the type state.InmemoryStorageState. I've compiled the entire public interface of state.InmemoryStorageState that is called by other packages. The interface is as follows:

type StorageState interface {
	TrieState(root *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)
	StorageRoot() (common.Hash, error) // best block state root, use HeaderBackend
	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)
    
	LoadCode(hash *common.Hash) ([]byte, error)
	LoadCodeHash(hash *common.Hash) (common.Hash, error)
    
	RegisterStorageObserver(o Observer)
	UnregisterStorageObserver(o Observer)
    
	sync.Locker
}

Acceptance Criteria

  • Verify that the above interfaces can be used in place wherever the concrete BlockState type is defined.
  • Refactor NewBlockState to return an interface BlockState.
  • Rename current BlockState type to private blockState or defaultBlockState.
  • Introduce an all encompassing interface for StorageState.
  • Regression test

Other information and links

@timwu20 timwu20 changed the title Introduce revised BlockState and TrieState interface for entire public API Introduce revised BlockState and StorageState interface for entire public API Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant