Skip to content

Commit

Permalink
fix(runtime/storage): Wrap the block execution under a transaction (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
EclesioMeloJunior authored Aug 23, 2024
1 parent ea5be08 commit b6a687d
Show file tree
Hide file tree
Showing 16 changed files with 36 additions and 34 deletions.
2 changes: 1 addition & 1 deletion dot/core/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func (s *Service) handleBlock(block *types.Block, state *rtstorage.TrieState) er
}

logger.Debugf("imported block %s and stored state trie with root %s",
block.Header.Hash(), state.MustRoot())
block.Header.Hash(), state.Trie().MustHash())

parentRuntimeInstance, err := s.blockState.GetRuntime(block.Header.ParentHash)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/childstate_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func setupChildStateStorage(t *testing.T) (*ChildStateModule, common.Hash) {
err = tr.SetChildStorage(childStorageKey, []byte(":another_child"), []byte("value"))
require.NoError(t, err)

stateRoot, err := tr.Root()
stateRoot, err := tr.Trie().Hash()
require.NoError(t, err)

bb, err := st.Block.BestBlock()
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/childstate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ 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()
stateRoot, err := tr.Trie().Hash()
require.NoError(t, err)

return tr.Trie(), stateRoot
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/state_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ func setupStateModule(t *testing.T) (*StateModule, *common.Hash, *common.Hash) {
err = ts.SetChildStorage([]byte(`:child1`), []byte(`:key1`), []byte(`:childValue1`))
require.NoError(t, err)

sr1, err := ts.Root()
sr1, err := ts.Trie().Hash()
require.NoError(t, err)
err = chain.Storage.StoreTrie(ts, nil)
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/system_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func setupSystemModule(t *testing.T) *SystemModule {
Header: types.Header{
Number: 3,
ParentHash: chain.Block.BestBlockHash(),
StateRoot: ts.MustRoot(),
StateRoot: ts.Trie().MustHash(),
Digest: digest,
},
Body: types.Body{},
Expand Down
2 changes: 1 addition & 1 deletion dot/state/inmemory_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func NewStorageState(db database.Database, blockState *BlockState,

// StoreTrie stores the given trie in the StorageState and writes it to the database
func (s *InmemoryStorageState) StoreTrie(ts *storage.TrieState, header *types.Header) error {
root := ts.MustRoot()
root := ts.Trie().MustHash()
s.tries.softSet(root, ts.Trie())

if header != nil {
Expand Down
10 changes: 5 additions & 5 deletions dot/state/inmemory_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestStorage_StoreAndLoadTrie(t *testing.T) {
ts, err := storage.TrieState(&trie.EmptyHash)
require.NoError(t, err)

root, err := ts.Root()
root, err := ts.Trie().Hash()
require.NoError(t, err)
err = storage.StoreTrie(ts, nil)
require.NoError(t, err)
Expand All @@ -57,7 +57,7 @@ func TestStorage_GetStorageByBlockHash(t *testing.T) {
value := []byte("testvalue")
ts.Put(key, value)

root, err := ts.Root()
root, err := ts.Trie().Hash()
require.NoError(t, err)
err = storage.StoreTrie(ts, nil)
require.NoError(t, err)
Expand Down Expand Up @@ -89,7 +89,7 @@ func TestStorage_TrieState(t *testing.T) {
require.NoError(t, err)
ts.Put([]byte("noot"), []byte("washere"))

root, err := ts.Root()
root, err := ts.Trie().Hash()
require.NoError(t, err)
err = storage.StoreTrie(ts, nil)
require.NoError(t, err)
Expand Down Expand Up @@ -123,7 +123,7 @@ func TestStorage_LoadFromDB(t *testing.T) {
ts.Put(kv.key, kv.value)
}

root, err := ts.Root()
root, err := ts.Trie().Hash()
require.NoError(t, err)

// Write trie to disk.
Expand Down Expand Up @@ -196,7 +196,7 @@ func TestGetStorageChildAndGetStorageFromChild(t *testing.T) {

trieState := runtime.NewTrieState(genTrie)

header := types.NewHeader(blockState.GenesisHash(), trieState.MustRoot(),
header := types.NewHeader(blockState.GenesisHash(), trieState.Trie().MustHash(),
common.Hash{}, 1, types.NewDigest())

err = storage.StoreTrie(trieState, header)
Expand Down
2 changes: 1 addition & 1 deletion dot/state/service_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func generateBlockWithRandomTrie(t *testing.T, serv *Service,
err = trieState.Put(key, value)
require.NoError(t, err)

trieStateRoot, err := trieState.Root()
trieStateRoot, err := trieState.Trie().Hash()
require.NoError(t, err)

if parent == nil {
Expand Down
2 changes: 1 addition & 1 deletion dot/sync/chain_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ func (cs *chainSync) handleBlock(block *types.Block, announceImportedBlock bool)
return err
}

root := ts.MustRoot()
root := ts.Trie().MustHash()
if !bytes.Equal(parent.StateRoot[:], root[:]) {
panic("parent state root does not match snapshot state root")
}
Expand Down
10 changes: 5 additions & 5 deletions dot/sync/chain_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ func Test_chainSync_onBlockAnnounce(t *testing.T) {

errTest := errors.New("test error")
emptyTrieState := storage.NewTrieState(inmemory_trie.NewEmptyTrie())
block1AnnounceHeader := types.NewHeader(common.Hash{}, emptyTrieState.MustRoot(),
block1AnnounceHeader := types.NewHeader(common.Hash{}, emptyTrieState.Trie().MustHash(),
common.Hash{}, 1, nil)
block2AnnounceHeader := types.NewHeader(block1AnnounceHeader.Hash(),
emptyTrieState.MustRoot(),
emptyTrieState.Trie().MustHash(),
common.Hash{}, 2, nil)

testCases := map[string]struct {
Expand Down Expand Up @@ -252,10 +252,10 @@ func Test_chainSync_onBlockAnnounceHandshake_tipModeNeedToCatchup(t *testing.T)
const somePeer = peer.ID("abc")

emptyTrieState := storage.NewTrieState(inmemory_trie.NewEmptyTrie())
block1AnnounceHeader := types.NewHeader(common.Hash{}, emptyTrieState.MustRoot(),
block1AnnounceHeader := types.NewHeader(common.Hash{}, emptyTrieState.Trie().MustHash(),
common.Hash{}, 1, nil)
block2AnnounceHeader := types.NewHeader(block1AnnounceHeader.Hash(),
emptyTrieState.MustRoot(),
emptyTrieState.Trie().MustHash(),
common.Hash{}, 130, nil)

blockStateMock := NewMockBlockState(ctrl)
Expand Down Expand Up @@ -1382,7 +1382,7 @@ func createSuccesfullBlockResponse(t *testing.T, parentHeader common.Hash,
response.BlockData = make([]*types.BlockData, numBlocks)

emptyTrieState := storage.NewTrieState(inmemory_trie.NewEmptyTrie())
tsRoot := emptyTrieState.MustRoot()
tsRoot := emptyTrieState.Trie().MustHash()

firstHeader := types.NewHeader(parentHeader, tsRoot, common.Hash{},
uint(startingAt), nil)
Expand Down
2 changes: 1 addition & 1 deletion dot/sync/syncer_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func newTestSyncer(t *testing.T) *Service {

stateSrvc.Block.StoreRuntime(block.Header.Hash(), instance)
logger.Debugf("imported block %s and stored state trie with root %s",
block.Header.Hash(), ts.MustRoot())
block.Header.Hash(), ts.Trie().MustHash())
return nil
}).AnyTimes()
cfg.BlockImportHandler = blockImportHandler
Expand Down
18 changes: 7 additions & 11 deletions lib/runtime/storage/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,14 @@ func (t *TrieState) Get(key []byte) []byte {
return t.state.Get(key)
}

// MustRoot returns the trie's root hash. It panics if it fails to compute the root.
func (t *TrieState) MustRoot() common.Hash {
hash, err := t.Root()
if err != nil {
panic(err)
}

return hash
}

// Root returns the trie's root hash
// Root is executed in the block finalisation
// when it is wrapping everything and needs to ensure
// the root hash matches the expected one, in this case
// we commit the changeset we started in the beginning
// WARN: this function should be called only by ext_storage_root_version_1
func (t *TrieState) Root() (common.Hash, error) {
t.CommitTransaction()

// Since the Root function is called without running transactions we can do:
if currentTx := t.getCurrentTransaction(); currentTx != nil {
panic("cannot calculate root with running transactions")
Expand Down
4 changes: 2 additions & 2 deletions lib/runtime/storage/trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,8 @@ func TestTrieState_Root(t *testing.T) {
ts.Put([]byte(tc), []byte(tc))
}

expected := ts.MustRoot()
require.Equal(t, expected, ts.MustRoot())
expected := ts.Trie().MustHash()
require.Equal(t, expected, ts.Trie().MustHash())
}

func TestTrieState_ChildRoot(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions lib/runtime/wazero/imports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,7 @@ func Test_ext_storage_read_version_1_OffsetLargerThanValue(t *testing.T) {
func Test_ext_storage_root_version_1(t *testing.T) {
inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME, TestWithVersion(DefaultVersion))

inst.Context.Storage.StartTransaction()
ret, err := inst.Exec("rtm_ext_storage_root_version_1", []byte{})
require.NoError(t, err)

Expand All @@ -2200,6 +2201,7 @@ func Test_ext_storage_root_version_2(t *testing.T) {
encVersion, err := scale.Marshal(stateVersion)
require.NoError(t, err)

inst.Context.Storage.StartTransaction()
ret, err := inst.Exec("rtm_ext_storage_root_version_2", encVersion)
require.NoError(t, err)

Expand Down
5 changes: 5 additions & 0 deletions lib/runtime/wazero/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,7 @@ func (in *Instance) InitializeBlock(header *types.Header) error {
return fmt.Errorf("cannot encode header: %w", err)
}

in.Context.Storage.StartTransaction()
_, err = in.Exec(runtime.CoreInitializeBlock, encodedHeader)
return err
}
Expand Down Expand Up @@ -992,6 +993,10 @@ func (in *Instance) ExecuteBlock(block *types.Block) ([]byte, error) {
return nil, err
}

// start an changeset at the beginning of the block execution
// then clear prefix can work correctly by ignoring
// keys included under current block execution
in.Context.Storage.StartTransaction()
return in.Exec(runtime.CoreExecuteBlock, bdEnc)
}

Expand Down
3 changes: 1 addition & 2 deletions lib/runtime/wazero/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1013,8 +1013,7 @@ func TestInstance_ExecuteBlock_PaseoRuntime_PaseoBlock1008649(t *testing.T) {
require.NoError(t, err)

expectedRootNew := common.MustHexToHash("0xc75b6a15438acb997f925a09714092fc463af3ba44ab93654c89b775c44dfe13")
require.Equal(t, expectedRootNew, state.MustRoot())

require.Equal(t, expectedRootNew, state.Trie().MustHash())
}

func TestInstance_ExecuteBlock_PolkadotBlock1089328(t *testing.T) {
Expand Down

0 comments on commit b6a687d

Please sign in to comment.