From b2a8a861933317002e23cdbd7479755c00af01e1 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 15 Nov 2022 12:53:02 +0000 Subject: [PATCH] chore(lib/trie): remove `Store` method (#2922) - `WriteDirty` is just the clever version of `Store`, where we write only nodes that got changed in-memory from the version we have in the database. - This also ensures all the nodes are set as dirty correctly --- dot/state/base_test.go | 2 +- dot/state/initialize.go | 4 +- dot/state/service.go | 2 +- dot/state/service_test.go | 13 ++++++- lib/runtime/wasmer/imports_test.go | 2 +- lib/trie/database.go | 61 ------------------------------ lib/trie/database_test.go | 12 +++--- lib/trie/proof/proof_test.go | 2 +- lib/trie/trie_endtoend_test.go | 2 +- 9 files changed, 25 insertions(+), 75 deletions(-) diff --git a/dot/state/base_test.go b/dot/state/base_test.go index a217d63887..a6bedcde74 100644 --- a/dot/state/base_test.go +++ b/dot/state/base_test.go @@ -26,7 +26,7 @@ func TestTrie_StoreAndLoadFromDB(t *testing.T) { tt.Put(key, value) } - err := tt.Store(db) + err := tt.WriteDirty(db) require.NoError(t, err) encroot, err := tt.Hash() diff --git a/dot/state/initialize.go b/dot/state/initialize.go index 565e30fb72..cf226353ef 100644 --- a/dot/state/initialize.go +++ b/dot/state/initialize.go @@ -42,7 +42,7 @@ func (s *Service) Initialise(gen *genesis.Genesis, header *types.Header, t *trie return fmt.Errorf("failed to clear database: %s", err) } - if err = t.Store(chaindb.NewTable(db, storagePrefix)); err != nil { + if err = t.WriteDirty(chaindb.NewTable(db, storagePrefix)); err != nil { return fmt.Errorf("failed to write genesis trie to database: %w", err) } @@ -137,7 +137,7 @@ func loadGrandpaAuthorities(t *trie.Trie) ([]types.GrandpaVoter, error) { // storeInitialValues writes initial genesis values to the state database func (s *Service) storeInitialValues(data *genesis.Data, t *trie.Trie) error { // write genesis trie to database - if err := t.Store(chaindb.NewTable(s.db, storagePrefix)); err != nil { + if err := t.WriteDirty(chaindb.NewTable(s.db, storagePrefix)); err != nil { return fmt.Errorf("failed to write trie to database: %s", err) } diff --git a/dot/state/service.go b/dot/state/service.go index 0d9fa51b7f..c33122274a 100644 --- a/dot/state/service.go +++ b/dot/state/service.go @@ -316,7 +316,7 @@ func (s *Service) Import(header *types.Header, t *trie.Trie, firstSlot uint64) e logger.Info("importing storage trie from base path " + s.dbPath + " with root " + root.String() + "...") - if err := t.Store(storage.db); err != nil { + if err := t.WriteDirty(storage.db); err != nil { return err } diff --git a/dot/state/service_test.go b/dot/state/service_test.go index e788043e6d..c98fa976f3 100644 --- a/dot/state/service_test.go +++ b/dot/state/service_test.go @@ -72,13 +72,24 @@ func TestService_Initialise(t *testing.T) { state := newTestService(t) genData, genTrie, genesisHeader := newTestGenesisWithTrieAndHeader(t) + + // Deep copy the trie because of the following: + // Initialise clears the database, writes only dirty nodes to disk + // and marks them as clean. + // Initialise is called twice. + // The first call writes all nodes to disk and marks them as clean in the + // in-memory trie representation. + // If the same trie is re-used for the second call, the database is cleared + // and nothing is written to disk since all nodes are marked as clean. + genTrieCopy := genTrie.DeepCopy() + err := state.Initialise(&genData, &genesisHeader, &genTrie) require.NoError(t, err) genesisHeaderPtr := types.NewHeader(common.NewHash([]byte{77}), genTrie.MustHash(), trie.EmptyHash, 0, types.NewDigest()) - err = state.Initialise(&genData, genesisHeaderPtr, &genTrie) + err = state.Initialise(&genData, genesisHeaderPtr, genTrieCopy) require.NoError(t, err) err = state.SetupBase() diff --git a/lib/runtime/wasmer/imports_test.go b/lib/runtime/wasmer/imports_test.go index 7061110a77..e993fe6715 100644 --- a/lib/runtime/wasmer/imports_test.go +++ b/lib/runtime/wasmer/imports_test.go @@ -1789,7 +1789,7 @@ func Test_ext_trie_blake2_256_verify_proof_version_1(t *testing.T) { tr.Put([]byte("otherwise"), []byte("randomstuff")) tr.Put([]byte("cat"), []byte("another animal")) - err = tr.Store(memdb) + err = tr.WriteDirty(memdb) require.NoError(t, err) hash, err := tr.Hash() diff --git a/lib/trie/database.go b/lib/trie/database.go index b644878a2c..b3cbdad602 100644 --- a/lib/trie/database.go +++ b/lib/trie/database.go @@ -20,67 +20,6 @@ type Database interface { Get(key []byte) (value []byte, err error) } -// Store stores each trie node in the database, -// where the key is the hash of the encoded node -// and the value is the encoded node. -// Generally, this will only be used for the genesis trie. -func (t *Trie) Store(db chaindb.Database) error { - for _, v := range t.childTries { - if err := v.Store(db); err != nil { - return fmt.Errorf("failed to store child trie with root hash=0x%x in the db: %w", v.root.MerkleValue, err) - } - } - - batch := db.NewBatch() - err := t.storeNode(batch, t.root) - if err != nil { - batch.Reset() - return err - } - - return batch.Flush() -} - -func (t *Trie) storeNode(db chaindb.Batch, n *Node) (err error) { - if n == nil { - return nil - } - - var encoding, hash []byte - if n == t.root { - encoding, hash, err = n.EncodeAndHashRoot() - } else { - encoding, hash, err = n.EncodeAndHash() - } - if err != nil { - return err - } - - err = db.Put(hash, encoding) - if err != nil { - return err - } - - if n.Kind() == node.Branch { - for _, child := range n.Children { - if child == nil { - continue - } - - err = t.storeNode(db, child) - if err != nil { - return err - } - } - } - - if n.Dirty { - n.SetClean() - } - - return nil -} - // Load reconstructs the trie from the database from the given root hash. // It is used when restarting the node to load the current state trie. func (t *Trie) Load(db Database, rootHash common.Hash) error { diff --git a/lib/trie/database_test.go b/lib/trie/database_test.go index 341eaa2e88..b552ae2933 100644 --- a/lib/trie/database_test.go +++ b/lib/trie/database_test.go @@ -29,7 +29,7 @@ func Test_Trie_Store_Load(t *testing.T) { rootHash := trie.MustHash() db := newTestDB(t) - err := trie.Store(db) + err := trie.WriteDirty(db) require.NoError(t, err) trieFromDB := NewEmptyTrie() @@ -64,7 +64,7 @@ func Test_Trie_WriteDirty_Put(t *testing.T) { assert.Equalf(t, value, valueFromDB, "for key=%x", key) } - err := trie.Store(db) + err := trie.WriteDirty(db) require.NoError(t, err) // Pick an existing key and replace its value @@ -100,7 +100,7 @@ func Test_Trie_WriteDirty_Delete(t *testing.T) { keysToDelete := pickKeys(keyValues, generator, size/50) db := newTestDB(t) - err := trie.Store(db) + err := trie.WriteDirty(db) require.NoError(t, err) deletedKeys := make(map[string]struct{}, len(keysToDelete)) @@ -141,7 +141,7 @@ func Test_Trie_WriteDirty_ClearPrefix(t *testing.T) { keysToClearPrefix := pickKeys(keyValues, generator, size/50) db := newTestDB(t) - err := trie.Store(db) + err := trie.WriteDirty(db) require.NoError(t, err) for _, keyToClearPrefix := range keysToClearPrefix { @@ -261,7 +261,7 @@ func Test_GetFromDB(t *testing.T) { trie, keyValues := makeSeededTrie(t, size) db := newTestDB(t) - err := trie.Store(db) + err := trie.WriteDirty(db) require.NoError(t, err) root := trie.MustHash() @@ -298,7 +298,7 @@ func Test_Trie_PutChild_Store_Load(t *testing.T) { err := trie.PutChild(keyToChildTrie, childTrie) require.NoError(t, err) - err = trie.Store(db) + err = trie.WriteDirty(db) require.NoError(t, err) trieFromDB := NewEmptyTrie() diff --git a/lib/trie/proof/proof_test.go b/lib/trie/proof/proof_test.go index 7a403553fb..51ecc49787 100644 --- a/lib/trie/proof/proof_test.go +++ b/lib/trie/proof/proof_test.go @@ -37,7 +37,7 @@ func Test_Generate_Verify(t *testing.T) { InMemory: true, }) require.NoError(t, err) - err = trie.Store(database) + err = trie.WriteDirty(database) require.NoError(t, err) for i, key := range keys { diff --git a/lib/trie/trie_endtoend_test.go b/lib/trie/trie_endtoend_test.go index 5fb670e25f..46d214854a 100644 --- a/lib/trie/trie_endtoend_test.go +++ b/lib/trie/trie_endtoend_test.go @@ -304,7 +304,7 @@ func TestTrieDiff(t *testing.T) { } newTrie := trie.Snapshot() - err = trie.Store(storageDB) + err = trie.WriteDirty(storageDB) require.NoError(t, err) tests = []keyValues{