From b758ae98e0dab8e2419d8f259d48dd6ac9d0cfa9 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Tue, 10 Dec 2024 10:37:20 +0800 Subject: [PATCH] all: distinguish empty state root in merkle and verkle --- cmd/devp2p/internal/ethtest/snap.go | 2 +- cmd/evm/internal/t8ntool/execution.go | 2 +- cmd/geth/snapshot.go | 11 +++- cmd/utils/cmd.go | 6 +- core/genesis.go | 11 ++-- core/genesis_test.go | 9 ++- core/state/database.go | 4 +- core/state/pruner/pruner.go | 2 +- core/state/reader.go | 17 +++--- core/state/snapshot/conversion.go | 4 +- core/state/snapshot/generate.go | 10 +++- core/state/snapshot/generate_test.go | 50 ++++++++-------- core/state/snapshot/utils.go | 4 +- core/state/state_object.go | 33 ++++++++--- core/state/state_test.go | 8 +-- core/state/statedb.go | 6 +- core/state/statedb_fuzz_test.go | 18 +++--- core/state/statedb_hooked_test.go | 4 +- core/state/statedb_test.go | 40 ++++++------- core/state/stateupdate.go | 5 +- core/state/sync_test.go | 6 +- core/state/trie_prefetcher_test.go | 4 +- core/txpool/blobpool/blobpool.go | 2 +- core/txpool/blobpool/blobpool_test.go | 12 ++-- core/txpool/legacypool/legacypool.go | 2 +- core/txpool/legacypool/legacypool2_test.go | 8 +-- core/txpool/legacypool/legacypool_test.go | 40 ++++++------- core/types/hashes.go | 19 +++---- core/types/state_account.go | 26 ++++++--- core/verkle_witness_test.go | 2 +- core/vm/evm.go | 2 +- core/vm/gas_table_test.go | 4 +- core/vm/instructions_test.go | 2 +- core/vm/interpreter_test.go | 2 +- core/vm/runtime/runtime.go | 8 ++- core/vm/runtime/runtime_test.go | 14 ++--- eth/api_debug.go | 2 +- eth/api_debug_test.go | 8 +-- eth/protocols/eth/handlers.go | 2 +- eth/protocols/snap/protocol.go | 2 +- eth/protocols/snap/sync.go | 4 +- eth/protocols/snap/sync_test.go | 22 ++++---- internal/ethapi/api.go | 4 +- internal/ethapi/api_test.go | 8 +-- tests/state_test_util.go | 4 +- trie/database_test.go | 2 +- trie/iterator.go | 4 +- trie/iterator_test.go | 16 +++--- trie/secure_trie_test.go | 6 +- trie/stacktrie.go | 2 +- trie/stacktrie_fuzzer_test.go | 2 +- trie/sync.go | 2 +- trie/sync_test.go | 16 +++--- trie/tracer_test.go | 8 +-- trie/trie.go | 12 ++-- trie/trie_reader.go | 11 ++-- trie/trie_test.go | 24 ++++---- trie/verkle.go | 4 +- triedb/database.go | 2 +- triedb/hashdb/database.go | 8 ++- triedb/pathdb/database.go | 66 ++++++++++++++++------ triedb/pathdb/database_test.go | 25 ++++---- triedb/pathdb/execute.go | 6 +- triedb/pathdb/history_test.go | 6 +- triedb/pathdb/journal.go | 15 +++-- triedb/pathdb/layertree.go | 9 +-- 66 files changed, 397 insertions(+), 304 deletions(-) diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go index 9c1efa0e8e22e..70db91ee2469e 100644 --- a/cmd/devp2p/internal/ethtest/snap.go +++ b/cmd/devp2p/internal/ethtest/snap.go @@ -479,7 +479,7 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { { desc: `Here we request the empty state root (which is not an existing code hash). The server should deliver an empty response with no items.`, nBytes: 10000, - hashes: []common.Hash{types.EmptyRootHash}, + hashes: []common.Hash{types.EmptyMerkleHash}, // TODO add verkle tests expHashes: 0, }, { diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 7a0de86a1106e..ce17321c64d14 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -427,7 +427,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB { tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) sdb := state.NewDatabase(tdb, nil) - statedb, _ := state.New(types.EmptyRootHash, sdb) + statedb, _ := state.New(types.EmptyMerkleHash, sdb) // TODO support verkle node in t8n for addr, a := range accounts { statedb.SetCode(addr, a.Code) statedb.SetNonce(addr, a.Nonce) diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index f0be52a0dffb3..b63890866671a 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -265,6 +265,8 @@ func checkDanglingStorage(ctx *cli.Context) error { // traverseState is a helper function used for pruning verification. // Basically it just iterates the trie, ensure all nodes and associated // contract codes are present. +// +// TODO(rjl493456442) this command is not compatible with verkle. func traverseState(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() @@ -324,7 +326,7 @@ func traverseState(ctx *cli.Context) error { log.Error("Invalid account encountered during traversal", "err", err) return err } - if acc.Root != types.EmptyRootHash { + if acc.Root != types.EmptyMerkleHash { id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root) storageTrie, err := trie.NewStateTrie(id, triedb) if err != nil { @@ -374,6 +376,8 @@ func traverseState(ctx *cli.Context) error { // Basically it just iterates the trie, ensure all nodes and associated // contract codes are present. It's basically identical to traverseState // but it will check each trie node. +// +// TODO(rjl493456442) this command is not compatible with verkle. func traverseRawState(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() @@ -462,7 +466,7 @@ func traverseRawState(ctx *cli.Context) error { log.Error("Invalid account encountered during traversal", "err", err) return errors.New("invalid account") } - if acc.Root != types.EmptyRootHash { + if acc.Root != types.EmptyMerkleHash { id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root) storageTrie, err := trie.NewStateTrie(id, triedb) if err != nil { @@ -537,6 +541,7 @@ func parseRoot(input string) (common.Hash, error) { return h, nil } +// dumpState is not compatible with verkle mode. func dumpState(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() @@ -578,7 +583,7 @@ func dumpState(ctx *cli.Context) error { Root common.Hash `json:"root"` }{root}) for accIt.Next() { - account, err := types.FullAccount(accIt.Account()) + account, err := types.FullAccount(accIt.Account(), false) if err != nil { return err } diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 791b3d1d205a6..ed30fda4dbf6f 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -567,6 +567,8 @@ func ExportPreimages(db ethdb.Database, fn string) error { // ExportSnapshotPreimages exports the preimages corresponding to the enumeration of // the snapshot for a given root. +// +// TODO(rjl493456442) this command is not compatible with verkle. func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn string, root common.Hash) error { log.Info("Exporting preimages", "file", fn) @@ -608,7 +610,7 @@ func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn defer accIt.Release() for accIt.Next() { - acc, err := types.FullAccount(accIt.Account()) + acc, err := types.FullAccount(accIt.Account(), false) if err != nil { log.Error("Failed to get full account", "error", err) return @@ -616,7 +618,7 @@ func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn preimages += 1 hashCh <- hashAndPreimageSize{Hash: accIt.Hash(), Size: common.AddressLength} - if acc.Root != (common.Hash{}) && acc.Root != types.EmptyRootHash { + if acc.Root != (common.Hash{}) && acc.Root != types.EmptyMerkleHash { stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{}) if err != nil { log.Error("Failed to create storage iterator", "error", err) diff --git a/core/genesis.go b/core/genesis.go index 85ef049ba6cfd..35c4635f34382 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -128,7 +128,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { // Create an ephemeral in-memory database for computing hash, // all the derived states will be discarded to not pollute disk. db := rawdb.NewMemoryDatabase() - statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb.NewDatabase(db, config), nil)) + statedb, err := state.New(types.EmptyRootHash(isVerkle), state.NewDatabase(triedb.NewDatabase(db, config), nil)) if err != nil { return common.Hash{}, err } @@ -148,7 +148,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { // flushAlloc is very similar with hash, but the main difference is all the // generated states will be persisted into the given database. func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) { - statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb, nil)) + statedb, err := state.New(types.EmptyRootHash(triedb.IsVerkle()), state.NewDatabase(triedb, nil)) if err != nil { return common.Hash{}, err } @@ -169,7 +169,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, e return common.Hash{}, err } // Commit newly generated states into disk if it's not empty. - if root != types.EmptyRootHash { + if root != types.EmptyRootHash(triedb.IsVerkle()) { if err := triedb.Commit(root, true); err != nil { return common.Hash{}, err } @@ -292,7 +292,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g // is initialized with an external ancient store. Commit genesis state // in this case. header := rawdb.ReadHeader(db, stored, 0) - if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) { + if header.Root != types.EmptyRootHash(triedb.IsVerkle()) && !triedb.Initialized(header.Root) { if genesis == nil { genesis = DefaultGenesisBlock() } @@ -494,6 +494,9 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo if config.Clique != nil && len(g.ExtraData) < 32+crypto.SignatureLength { return nil, errors.New("can't start clique chain without signers") } + if g.IsVerkle() != triedb.IsVerkle() { + return nil, errors.New("supplied triedb is in wrong mode") + } // flush the data to disk and compute the state root root, err := flushAlloc(&g.Alloc, triedb) if err != nil { diff --git a/core/genesis_test.go b/core/genesis_test.go index 3ec87474e568b..7b4615cf8c93d 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -175,11 +175,18 @@ func TestGenesisHashes(t *testing.T) { want common.Hash }{ {DefaultGenesisBlock(), params.MainnetGenesisHash}, + {DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash}, {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, + + // TODO (rjl493456442, gballet) add verkle genesis tests } { // Test via MustCommit db := rawdb.NewMemoryDatabase() - if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want { + config := triedb.HashDefaults + if c.genesis.IsVerkle() { + config = triedb.VerkleDefaults + } + if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, config)).Hash(); have != c.want { t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) } // Test via ToBlock diff --git a/core/state/database.go b/core/state/database.go index faf4954650bf7..e6f83d1823c4a 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -183,14 +183,14 @@ func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) { // then construct the legacy snap reader. snap := db.snap.Snapshot(stateRoot) if snap != nil { - readers = append(readers, newFlatReader(snap)) + readers = append(readers, newFlatReader(snap, db.triedb.IsVerkle())) } } else { // If standalone state snapshot is not available, try to construct // the state reader with database. reader, err := db.triedb.StateReader(stateRoot) if err == nil { - readers = append(readers, newFlatReader(reader)) // state reader is optional + readers = append(readers, newFlatReader(reader, db.triedb.IsVerkle())) // state reader is optional } } // Set up the trie reader, which is expected to always be available diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index 46558a6fceeca..1eaf64b79917d 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -431,7 +431,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error { if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil { return err } - if acc.Root != types.EmptyRootHash { + if acc.Root != types.EmptyMerkleHash { id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root) storageTrie, err := trie.NewStateTrie(id, triedb.NewDatabase(db, triedb.HashDefaults)) if err != nil { diff --git a/core/state/reader.go b/core/state/reader.go index a0f15dfcc8b5c..437b57eff0ec6 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -125,15 +125,17 @@ func (r *cachingCodeReader) CodeSize(addr common.Address, codeHash common.Hash) // flatReader wraps a database state reader. type flatReader struct { - reader database.StateReader - buff crypto.KeccakState + reader database.StateReader + buff crypto.KeccakState + isVerkle bool } // newFlatReader constructs a state reader with on the given state root. -func newFlatReader(reader database.StateReader) *flatReader { +func newFlatReader(reader database.StateReader, isVerkle bool) *flatReader { return &flatReader{ - reader: reader, - buff: crypto.NewKeccakState(), + reader: reader, + buff: crypto.NewKeccakState(), + isVerkle: isVerkle, } } @@ -160,8 +162,9 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) { if len(acct.CodeHash) == 0 { acct.CodeHash = types.EmptyCodeHash.Bytes() } + // Annotate the empty root hash, especially for merkle tree. if acct.Root == (common.Hash{}) { - acct.Root = types.EmptyRootHash + acct.Root = types.EmptyRootHash(r.isVerkle) } return acct, nil } @@ -240,7 +243,7 @@ func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) { return nil, err } if account == nil { - r.subRoots[addr] = types.EmptyRootHash + r.subRoots[addr] = types.EmptyRootHash(r.db.IsVerkle()) } else { r.subRoots[addr] = account.Root } diff --git a/core/state/snapshot/conversion.go b/core/state/snapshot/conversion.go index 4b0774f2ae30a..5fbbe9f703510 100644 --- a/core/state/snapshot/conversion.go +++ b/core/state/snapshot/conversion.go @@ -290,7 +290,7 @@ func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, accou fullData []byte ) if leafCallback == nil { - fullData, err = types.FullAccountRLP(it.(AccountIterator).Account()) + fullData, err = types.FullAccountRLP(it.(AccountIterator).Account(), false) if err != nil { return stop(err) } @@ -302,7 +302,7 @@ func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, accou return stop(err) } // Fetch the next account and process it concurrently - account, err := types.FullAccount(it.(AccountIterator).Account()) + account, err := types.FullAccount(it.(AccountIterator).Account(), false) if err != nil { return stop(err) } diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go index 01fb55ea4cd68..b36ecb788f9a1 100644 --- a/core/state/snapshot/generate.go +++ b/core/state/snapshot/generate.go @@ -582,7 +582,7 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) { dataLen -= 32 } - if acc.Root == types.EmptyRootHash { + if acc.Root == types.EmptyMerkleHash { dataLen -= 32 } snapRecoveredAccountMeter.Mark(1) @@ -609,7 +609,7 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er // If the iterated account is the contract, create a further loop to // verify or regenerate the contract storage. - if acc.Root == types.EmptyRootHash { + if acc.Root == types.EmptyMerkleHash { ctx.removeStorageAt(account) } else { var storeMarker []byte @@ -627,7 +627,11 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er origin := common.CopyBytes(accMarker) for { id := trie.StateTrieID(dl.root) - exhausted, last, err := dl.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountCheckRange, onAccount, types.FullAccountRLP) + exhausted, last, err := dl.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountCheckRange, onAccount, + func(data []byte) ([]byte, error) { + return types.FullAccountRLP(data, false) + }, + ) if err != nil { return err // The procedure it aborted, either by external signal or internal error. } diff --git a/core/state/snapshot/generate_test.go b/core/state/snapshot/generate_test.go index 661610840a035..244665591c5b6 100644 --- a/core/state/snapshot/generate_test.go +++ b/core/state/snapshot/generate_test.go @@ -60,7 +60,7 @@ func testGeneration(t *testing.T, scheme string) { stRoot := helper.makeStorageTrie("", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) @@ -102,8 +102,8 @@ func testGenerateExistentState(t *testing.T, scheme string) { helper.addSnapAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -171,7 +171,7 @@ func newHelper(scheme string) *testHelper { config.HashDB = &hashdb.Config{} // disable caching } db := triedb.NewDatabase(diskdb, config) - accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), db) + accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyMerkleHash), db) return &testHelper{ diskdb: diskdb, triedb: db, @@ -210,7 +210,7 @@ func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) func (t *testHelper) makeStorageTrie(accKey string, keys []string, vals []string, commit bool) common.Hash { owner := hashData([]byte(accKey)) addr := common.BytesToAddress([]byte(accKey)) - id := trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash) + id := trie.StorageTrieID(types.EmptyMerkleHash, owner, types.EmptyMerkleHash) stTrie, _ := trie.NewStateTrie(id, t.triedb) for i, k := range keys { stTrie.MustUpdate([]byte(k), []byte(vals[i])) @@ -238,7 +238,7 @@ func (t *testHelper) Commit() common.Hash { if nodes != nil { t.nodes.Merge(nodes) } - t.triedb.Update(root, types.EmptyRootHash, 0, t.nodes, t.states) + t.triedb.Update(root, types.EmptyMerkleHash, 0, t.nodes, t.states) t.triedb.Commit(root, false) return root } @@ -276,7 +276,7 @@ func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) { helper := newHelper(scheme) // Account one, empty root but non-empty database - helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) // Account two, non empty root but empty database @@ -394,14 +394,14 @@ func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) { helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) } // Extra accounts, only in the snap { - helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning - helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle - helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end + helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning + helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle + helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end } root, snap := helper.CommitAndGenerate() @@ -435,9 +435,9 @@ func testGenerateCorruptAccountTrie(t *testing.T, scheme string) { // without any storage slots to keep the test smaller. helper := newHelper(scheme) - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 @@ -479,9 +479,9 @@ func testGenerateMissingStorageTrie(t *testing.T, scheme string) { acc3 = hashData([]byte("acc-3")) helper = newHelper(scheme) ) - stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 @@ -519,9 +519,9 @@ func testGenerateCorruptStorageTrie(t *testing.T, scheme string) { // two of which also has the same 3-slot storage trie attached. helper := newHelper(scheme) - stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 + stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 + helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 stRoot = helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 @@ -653,7 +653,7 @@ func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) { { // 100 accounts exist only in snapshot for i := 0; i < 1000; i++ { - acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) key := hashData([]byte(fmt.Sprintf("acc-%d", i))) rawdb.WriteAccountSnapshot(helper.diskdb, key, val) @@ -695,7 +695,7 @@ func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) { } helper := newHelper(scheme) { - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val) @@ -737,7 +737,7 @@ func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) { } helper := newHelper(scheme) { - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} + acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()} val, _ := rlp.EncodeToBytes(acc) helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) @@ -921,7 +921,7 @@ func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) @@ -961,7 +961,7 @@ func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string) stRoot := helper.makeStorageTrie("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) + helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyMerkleHash, CodeHash: types.EmptyCodeHash.Bytes()}) helper.makeStorageTrie("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) diff --git a/core/state/snapshot/utils.go b/core/state/snapshot/utils.go index c35c82f67a44d..80b694d500bbd 100644 --- a/core/state/snapshot/utils.go +++ b/core/state/snapshot/utils.go @@ -98,7 +98,7 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error { baseRoot := rawdb.ReadSnapshotRoot(db) fmt.Printf("Disklayer: Root: %x\n", baseRoot) if data := rawdb.ReadAccountSnapshot(db, hash); data != nil { - account, err := types.FullAccount(data) + account, err := types.FullAccount(data, false) if err != nil { panic(err) } @@ -128,7 +128,7 @@ func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error { } fmt.Printf("Disklayer+%d: Root: %x, parent %x\n", depth, root, pRoot) if data, ok := accounts[hash]; ok { - account, err := types.FullAccount(data) + account, err := types.FullAccount(data, false) if err != nil { panic(err) } diff --git a/core/state/state_object.go b/core/state/state_object.go index 2d542e50058c8..7b09a9278d8f3 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -93,7 +93,7 @@ func (s *stateObject) empty() bool { func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject { origin := acct if acct == nil { - acct = types.NewEmptyStateAccount() + acct = types.NewEmptyStateAccount(db.db.TrieDB().IsVerkle()) } return &stateObject{ db: db, @@ -142,7 +142,8 @@ func (s *stateObject) getTrie() (Trie, error) { func (s *stateObject) getPrefetchedTrie() Trie { // If there's nothing to meaningfully return, let the user figure it out by // pulling the trie from disk. - if (s.data.Root == types.EmptyRootHash && !s.db.db.TrieDB().IsVerkle()) || s.db.prefetcher == nil { + isVerkle := s.db.db.TrieDB().IsVerkle() + if (s.data.Root == types.EmptyRootHash(isVerkle) && !isVerkle) || s.db.prefetcher == nil { return nil } // Attempt to retrieve the trie from the prefetcher @@ -197,9 +198,17 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { s.db.StorageReads += time.Since(start) // Schedule the resolved storage slots for prefetching if it's enabled. - if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash { - if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, nil, []common.Hash{key}, true); err != nil { - log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err) + // Verkle tree is always available for prefetching, or the storage trie is + // existent in merkle. + if s.db.prefetcher != nil { + if s.db.db.TrieDB().IsVerkle() { + if err = s.db.prefetcher.prefetch(s.addrHash, common.Hash{}, s.address, nil, []common.Hash{key}, true); err != nil { + log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err) + } + } else if s.data.Root != types.EmptyMerkleHash { + if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, nil, []common.Hash{key}, true); err != nil { + log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err) + } } } s.originStorage[key] = value @@ -258,9 +267,17 @@ func (s *stateObject) finalise() { // byzantium fork) and entry is necessary to modify the value back. s.pendingStorage[key] = value } - if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash { - if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, nil, slotsToPrefetch, false); err != nil { - log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err) + // Verkle tree is always available for prefetching, or the storage trie is + // existent in merkle. + if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 { + if s.db.db.TrieDB().IsVerkle() { + if err := s.db.prefetcher.prefetch(s.addrHash, common.Hash{}, s.address, nil, slotsToPrefetch, false); err != nil { + log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err) + } + } else if s.data.Root != types.EmptyMerkleHash { + if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, nil, slotsToPrefetch, false); err != nil { + log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err) + } } } if len(s.dirtyStorage) > 0 { diff --git a/core/state/state_test.go b/core/state/state_test.go index 6f54300c37ad6..8a32d08590249 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -34,7 +34,7 @@ type stateEnv struct { } func newStateEnv() *stateEnv { - sdb, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + sdb, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) return &stateEnv{state: sdb} } @@ -42,7 +42,7 @@ func TestDump(t *testing.T) { db := rawdb.NewMemoryDatabase() triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) tdb := NewDatabase(triedb, nil) - sdb, _ := New(types.EmptyRootHash, tdb) + sdb, _ := New(types.EmptyMerkleHash, tdb) s := &stateEnv{state: sdb} // generate a few entries @@ -100,7 +100,7 @@ func TestIterativeDump(t *testing.T) { db := rawdb.NewMemoryDatabase() triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) tdb := NewDatabase(triedb, nil) - sdb, _ := New(types.EmptyRootHash, tdb) + sdb, _ := New(types.EmptyMerkleHash, tdb) s := &stateEnv{state: sdb} // generate a few entries @@ -193,7 +193,7 @@ func TestSnapshotEmpty(t *testing.T) { } func TestCreateObjectRevert(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) addr := common.BytesToAddress([]byte("so0")) snap := state.Snapshot() diff --git a/core/state/statedb.go b/core/state/statedb.go index b0603db7f0efa..b1fad7bafb70f 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1075,8 +1075,10 @@ func (s *StateDB) handleDestruction() (map[common.Hash]*accountDelete, []*trieno } deletes[addrHash] = op - // Short circuit if the origin storage was empty. - if prev.Root == types.EmptyRootHash || s.db.TrieDB().IsVerkle() { + // Short circuit if the origin storage was empty. Notably, this + // condition is always true for verkle and storage deletion is + // not supported. + if prev.Root == types.EmptyRootHash(s.db.TrieDB().IsVerkle()) { continue } // Remove storage slots belonging to the account. diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go index 7cbfd9b9d7d88..7b562c34f5ef5 100644 --- a/core/state/statedb_fuzz_test.go +++ b/core/state/statedb_fuzz_test.go @@ -202,10 +202,10 @@ func (test *stateTest) run() bool { Recovery: false, NoBuild: false, AsyncBuild: false, - }, disk, tdb, types.EmptyRootHash) + }, disk, tdb, types.EmptyMerkleHash) } for i, actions := range test.actions { - root := types.EmptyRootHash + root := types.EmptyMerkleHash if i != 0 { root = roots[len(roots)-1] } @@ -239,7 +239,7 @@ func (test *stateTest) run() bool { roots = append(roots, ret.root) } for i := 0; i < len(test.actions); i++ { - root := types.EmptyRootHash + root := types.EmptyMerkleHash if i != 0 { root = roots[i-1] } @@ -275,7 +275,7 @@ func (test *stateTest) verifyAccountCreation(next common.Hash, db *triedb.Databa if len(nBlob) == 0 { return fmt.Errorf("missing account in new trie, %x", addrHash) } - full, err := types.FullAccountRLP(account) + full, err := types.FullAccountRLP(account, false) if err != nil { return err } @@ -289,7 +289,7 @@ func (test *stateTest) verifyAccountCreation(next common.Hash, db *triedb.Databa return err } // Account has no slot, empty slot set is expected - if nAcct.Root == types.EmptyRootHash { + if nAcct.Root == types.EmptyMerkleHash { if len(storagesOrigin) != 0 { return fmt.Errorf("unexpected slot changes %x", addrHash) } @@ -319,7 +319,7 @@ func (test *stateTest) verifyAccountCreation(next common.Hash, db *triedb.Databa if len(storagesOrigin) != len(storages) { return fmt.Errorf("extra storage found, want: %d, got: %d", len(storagesOrigin), len(storages)) } - if st.Hash() != types.EmptyRootHash { + if st.Hash() != types.EmptyMerkleHash { return errors.New("invalid slot changes") } return nil @@ -346,7 +346,7 @@ func (test *stateTest) verifyAccountUpdate(next common.Hash, db *triedb.Database if len(oBlob) == 0 { return fmt.Errorf("missing account in old trie, %x", addrHash) } - full, err := types.FullAccountRLP(accountOrigin) + full, err := types.FullAccountRLP(accountOrigin, false) if err != nil { return err } @@ -358,7 +358,7 @@ func (test *stateTest) verifyAccountUpdate(next common.Hash, db *triedb.Database return errors.New("unexpected account data") } } else { - full, _ = types.FullAccountRLP(account) + full, _ = types.FullAccountRLP(account, false) if !bytes.Equal(full, nBlob) { return fmt.Errorf("unexpected account data, %x, want %v, got: %v", addrHash, full, nBlob) } @@ -373,7 +373,7 @@ func (test *stateTest) verifyAccountUpdate(next common.Hash, db *triedb.Database return err } if len(nBlob) == 0 { - nRoot = types.EmptyRootHash + nRoot = types.EmptyMerkleHash } else { if err := rlp.DecodeBytes(nBlob, &nAcct); err != nil { return err diff --git a/core/state/statedb_hooked_test.go b/core/state/statedb_hooked_test.go index 5f82ed06d0f11..6faab3e5998c0 100644 --- a/core/state/statedb_hooked_test.go +++ b/core/state/statedb_hooked_test.go @@ -38,7 +38,7 @@ func TestBurn(t *testing.T) { // 3. contract B sends ether to A var burned = new(uint256.Int) - s, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + s, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) hooked := NewHookedState(s, &tracing.Hooks{ OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) { if reason == tracing.BalanceDecreaseSelfdestructBurn { @@ -79,7 +79,7 @@ func TestBurn(t *testing.T) { // TestHooks is a basic sanity-check of all hooks func TestHooks(t *testing.T) { - inner, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + inner, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) inner.SetTxContext(common.Hash{0x11}, 100) // For the log var result []string var wants = []string{ diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 57886e6e0390e..5d0242515b49e 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -54,7 +54,7 @@ func TestUpdateLeaks(t *testing.T) { tdb = triedb.NewDatabase(db, nil) sdb = NewDatabase(tdb, nil) ) - state, _ := New(types.EmptyRootHash, sdb) + state, _ := New(types.EmptyMerkleHash, sdb) // Update it with some accounts for i := byte(0); i < 255; i++ { @@ -90,8 +90,8 @@ func TestIntermediateLeaks(t *testing.T) { finalDb := rawdb.NewMemoryDatabase() transNdb := triedb.NewDatabase(transDb, nil) finalNdb := triedb.NewDatabase(finalDb, nil) - transState, _ := New(types.EmptyRootHash, NewDatabase(transNdb, nil)) - finalState, _ := New(types.EmptyRootHash, NewDatabase(finalNdb, nil)) + transState, _ := New(types.EmptyMerkleHash, NewDatabase(transNdb, nil)) + finalState, _ := New(types.EmptyMerkleHash, NewDatabase(finalNdb, nil)) modify := func(state *StateDB, addr common.Address, i, tweak byte) { state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified) @@ -166,7 +166,7 @@ func TestIntermediateLeaks(t *testing.T) { // https://github.com/ethereum/go-ethereum/pull/15549. func TestCopy(t *testing.T) { // Create a random state test to copy and modify "independently" - orig, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + orig, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) for i := byte(0); i < 255; i++ { obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) @@ -231,7 +231,7 @@ func TestCopy(t *testing.T) { // stateDB with dirty journal present. func TestCopyWithDirtyJournal(t *testing.T) { db := NewDatabaseForTesting() - orig, _ := New(types.EmptyRootHash, db) + orig, _ := New(types.EmptyMerkleHash, db) // Fill up the initial states for i := byte(0); i < 255; i++ { @@ -277,7 +277,7 @@ func TestCopyWithDirtyJournal(t *testing.T) { // to affect S2. This test checks that the copy properly deep-copies the objectstate func TestCopyObjectState(t *testing.T) { db := NewDatabaseForTesting() - orig, _ := New(types.EmptyRootHash, db) + orig, _ := New(types.EmptyMerkleHash, db) // Fill up the initial states for i := byte(0); i < 5; i++ { @@ -404,7 +404,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction { contractHash := s.GetCodeHash(addr) emptyCode := contractHash == (common.Hash{}) || contractHash == types.EmptyCodeHash storageRoot := s.GetStorageRoot(addr) - emptyStorage := storageRoot == (common.Hash{}) || storageRoot == types.EmptyRootHash + emptyStorage := storageRoot == (common.Hash{}) || storageRoot == types.EmptyMerkleHash if s.GetNonce(addr) == 0 && emptyCode && emptyStorage { s.CreateContract(addr) // We also set some code here, to prevent the @@ -529,7 +529,7 @@ func (test *snapshotTest) String() string { func (test *snapshotTest) run() bool { // Run all actions and create snapshots. var ( - state, _ = New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ = New(types.EmptyMerkleHash, NewDatabaseForTesting()) snapshotRevs = make([]int, len(test.snapshots)) sindex = 0 checkstates = make([]*StateDB, len(test.snapshots)) @@ -718,7 +718,7 @@ func TestTouchDelete(t *testing.T) { // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 func TestCopyOfCopy(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) addr := common.HexToAddress("aaaa") state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) @@ -736,7 +736,7 @@ func TestCopyOfCopy(t *testing.T) { // See https://github.com/ethereum/go-ethereum/issues/20106. func TestCopyCommitCopy(t *testing.T) { tdb := NewDatabaseForTesting() - state, _ := New(types.EmptyRootHash, tdb) + state, _ := New(types.EmptyMerkleHash, tdb) // Create an account and check if the retrieved balance is correct addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") @@ -809,7 +809,7 @@ func TestCopyCommitCopy(t *testing.T) { // // See https://github.com/ethereum/go-ethereum/issues/20106. func TestCopyCopyCommitCopy(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) // Create an account and check if the retrieved balance is correct addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") @@ -879,7 +879,7 @@ func TestCopyCopyCommitCopy(t *testing.T) { // TestCommitCopy tests the copy from a committed state is not fully functional. func TestCommitCopy(t *testing.T) { db := NewDatabaseForTesting() - state, _ := New(types.EmptyRootHash, db) + state, _ := New(types.EmptyMerkleHash, db) // Create an account and check if the retrieved balance is correct addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") @@ -942,7 +942,7 @@ func TestCommitCopy(t *testing.T) { // first, but the journal wiped the entire state object on create-revert. func TestDeleteCreateRevert(t *testing.T) { // Create an initial state with a single contract - state, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) addr := common.BytesToAddress([]byte("so")) state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified) @@ -994,7 +994,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) { db := NewDatabase(tdb, nil) var root common.Hash - state, _ := New(types.EmptyRootHash, db) + state, _ := New(types.EmptyMerkleHash, db) addr := common.BytesToAddress([]byte("so")) { state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified) @@ -1042,7 +1042,7 @@ func TestStateDBAccessList(t *testing.T) { } db := NewDatabaseForTesting() - state, _ := New(types.EmptyRootHash, db) + state, _ := New(types.EmptyMerkleHash, db) state.accessList = newAccessList() verifyAddrs := func(astrings ...string) { @@ -1213,7 +1213,7 @@ func TestFlushOrderDataLoss(t *testing.T) { memdb = rawdb.NewMemoryDatabase() tdb = triedb.NewDatabase(memdb, triedb.HashDefaults) statedb = NewDatabase(tdb, nil) - state, _ = New(types.EmptyRootHash, statedb) + state, _ = New(types.EmptyMerkleHash, statedb) ) for a := byte(0); a < 10; a++ { state.CreateAccount(common.Address{a}) @@ -1248,7 +1248,7 @@ func TestFlushOrderDataLoss(t *testing.T) { func TestStateDBTransientStorage(t *testing.T) { db := NewDatabaseForTesting() - state, _ := New(types.EmptyRootHash, db) + state, _ := New(types.EmptyMerkleHash, db) key := common.Hash{0x01} value := common.Hash{0x02} @@ -1283,9 +1283,9 @@ func TestDeleteStorage(t *testing.T) { var ( disk = rawdb.NewMemoryDatabase() tdb = triedb.NewDatabase(disk, nil) - snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) + snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyMerkleHash) db = NewDatabase(tdb, snaps) - state, _ = New(types.EmptyRootHash, db) + state, _ = New(types.EmptyMerkleHash, db) addr = common.HexToAddress("0x1") ) // Initialize account and populate storage @@ -1339,7 +1339,7 @@ func TestStorageDirtiness(t *testing.T) { disk = rawdb.NewMemoryDatabase() tdb = triedb.NewDatabase(disk, nil) db = NewDatabase(tdb, nil) - state, _ = New(types.EmptyRootHash, db) + state, _ = New(types.EmptyMerkleHash, db) addr = common.HexToAddress("0x1") checkDirty = func(key common.Hash, value common.Hash, dirty bool) { obj := state.getStateObject(addr) diff --git a/core/state/stateupdate.go b/core/state/stateupdate.go index a320b72f11eb0..45de660ca506b 100644 --- a/core/state/stateupdate.go +++ b/core/state/stateupdate.go @@ -20,7 +20,6 @@ import ( "maps" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/triedb" ) @@ -133,8 +132,8 @@ func newStateUpdate(originRoot common.Hash, root common.Hash, deletes map[common } } return &stateUpdate{ - originRoot: types.TrieRootHash(originRoot), - root: types.TrieRootHash(root), + originRoot: originRoot, + root: root, accounts: accounts, accountsOrigin: accountsOrigin, storages: storages, diff --git a/core/state/sync_test.go b/core/state/sync_test.go index efa56f8860dd0..d5e68ec777527 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -53,7 +53,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c db := rawdb.NewMemoryDatabase() nodeDb := triedb.NewDatabase(db, config) sdb := NewDatabase(nodeDb, nil) - state, _ := New(types.EmptyRootHash, sdb) + state, _ := New(types.EmptyMerkleHash, sdb) // Fill it with some arbitrary data var accounts []*testAccount @@ -134,11 +134,11 @@ func TestEmptyStateSync(t *testing.T) { dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil) dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &triedb.Config{PathDB: pathdb.Defaults}) - sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme()) + sync := NewStateSync(types.EmptyMerkleHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme()) if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) } - sync = NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbB.Scheme()) + sync = NewStateSync(types.EmptyMerkleHash, rawdb.NewMemoryDatabase(), nil, dbB.Scheme()) if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) } diff --git a/core/state/trie_prefetcher_test.go b/core/state/trie_prefetcher_test.go index d96727704cddd..55156d76cf832 100644 --- a/core/state/trie_prefetcher_test.go +++ b/core/state/trie_prefetcher_test.go @@ -31,7 +31,7 @@ import ( ) func filledStateDB() *StateDB { - state, _ := New(types.EmptyRootHash, NewDatabaseForTesting()) + state, _ := New(types.EmptyMerkleHash, NewDatabaseForTesting()) // Create an account and check if the retrieved balance is correct addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") @@ -71,7 +71,7 @@ func TestVerklePrefetcher(t *testing.T) { db := triedb.NewDatabase(disk, triedb.VerkleDefaults) sdb := NewDatabase(db, nil) - state, err := New(types.EmptyRootHash, sdb) + state, err := New(types.EmptyVerkleHash, sdb) if err != nil { t.Fatalf("failed to initialize state: %v", err) } diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 02d339f99c2db..53d7dcfcfd6ba 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -373,7 +373,7 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.Addres // fully synced). state, err := p.chain.StateAt(head.Root) if err != nil { - state, err = p.chain.StateAt(types.EmptyRootHash) + state, err = p.chain.StateAt(types.EmptyMerkleHash) // TODO (rjl493456442) support verkle } if err != nil { return err diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index e4441bec5dad3..4a3753cc20907 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -636,7 +636,7 @@ func TestOpenDrops(t *testing.T) { store.Close() // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified) @@ -767,7 +767,7 @@ func TestOpenIndex(t *testing.T) { store.Close() // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) statedb.Commit(0, true) @@ -867,7 +867,7 @@ func TestOpenHeap(t *testing.T) { store.Close() // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) @@ -947,7 +947,7 @@ func TestOpenCap(t *testing.T) { // with a high cap to ensure everything was persisted previously for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} { // Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified) @@ -1376,7 +1376,7 @@ func TestAdd(t *testing.T) { keys = make(map[string]*ecdsa.PrivateKey) addrs = make(map[string]common.Address) ) - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) for acc, seed := range tt.seeds { // Generate a new random key/address for the seed account keys[acc], _ = crypto.GenerateKey() @@ -1482,7 +1482,7 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) { basefee = uint64(1050) blobfee = uint64(105) signer = types.LatestSigner(params.MainnetChainConfig) - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) chain = &testBlockChain{ config: params.MainnetChainConfig, basefee: uint256.NewInt(basefee), diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 70be7034eea9a..844ab203f6f94 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -302,7 +302,7 @@ func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.A // fully synced). statedb, err := pool.chain.StateAt(head.Root) if err != nil { - statedb, err = pool.chain.StateAt(types.EmptyRootHash) + statedb, err = pool.chain.StateAt(types.EmptyMerkleHash) // TODO (rjl493456442) support verkle } if err != nil { return err diff --git a/core/txpool/legacypool/legacypool2_test.go b/core/txpool/legacypool/legacypool2_test.go index 1377479da11ce..748945944096c 100644 --- a/core/txpool/legacypool/legacypool2_test.go +++ b/core/txpool/legacypool/legacypool2_test.go @@ -79,7 +79,7 @@ func TestTransactionFutureAttack(t *testing.T) { t.Parallel() // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig config.GlobalQueue = 100 @@ -116,7 +116,7 @@ func TestTransactionFutureAttack(t *testing.T) { func TestTransactionFuture1559(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) @@ -149,7 +149,7 @@ func TestTransactionFuture1559(t *testing.T) { func TestTransactionZAttack(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) @@ -217,7 +217,7 @@ func TestTransactionZAttack(t *testing.T) { func BenchmarkFutureAttack(b *testing.B) { // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig config.GlobalQueue = 100 diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 39673d176db96..49d0a0dc00aa1 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -159,7 +159,7 @@ func setupPool() (*LegacyPool, *ecdsa.PrivateKey) { } func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) key, _ := crypto.GenerateKey() @@ -250,7 +250,7 @@ func (c *testChain) State() (*state.StateDB, error) { // a state change between those fetches. stdb := c.statedb if *c.trigger { - c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + c.statedb, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) // simulate that the new head block included tx0 and tx1 c.statedb.SetNonce(c.address, 2) c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether), tracing.BalanceChangeUnspecified) @@ -268,7 +268,7 @@ func TestStateChangeDuringReset(t *testing.T) { var ( key, _ = crypto.GenerateKey() address = crypto.PubkeyToAddress(key.PublicKey) - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) trigger = false ) @@ -467,7 +467,7 @@ func TestChainFork(t *testing.T) { addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified) pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) @@ -496,7 +496,7 @@ func TestDoubleNonce(t *testing.T) { addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified) pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) @@ -696,7 +696,7 @@ func TestPostponing(t *testing.T) { t.Parallel() // Create the pool to test the postponing with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) @@ -909,7 +909,7 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) { t.Parallel() // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1002,7 +1002,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) { evictionInterval = time.Millisecond * 100 // Create the pool to test the non-expiration enforcement - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1188,7 +1188,7 @@ func TestPendingGlobalLimiting(t *testing.T) { t.Parallel() // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1290,7 +1290,7 @@ func TestCapClearsFromAll(t *testing.T) { t.Parallel() // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1325,7 +1325,7 @@ func TestPendingMinimumAllowance(t *testing.T) { t.Parallel() // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1374,7 +1374,7 @@ func TestRepricing(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) @@ -1494,7 +1494,7 @@ func TestMinGasPriceEnforced(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed)) txPoolConfig := DefaultConfig @@ -1667,7 +1667,7 @@ func TestRepricingKeepsLocals(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) @@ -1741,7 +1741,7 @@ func TestUnderpricing(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -1856,7 +1856,7 @@ func TestStableUnderpricing(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -2089,7 +2089,7 @@ func TestDeduplication(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) @@ -2156,7 +2156,7 @@ func TestReplacement(t *testing.T) { t.Parallel() // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) @@ -2362,7 +2362,7 @@ func testJournaling(t *testing.T, nolocals bool) { os.Remove(journal) // Create the original pool to inject transaction into the journal - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) config := testTxPoolConfig @@ -2463,7 +2463,7 @@ func TestStatusCheck(t *testing.T) { t.Parallel() // Create the pool to test the status retrievals with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) pool := New(testTxPoolConfig, blockchain) diff --git a/core/types/hashes.go b/core/types/hashes.go index 55506d63d0b76..4b2ee07ea84aa 100644 --- a/core/types/hashes.go +++ b/core/types/hashes.go @@ -19,13 +19,9 @@ package types import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" ) var ( - // EmptyRootHash is the known root hash of an empty merkle trie. - EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - // EmptyUncleHash is the known hash of the empty uncle set. EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 @@ -46,14 +42,15 @@ var ( // EmptyVerkleHash is the known hash of an empty verkle trie. EmptyVerkleHash = common.Hash{} + + // EmptyMerkleHash is the known root hash of an empty merkle trie. + EmptyMerkleHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") ) -// TrieRootHash returns the hash itself if it's non-empty or the predefined -// emptyHash one instead. -func TrieRootHash(hash common.Hash) common.Hash { - if hash == (common.Hash{}) { - log.Error("Zero trie root hash!") - return EmptyRootHash +// EmptyRootHash returns the empty root tree hash of the specific tree type. +func EmptyRootHash(isVerkle bool) common.Hash { + if !isVerkle { + return EmptyMerkleHash } - return hash + return EmptyVerkleHash } diff --git a/core/types/state_account.go b/core/types/state_account.go index 52ef843b3527f..37040c2a13744 100644 --- a/core/types/state_account.go +++ b/core/types/state_account.go @@ -36,10 +36,14 @@ type StateAccount struct { } // NewEmptyStateAccount constructs an empty state account. -func NewEmptyStateAccount() *StateAccount { +func NewEmptyStateAccount(isVerkle bool) *StateAccount { + emptyRoot := EmptyMerkleHash + if isVerkle { + emptyRoot = EmptyVerkleHash + } return &StateAccount{ Balance: new(uint256.Int), - Root: EmptyRootHash, + Root: emptyRoot, CodeHash: EmptyCodeHash.Bytes(), } } @@ -74,7 +78,11 @@ func SlimAccountRLP(account StateAccount) []byte { Nonce: account.Nonce, Balance: account.Balance, } - if account.Root != EmptyRootHash { + // It is highly unlikely for a valid hash (value = [32]byte{}) to appear + // in a Merkle tree, or for a valid hash (value = EmptyMerkleHash) to appear + // in a Verkle tree. Therefore, in both cases, any other value is considered + // a non-empty root hash. + if account.Root != EmptyMerkleHash && account.Root != EmptyVerkleHash { slim.Root = account.Root[:] } if !bytes.Equal(account.CodeHash, EmptyCodeHash[:]) { @@ -89,7 +97,7 @@ func SlimAccountRLP(account StateAccount) []byte { // FullAccount decodes the data on the 'slim RLP' format and returns // the consensus format account. -func FullAccount(data []byte) (*StateAccount, error) { +func FullAccount(data []byte, isVerkle bool) (*StateAccount, error) { var slim SlimAccount if err := rlp.DecodeBytes(data, &slim); err != nil { return nil, err @@ -99,7 +107,11 @@ func FullAccount(data []byte) (*StateAccount, error) { // Interpret the storage root and code hash in slim format. if len(slim.Root) == 0 { - account.Root = EmptyRootHash + if isVerkle { + account.Root = EmptyVerkleHash + } else { + account.Root = EmptyMerkleHash + } } else { account.Root = common.BytesToHash(slim.Root) } @@ -112,8 +124,8 @@ func FullAccount(data []byte) (*StateAccount, error) { } // FullAccountRLP converts data on the 'slim RLP' format into the full RLP-format. -func FullAccountRLP(data []byte) ([]byte, error) { - account, err := FullAccount(data) +func FullAccountRLP(data []byte, isVerkle bool) ([]byte, error) { + account, err := FullAccount(data, isVerkle) if err != nil { return nil, err } diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go index 45b317d3c09e1..0157e352ffcc6 100644 --- a/core/verkle_witness_test.go +++ b/core/verkle_witness_test.go @@ -237,7 +237,7 @@ func TestProcessParentBlockHash(t *testing.T) { } } t.Run("MPT", func(t *testing.T) { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) checkBlockHashes(statedb) }) t.Run("Verkle", func(t *testing.T) { diff --git a/core/vm/evm.go b/core/vm/evm.go index 07e4a272fa46f..ffa0c0363c806 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -467,7 +467,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, storageRoot := evm.StateDB.GetStorageRoot(address) if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code - (storageRoot != (common.Hash{}) && storageRoot != types.EmptyRootHash) { // non-empty storage + (storageRoot != (common.Hash{}) && storageRoot != types.EmptyMerkleHash) { // non-empty storage TODO (rjl493456442) support verkle if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index be86885261930..281f8df38eab3 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -85,7 +85,7 @@ func TestEIP2200(t *testing.T) { for i, tt := range eip2200Tests { address := common.BytesToAddress([]byte("contract")) - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) statedb.SetCode(address, hexutil.MustDecode(tt.input)) statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original})) @@ -137,7 +137,7 @@ func TestCreateGas(t *testing.T) { var gasUsed = uint64(0) doCheck := func(testGas int) bool { address := common.BytesToAddress([]byte("contract")) - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) statedb.SetCode(address, hexutil.MustDecode(tt.code)) statedb.Finalise(true) diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 08f2b2bfea1b1..bdac8b44098b1 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -569,7 +569,7 @@ func BenchmarkOpMstore(bench *testing.B) { func TestOpTstore(t *testing.T) { var ( - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) evm = NewEVM(BlockContext{}, statedb, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index cacad8f813392..7649b79e7f636 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -42,7 +42,7 @@ func TestLoopInterrupt(t *testing.T) { } for i, tt := range loopInterruptTests { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.CreateAccount(address) statedb.SetCode(address, common.Hex2Bytes(tt)) statedb.Finalise(true) diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 2243e14b65a9c..59ea834a981f5 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -116,6 +116,8 @@ func setDefaults(cfg *Config) { // // Execute sets up an in-memory, temporary, environment for the execution of // the given code. It makes sure that it's restored to its original state afterwards. +// +// TODO (rjl493456442) support verkle mode. func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { if cfg == nil { cfg = new(Config) @@ -123,7 +125,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { setDefaults(cfg) if cfg.State == nil { - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + cfg.State, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) } var ( address = common.BytesToAddress([]byte("contract")) @@ -156,6 +158,8 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { } // Create executes the code using the EVM create method +// +// TODO (rjl493456442) support verkle mode. func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { if cfg == nil { cfg = new(Config) @@ -163,7 +167,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { setDefaults(cfg) if cfg.State == nil { - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + cfg.State, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) } var ( vmenv = NewEnv(cfg) diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 0e774a01c2def..22e364bcbea18 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -106,7 +106,7 @@ func TestExecute(t *testing.T) { } func TestCall(t *testing.T) { - state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + state, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) address := common.HexToAddress("0xaa") state.SetCode(address, []byte{ byte(vm.PUSH1), 10, @@ -162,7 +162,7 @@ func BenchmarkCall(b *testing.B) { } func benchmarkEVM_Create(bench *testing.B, code string) { var ( - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) sender = common.BytesToAddress([]byte("sender")) receiver = common.BytesToAddress([]byte("receiver")) ) @@ -228,7 +228,7 @@ func BenchmarkEVM_SWAP1(b *testing.B) { return contract } - state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + state, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) contractAddr := common.BytesToAddress([]byte("contract")) b.Run("10k", func(b *testing.B) { @@ -256,7 +256,7 @@ func BenchmarkEVM_RETURN(b *testing.B) { return contract } - state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + state, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) contractAddr := common.BytesToAddress([]byte("contract")) for _, n := range []uint64{1_000, 10_000, 100_000, 1_000_000} { @@ -394,7 +394,7 @@ func TestBlockhash(t *testing.T) { func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) { cfg := new(Config) setDefaults(cfg) - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + cfg.State, _ = state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) cfg.GasLimit = gas if len(tracerCode) > 0 { tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil, cfg.ChainConfig) @@ -780,7 +780,7 @@ func TestRuntimeJSTracer(t *testing.T) { main := common.HexToAddress("0xaa") for i, jsTracer := range jsTracers { for j, tc := range tests { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) statedb.SetCode(main, tc.code) statedb.SetCode(common.HexToAddress("0xbb"), calleeCode) statedb.SetCode(common.HexToAddress("0xcc"), calleeCode) @@ -822,7 +822,7 @@ func TestJSTracerCreateTx(t *testing.T) { exit: function(res) { this.exits++ }}` code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)} - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb, _ := state.New(types.EmptyMerkleHash, state.NewDatabaseForTesting()) tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil, params.MergedTestChainConfig) if err != nil { t.Fatal(err) diff --git a/eth/api_debug.go b/eth/api_debug.go index d5e4dda1401c9..dcf7c192b3471 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -231,7 +231,7 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) { storageRoot := statedb.GetStorageRoot(address) - if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) { + if storageRoot == types.EmptyMerkleHash || storageRoot == (common.Hash{}) { return StorageRangeResult{}, nil // empty storage } id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot) diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go index cfb8829b5cc07..621acb7242d58 100644 --- a/eth/api_debug_test.go +++ b/eth/api_debug_test.go @@ -66,7 +66,7 @@ func TestAccountRange(t *testing.T) { var ( mdb = rawdb.NewMemoryDatabase() statedb = state.NewDatabase(triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}), nil) - sdb, _ = state.New(types.EmptyRootHash, statedb) + sdb, _ = state.New(types.EmptyMerkleHash, statedb) addrs = [AccountRangeMaxResults * 2]common.Address{} m = map[common.Address]bool{} ) @@ -137,11 +137,11 @@ func TestEmptyAccountRange(t *testing.T) { var ( statedb = state.NewDatabaseForTesting() - st, _ = state.New(types.EmptyRootHash, statedb) + st, _ = state.New(types.EmptyMerkleHash, statedb) ) // Commit(although nothing to flush) and re-init the statedb st.Commit(0, true) - st, _ = state.New(types.EmptyRootHash, statedb) + st, _ = state.New(types.EmptyMerkleHash, statedb) results := st.RawDump(&state.DumpConfig{ SkipCode: true, @@ -165,7 +165,7 @@ func TestStorageRangeAt(t *testing.T) { mdb = rawdb.NewMemoryDatabase() tdb = triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}) db = state.NewDatabase(tdb, nil) - sdb, _ = state.New(types.EmptyRootHash, db) + sdb, _ = state.New(types.EmptyMerkleHash, db) addr = common.Address{0x01} keys = []common.Hash{ // hashes of Keys of storage common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"), diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index b3886270f3dd1..a7f9e1a3aec1d 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -262,7 +262,7 @@ func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) [ // Retrieve the requested block's receipts results := chain.GetReceiptsByHash(hash) if results == nil { - if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { + if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyMerkleHash { continue } } diff --git a/eth/protocols/snap/protocol.go b/eth/protocols/snap/protocol.go index 0db206b0810ec..ce465638eb28b 100644 --- a/eth/protocols/snap/protocol.go +++ b/eth/protocols/snap/protocol.go @@ -104,7 +104,7 @@ func (p *AccountRangePacket) Unpack() ([]common.Hash, [][]byte, error) { accounts = make([][]byte, len(p.Accounts)) ) for i, acc := range p.Accounts { - val, err := types.FullAccountRLP(acc.Body) + val, err := types.FullAccountRLP(acc.Body, false) // TODO support verkle snap sync if err != nil { return nil, nil, fmt.Errorf("invalid account %x: %v", acc.Body, err) } diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 9e079f540f07d..5dc74da55c6e7 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -1907,7 +1907,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { } } // Check if the account is a contract with an unknown storage trie - if account.Root != types.EmptyRootHash { + if account.Root != types.EmptyMerkleHash { // If the storage was already retrieved in the last cycle, there's no need // to resync it again, regardless of whether the storage root is consistent // or not. @@ -2422,7 +2422,7 @@ func (s *Syncer) forwardAccountTask(task *accountTask) { if !task.needHeal[i] { // If the storage task is complete, drop it into the stack trie // to generate account trie nodes for it - full, err := types.FullAccountRLP(slim) // TODO(karalabe): Slim parsing can be omitted + full, err := types.FullAccountRLP(slim, false) // TODO(karalabe): Slim parsing can be omitted if err != nil { panic(err) // Really shouldn't ever happen } diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go index d318077d99a88..26df7ad28de9c 100644 --- a/eth/protocols/snap/sync_test.go +++ b/eth/protocols/snap/sync_test.go @@ -1502,7 +1502,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: i, Balance: uint256.NewInt(i), - Root: types.EmptyRootHash, + Root: types.EmptyMerkleHash, CodeHash: getCodeHash(i), }) key := key32(i) @@ -1515,7 +1515,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) // Commit the state changes into db and re-create the trie // for accessing later. root, nodes := accTrie.Commit(false) - db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet()) + db.Update(root, types.EmptyMerkleHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet()) accTrie, _ = trie.New(trie.StateTrieID(root), db) return db.Scheme(), accTrie, entries @@ -1553,7 +1553,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) { value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: uint64(0), Balance: uint256.NewInt(uint64(i)), - Root: types.EmptyRootHash, + Root: types.EmptyMerkleHash, CodeHash: getCodeHash(uint64(i)), }) elem := &kv{boundaries[i].Bytes(), value} @@ -1565,7 +1565,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) { value, _ := rlp.EncodeToBytes(&types.StateAccount{ Nonce: i, Balance: uint256.NewInt(i), - Root: types.EmptyRootHash, + Root: types.EmptyMerkleHash, CodeHash: getCodeHash(i), }) elem := &kv{key32(i), value} @@ -1577,7 +1577,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) { // Commit the state changes into db and re-create the trie // for accessing later. root, nodes := accTrie.Commit(false) - db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet()) + db.Update(root, types.EmptyMerkleHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet()) accTrie, _ = trie.New(trie.StateTrieID(root), db) return db.Scheme(), accTrie, entries @@ -1626,7 +1626,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots nodes.Merge(set) // Commit gathered dirty nodes into database - db.Update(root, types.EmptyRootHash, 0, nodes, triedb.NewStateSet()) + db.Update(root, types.EmptyMerkleHash, 0, nodes, triedb.NewStateSet()) // Re-create tries with new root accTrie, _ = trie.New(trie.StateTrieID(root), db) @@ -1693,7 +1693,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda nodes.Merge(set) // Commit gathered dirty nodes into database - db.Update(root, types.EmptyRootHash, 0, nodes, triedb.NewStateSet()) + db.Update(root, types.EmptyMerkleHash, 0, nodes, triedb.NewStateSet()) // Re-create tries with new root accTrie, err := trie.New(trie.StateTrieID(root), db) @@ -1716,7 +1716,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda // not-yet-committed trie and the sorted entries. The seeds can be used to ensure // that tries are unique. func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) { - trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) + trie, _ := trie.New(trie.StorageTrieID(types.EmptyMerkleHash, owner, types.EmptyMerkleHash), db) var entries []*kv for i := uint64(1); i <= n; i++ { // store 'x' at slot 'x' @@ -1742,7 +1742,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (com var ( entries []*kv boundaries []common.Hash - trie, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) + trie, _ = trie.New(trie.StorageTrieID(types.EmptyMerkleHash, owner, types.EmptyMerkleHash), db) ) // Initialize boundaries var next common.Hash @@ -1791,7 +1791,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (com func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) { var ( entries []*kv - tr, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) + tr, _ = trie.New(trie.StorageTrieID(types.EmptyMerkleHash, owner, types.EmptyMerkleHash), db) chosen = make(map[byte]struct{}) ) for i := 0; i < 3; i++ { @@ -1838,7 +1838,7 @@ func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *test log.Crit("Invalid account encountered during snapshot creation", "err", err) } accounts++ - if acc.Root != types.EmptyRootHash { + if acc.Root != types.EmptyMerkleHash { id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root) storeTrie, err := trie.NewStateTrie(id, triedb) if err != nil { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 067d07ba7a8dc..e310508eeb5b2 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -363,6 +363,8 @@ func (n *proofList) Delete(key []byte) error { } // GetProof returns the Merkle-proof for a given account and optionally some storage keys. +// +// TODO (rjl493456442) This function needs to be rewritten for verkle compatibility. func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { var ( keys = make([]common.Hash, len(storageKeys)) @@ -386,7 +388,7 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address, if len(keys) > 0 { var storageTrie state.Trie - if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) { + if storageRoot != types.EmptyMerkleHash && storageRoot != (common.Hash{}) { id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot) st, err := trie.NewStateTrie(id, statedb.Database().TrieDB()) if err != nil { diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 1f5f2dd1d5108..233b2e185eefc 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -197,7 +197,7 @@ func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txDa AccessList: types.AccessList{ types.AccessTuple{ Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, + StorageKeys: []common.Hash{types.EmptyMerkleHash}, }, }, V: big.NewInt(32), @@ -243,7 +243,7 @@ func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txDa AccessList: types.AccessList{ types.AccessTuple{ Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, + StorageKeys: []common.Hash{types.EmptyMerkleHash}, }, }, V: big.NewInt(32), @@ -290,7 +290,7 @@ func allTransactionTypes(addr common.Address, config *params.ChainConfig) []txDa AccessList: types.AccessList{ types.AccessTuple{ Address: common.Address{0x2}, - StorageKeys: []common.Hash{types.EmptyRootHash}, + StorageKeys: []common.Hash{types.EmptyMerkleHash}, }, }, V: big.NewInt(32), @@ -3294,7 +3294,7 @@ func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil func TestStateOverrideMovePrecompile(t *testing.T) { db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil) - statedb, err := state.New(common.Hash{}, db) + statedb, err := state.New(types.EmptyMerkleHash, db) if err != nil { t.Fatalf("failed to create statedb: %v", err) } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 6884ae7ed5a8b..bfa3b80aba787 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -465,7 +465,9 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo } triedb := triedb.NewDatabase(db, tconf) sdb := state.NewDatabase(triedb, nil) - statedb, _ := state.New(types.EmptyRootHash, sdb) + + // TODO (rjl493456442) support verkle state tests + statedb, _ := state.New(types.EmptyMerkleHash, sdb) for addr, a := range accounts { statedb.SetCode(addr, a.Code) statedb.SetNonce(addr, a.Nonce) diff --git a/trie/database_test.go b/trie/database_test.go index 729d9f699be1f..3d19c201c9bdd 100644 --- a/trie/database_test.go +++ b/trie/database_test.go @@ -66,7 +66,7 @@ type testDb struct { func newTestDatabase(diskdb ethdb.Database, scheme string) *testDb { return &testDb{ disk: diskdb, - root: types.EmptyRootHash, + root: types.EmptyMerkleHash, scheme: scheme, nodes: make(map[common.Hash]*trienode.MergedNodeSet), parents: make(map[common.Hash]common.Hash), diff --git a/trie/iterator.go b/trie/iterator.go index fa016110636ab..ef44c8cd1ea77 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -162,7 +162,7 @@ func (e seekError) Error() string { } func newNodeIterator(trie *Trie, start []byte) NodeIterator { - if trie.Hash() == types.EmptyRootHash { + if trie.Hash() == types.EmptyMerkleHash { return &nodeIterator{ trie: trie, err: errIteratorEnd, @@ -323,7 +323,7 @@ func (it *nodeIterator) seek(prefix []byte) error { func (it *nodeIterator) init() (*nodeIteratorState, error) { root := it.trie.Hash() state := &nodeIteratorState{node: it.trie.root, index: -1} - if root != types.EmptyRootHash { + if root != types.EmptyMerkleHash { state.hash = root } return state, state.resolve(it, nil) diff --git a/trie/iterator_test.go b/trie/iterator_test.go index 74a1aa378c65a..10731c69b7d87 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -60,7 +60,7 @@ func TestIterator(t *testing.T) { trie.MustUpdate([]byte(val.k), []byte(val.v)) } root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) trie, _ = New(TrieID(root), db) found := make(map[string]string) @@ -258,7 +258,7 @@ func TestDifferenceIterator(t *testing.T) { triea.MustUpdate([]byte(val.k), []byte(val.v)) } rootA, nodesA := triea.Commit(false) - dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)) + dba.Update(rootA, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesA)) triea, _ = New(TrieID(rootA), dba) dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) @@ -267,7 +267,7 @@ func TestDifferenceIterator(t *testing.T) { trieb.MustUpdate([]byte(val.k), []byte(val.v)) } rootB, nodesB := trieb.Commit(false) - dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB)) + dbb.Update(rootB, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesB)) trieb, _ = New(TrieID(rootB), dbb) found := make(map[string]string) @@ -300,7 +300,7 @@ func TestUnionIterator(t *testing.T) { triea.MustUpdate([]byte(val.k), []byte(val.v)) } rootA, nodesA := triea.Commit(false) - dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)) + dba.Update(rootA, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesA)) triea, _ = New(TrieID(rootA), dba) dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) @@ -309,7 +309,7 @@ func TestUnionIterator(t *testing.T) { trieb.MustUpdate([]byte(val.k), []byte(val.v)) } rootB, nodesB := trieb.Commit(false) - dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB)) + dbb.Update(rootB, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesB)) trieb, _ = New(TrieID(rootB), dbb) di, _ := NewUnionIterator([]NodeIterator{triea.MustNodeIterator(nil), trieb.MustNodeIterator(nil)}) @@ -372,7 +372,7 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) { tr.MustUpdate([]byte(val.k), []byte(val.v)) } root, nodes := tr.Commit(false) - tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + tdb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) if !memonly { tdb.Commit(root) } @@ -488,7 +488,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin break } } - triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + triedb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) if !memonly { triedb.Commit(root) } @@ -562,7 +562,7 @@ func testIteratorNodeBlob(t *testing.T, scheme string) { trie.MustUpdate([]byte(val.k), []byte(val.v)) } root, nodes := trie.Commit(false) - triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + triedb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) triedb.Commit(root) var found = make(map[common.Hash][]byte) diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go index 59958d33f4cf2..fc5cca3323d41 100644 --- a/trie/secure_trie_test.go +++ b/trie/secure_trie_test.go @@ -31,7 +31,7 @@ import ( ) func newEmptySecure() *StateTrie { - trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) + trie, _ := NewStateTrie(TrieID(types.EmptyMerkleHash), newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) return trie } @@ -39,7 +39,7 @@ func newEmptySecure() *StateTrie { func makeTestStateTrie() (*testDb, *StateTrie, map[string][]byte) { // Create an empty trie triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme) - trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb) + trie, _ := NewStateTrie(TrieID(types.EmptyMerkleHash), triedb) // Fill it with some arbitrary data content := make(map[string][]byte) @@ -61,7 +61,7 @@ func makeTestStateTrie() (*testDb, *StateTrie, map[string][]byte) { } } root, nodes := trie.Commit(false) - if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil { + if err := triedb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)); err != nil { panic(fmt.Errorf("failed to commit db %v", err)) } // Re-create the trie based on the new state diff --git a/trie/stacktrie.go b/trie/stacktrie.go index d194cbf0aec4e..7dbe663959b8c 100644 --- a/trie/stacktrie.go +++ b/trie/stacktrie.go @@ -312,7 +312,7 @@ func (t *StackTrie) hash(st *stNode, path []byte) { return case emptyNode: - st.val = types.EmptyRootHash.Bytes() + st.val = types.EmptyMerkleHash.Bytes() st.key = st.key[:0] st.typ = hashedNode return diff --git a/trie/stacktrie_fuzzer_test.go b/trie/stacktrie_fuzzer_test.go index df487d16bf460..6c2e0510c2d7b 100644 --- a/trie/stacktrie_fuzzer_test.go +++ b/trie/stacktrie_fuzzer_test.go @@ -81,7 +81,7 @@ func fuzz(data []byte, debugging bool) { // Flush trie -> database rootA, nodes := trieA.Commit(false) if nodes != nil { - dbA.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + dbA.Update(rootA, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) } // Flush memdb -> disk (sponge) dbA.Commit(rootA) diff --git a/trie/sync.go b/trie/sync.go index 3b7caae5b1032..8b60cec61e36c 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -286,7 +286,7 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb // parent for completion tracking. The given path is a unique node path in // hex format and contain all the parent path if it's layered trie node. func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, parentPath []byte, callback LeafCallback) { - if root == types.EmptyRootHash { + if root == types.EmptyMerkleHash { return } owner, inner := ResolvePath(path) diff --git a/trie/sync_test.go b/trie/sync_test.go index 2ff02576d4dd7..131ce947e8ffc 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -37,7 +37,7 @@ func makeTestTrie(scheme string) (ethdb.Database, *testDb, *StateTrie, map[strin // Create an empty trie db := rawdb.NewMemoryDatabase() triedb := newTestDatabase(db, scheme) - trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb) + trie, _ := NewStateTrie(TrieID(types.EmptyMerkleHash), triedb) // Fill it with some arbitrary data content := make(map[string][]byte) @@ -59,7 +59,7 @@ func makeTestTrie(scheme string) (ethdb.Database, *testDb, *StateTrie, map[strin } } root, nodes := trie.Commit(false) - if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil { + if err := triedb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)); err != nil { panic(fmt.Errorf("failed to commit db %v", err)) } if err := triedb.Commit(root); err != nil { @@ -139,9 +139,9 @@ func TestEmptySync(t *testing.T) { dbD := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme) emptyA := NewEmpty(dbA) - emptyB, _ := New(TrieID(types.EmptyRootHash), dbB) + emptyB, _ := New(TrieID(types.EmptyMerkleHash), dbB) emptyC := NewEmpty(dbC) - emptyD, _ := New(TrieID(types.EmptyRootHash), dbD) + emptyD, _ := New(TrieID(types.EmptyMerkleHash), dbD) for i, trie := range []*Trie{emptyA, emptyB, emptyC, emptyD} { sync := NewSync(trie.Hash(), memorydb.New(), nil, []*testDb{dbA, dbB, dbC, dbD}[i].Scheme()) @@ -821,7 +821,7 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) { var ( srcDisk = rawdb.NewMemoryDatabase() srcTrieDB = newTestDatabase(srcDisk, scheme) - srcTrie, _ = New(TrieID(types.EmptyRootHash), srcTrieDB) + srcTrie, _ = New(TrieID(types.EmptyMerkleHash), srcTrieDB) deleteFn = func(key []byte, tr *Trie, states map[string][]byte) { tr.Delete(key) @@ -848,7 +848,7 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) { writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA) rootA, nodesA := srcTrie.Commit(false) - if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil { + if err := srcTrieDB.Update(rootA, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesA)); err != nil { panic(err) } if err := srcTrieDB.Commit(rootA); err != nil { @@ -922,7 +922,7 @@ func testSyncAbort(t *testing.T, scheme string) { var ( srcDisk = rawdb.NewMemoryDatabase() srcTrieDB = newTestDatabase(srcDisk, scheme) - srcTrie, _ = New(TrieID(types.EmptyRootHash), srcTrieDB) + srcTrie, _ = New(TrieID(types.EmptyMerkleHash), srcTrieDB) deleteFn = func(key []byte, tr *Trie, states map[string][]byte) { tr.Delete(key) @@ -947,7 +947,7 @@ func testSyncAbort(t *testing.T, scheme string) { writeFn(key, val, srcTrie, stateA) rootA, nodesA := srcTrie.Commit(false) - if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil { + if err := srcTrieDB.Update(rootA, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodesA)); err != nil { panic(err) } if err := srcTrieDB.Commit(rootA); err != nil { diff --git a/trie/tracer_test.go b/trie/tracer_test.go index 852a706021b08..eb5b937b79474 100644 --- a/trie/tracer_test.go +++ b/trie/tracer_test.go @@ -71,7 +71,7 @@ func testTrieTracer(t *testing.T, vals []struct{ k, v string }) { insertSet := copySet(trie.tracer.inserts) // copy before commit deleteSet := copySet(trie.tracer.deletes) // copy before commit root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) seen := setKeys(iterNodes(db, root)) if !compareSet(insertSet, seen) { @@ -138,7 +138,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) { trie.MustUpdate([]byte(val.k), []byte(val.v)) } root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) trie, _ = New(TrieID(root), db) if err := verifyAccessList(orig, trie, nodes); err != nil { @@ -220,7 +220,7 @@ func TestAccessListLeak(t *testing.T) { trie.MustUpdate([]byte(val.k), []byte(val.v)) } root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) var cases = []struct { op func(tr *Trie) @@ -270,7 +270,7 @@ func TestTinyTree(t *testing.T) { trie.MustUpdate([]byte(val.k), randBytes(32)) } root, set := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(set)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(set)) parent := root trie, _ = New(TrieID(root), db) diff --git a/trie/trie.go b/trie/trie.go index ae2a7b21a236b..f3b21366b4970 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -84,7 +84,7 @@ func (t *Trie) Copy() *Trie { // empty, otherwise, the root node must be present in database or returns // a MissingNodeError if not. func New(id *ID, db database.NodeDatabase) (*Trie, error) { - reader, err := newTrieReader(id.StateRoot, id.Owner, db) + reader, err := newTrieReader(false, id.StateRoot, id.Owner, db) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func New(id *ID, db database.NodeDatabase) (*Trie, error) { reader: reader, tracer: newTracer(), } - if id.Root != (common.Hash{}) && id.Root != types.EmptyRootHash { + if id.Root != types.EmptyMerkleHash { rootnode, err := trie.resolveAndTrack(id.Root[:], nil) if err != nil { return nil, err @@ -105,7 +105,7 @@ func New(id *ID, db database.NodeDatabase) (*Trie, error) { // NewEmpty is a shortcut to create empty tree. It's mostly used in tests. func NewEmpty(db database.NodeDatabase) *Trie { - tr, _ := New(TrieID(types.EmptyRootHash), db) + tr, _ := New(TrieID(types.EmptyMerkleHash), db) return tr } @@ -621,13 +621,13 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { if t.root == nil { paths := t.tracer.deletedNodes() if len(paths) == 0 { - return types.EmptyRootHash, nil // case (a) + return types.EmptyMerkleHash, nil // case (a) } nodes := trienode.NewNodeSet(t.owner) for _, path := range paths { nodes.AddNode([]byte(path), trienode.NewDeleted()) } - return types.EmptyRootHash, nodes // case (b) + return types.EmptyMerkleHash, nodes // case (b) } // Derive the hash for all dirty nodes first. We hold the assumption // in the following procedure that all nodes are hashed. @@ -654,7 +654,7 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { // hashRoot calculates the root hash of the given trie func (t *Trie) hashRoot() (node, node) { if t.root == nil { - return hashNode(types.EmptyRootHash.Bytes()), nil + return hashNode(types.EmptyMerkleHash.Bytes()), nil } // If the number of changes is below 100, we let one thread handle it h := newHasher(t.unhashed >= 100) diff --git a/trie/trie_reader.go b/trie/trie_reader.go index 4b8ba808df012..5775dff2a1c04 100644 --- a/trie/trie_reader.go +++ b/trie/trie_reader.go @@ -19,7 +19,6 @@ package trie import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/triedb/database" ) @@ -32,11 +31,11 @@ type trieReader struct { } // newTrieReader initializes the trie reader with the given node reader. -func newTrieReader(stateRoot, owner common.Hash, db database.NodeDatabase) (*trieReader, error) { - if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash { - if stateRoot == (common.Hash{}) { - log.Error("Zero state root hash!") - } +func newTrieReader(isVerkle bool, stateRoot, owner common.Hash, db database.NodeDatabase) (*trieReader, error) { + if isVerkle && stateRoot == types.EmptyVerkleHash { + return &trieReader{owner: owner}, nil + } + if !isVerkle && stateRoot == types.EmptyMerkleHash { return &trieReader{owner: owner}, nil } reader, err := db.NodeReader(stateRoot) diff --git a/trie/trie_test.go b/trie/trie_test.go index 423ed30fe88f0..ede95a00c0323 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -51,7 +51,7 @@ func init() { func TestEmptyTrie(t *testing.T) { trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)) res := trie.Hash() - exp := types.EmptyRootHash + exp := types.EmptyMerkleHash if res != exp { t.Errorf("expected %x got %x", exp, res) } @@ -98,7 +98,7 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) { updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer") updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf") root, nodes := trie.Commit(false) - triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + triedb.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) if !memonly { triedb.Commit(root) @@ -212,7 +212,7 @@ func TestGet(t *testing.T) { return } root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) trie, _ = New(TrieID(root), db) } } @@ -285,7 +285,7 @@ func TestReplication(t *testing.T) { updateString(trie, val.k, val.v) } root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) // create a new trie on top of the database and check that lookups work. trie2, err := New(TrieID(root), db) @@ -304,7 +304,7 @@ func TestReplication(t *testing.T) { // recreate the trie after commit if nodes != nil { - db.Update(hash, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(hash, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) } trie2, err = New(TrieID(hash), db) if err != nil { @@ -493,7 +493,7 @@ func runRandTest(rt randTest) error { scheme = rawdb.PathScheme } var ( - origin = types.EmptyRootHash + origin = types.EmptyMerkleHash triedb = newTestDatabase(rawdb.NewMemoryDatabase(), scheme) tr = NewEmpty(triedb) values = make(map[string]string) // tracks content of the trie @@ -518,7 +518,7 @@ func runRandTest(rt randTest) error { } case opProve: hash := tr.Hash() - if hash == types.EmptyRootHash { + if hash == types.EmptyMerkleHash { continue } proofDb := rawdb.NewMemoryDatabase() @@ -790,7 +790,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { for i := 0; i < len(accounts); i++ { var ( nonce = uint64(random.Int63()) - root = types.EmptyRootHash + root = types.EmptyMerkleHash code = crypto.Keccak256(nil) ) // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, @@ -897,7 +897,7 @@ func TestCommitSequence(t *testing.T) { } // Flush trie -> database root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) // Flush memdb -> disk (sponge) db.Commit(root) if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { @@ -938,7 +938,7 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { } // Flush trie -> database root, nodes := trie.Commit(false) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) // Flush memdb -> disk (sponge) db.Commit(root) if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { @@ -988,7 +988,7 @@ func TestCommitSequenceStackTrie(t *testing.T) { // Flush trie -> database root, nodes := trie.Commit(false) // Flush memdb -> disk (sponge) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) db.Commit(root) s.Flush() @@ -1046,7 +1046,7 @@ func TestCommitSequenceSmallRoot(t *testing.T) { // Flush trie -> database root, nodes := trie.Commit(false) // Flush memdb -> disk (sponge) - db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) + db.Update(root, types.EmptyMerkleHash, trienode.NewWithNodeSet(nodes)) db.Commit(root) // And flush stacktrie -> disk diff --git a/trie/verkle.go b/trie/verkle.go index 2e4d62cd10412..f347d622aca8c 100644 --- a/trie/verkle.go +++ b/trie/verkle.go @@ -46,13 +46,13 @@ type VerkleTrie struct { // NewVerkleTrie constructs a verkle tree based on the specified root hash. func NewVerkleTrie(root common.Hash, db database.NodeDatabase, cache *utils.PointCache) (*VerkleTrie, error) { - reader, err := newTrieReader(root, common.Hash{}, db) + reader, err := newTrieReader(true, root, common.Hash{}, db) if err != nil { return nil, err } // Parse the root verkle node if it's not empty. node := verkle.New() - if root != types.EmptyVerkleHash && root != types.EmptyRootHash { + if root != types.EmptyVerkleHash { blob, err := reader.node(nil, common.Hash{}) if err != nil { return nil, err diff --git a/triedb/database.go b/triedb/database.go index b448d7cd07b04..136c273310a1d 100644 --- a/triedb/database.go +++ b/triedb/database.go @@ -146,7 +146,7 @@ func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, n } switch b := db.backend.(type) { case *hashdb.Database: - return b.Update(root, parent, block, nodes) + return b.Update(parent, nodes) case *pathdb.Database: return b.Update(root, parent, block, nodes, states.internal()) } diff --git a/triedb/hashdb/database.go b/triedb/hashdb/database.go index fb718f4e7426b..2ab6d49653bd9 100644 --- a/triedb/hashdb/database.go +++ b/triedb/hashdb/database.go @@ -77,6 +77,8 @@ var Defaults = &Config{ // Database is an intermediate write layer between the trie data structures and // the disk database. The aim is to accumulate trie writes in-memory and only // periodically flush a couple tries to disk, garbage collecting the remainder. +// +// This database is not compatible with verkle tree node. type Database struct { diskdb ethdb.Database // Persistent storage for matured trie nodes cleans *fastcache.Cache // GC friendly memory cache of clean node RLPs @@ -540,9 +542,9 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool { // Update inserts the dirty nodes in provided nodeset into database and link the // account trie with multiple storage tries if necessary. -func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet) error { +func (db *Database) Update(parent common.Hash, nodes *trienode.MergedNodeSet) error { // Ensure the parent state is present and signal a warning if not. - if parent != types.EmptyRootHash { + if parent != types.EmptyMerkleHash { if blob, _ := db.node(parent); len(blob) == 0 { log.Error("parent state is not present") } @@ -583,7 +585,7 @@ func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, n if err := rlp.DecodeBytes(n.Blob, &account); err != nil { return err } - if account.Root != types.EmptyRootHash { + if account.Root != types.EmptyMerkleHash { db.reference(account.Root, n.Parent) } } diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index cfbdb01c497ae..c9204e8a8c96a 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie/trienode" + "github.com/ethereum/go-verkle" ) const ( @@ -148,6 +149,29 @@ var Defaults = &Config{ // ReadOnly is the config in order to open database in read only mode. var ReadOnly = &Config{ReadOnly: true} +// nodeHasher is the function to compute the hash of supplied node blob. +type nodeHasher func([]byte) (common.Hash, error) + +// merkleNodeHasher computes the hash of the given merkle node. +func merkleNodeHasher(blob []byte) (common.Hash, error) { + if len(blob) == 0 { + return types.EmptyMerkleHash, nil + } + return crypto.Keccak256Hash(blob), nil +} + +// verkleNodeHasher computes the hash of the given verkle node. +func verkleNodeHasher(blob []byte) (common.Hash, error) { + if len(blob) == 0 { + return types.EmptyVerkleHash, nil + } + n, err := verkle.ParseNode(blob, 0) + if err != nil { + return common.Hash{}, err + } + return n.Commit().Bytes(), nil +} + // Database is a multiple-layered structure for maintaining in-memory states // along with its dirty trie nodes. It consists of one persistent base layer // backed by a key-value store, on top of which arbitrarily many in-memory diff @@ -164,9 +188,10 @@ type Database struct { // readOnly is the flag whether the mutation is allowed to be applied. // It will be set automatically when the database is journaled during // the shutdown to reject all following unexpected mutations. - readOnly bool // Flag if database is opened in read only mode - waitSync bool // Flag if database is deactivated due to initial state sync - isVerkle bool // Flag if database is used for verkle tree + readOnly bool // Flag if database is opened in read only mode + waitSync bool // Flag if database is deactivated due to initial state sync + isVerkle bool // Flag if database is used for verkle tree + hasher nodeHasher // Trie node hasher config *Config // Configuration for database diskdb ethdb.Database // Persistent storage for matured trie nodes @@ -184,19 +209,21 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database { } config = config.sanitize() + db := &Database{ + readOnly: config.ReadOnly, + isVerkle: isVerkle, + config: config, + diskdb: diskdb, + hasher: merkleNodeHasher, + } // Establish a dedicated database namespace tailored for verkle-specific // data, ensuring the isolation of both verkle and merkle tree data. It's // important to note that the introduction of a prefix won't lead to // substantial storage overhead, as the underlying database will efficiently // compress the shared key prefix. if isVerkle { - diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix)) - } - db := &Database{ - readOnly: config.ReadOnly, - isVerkle: isVerkle, - config: config, - diskdb: diskdb, + db.diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix)) + db.hasher = verkleNodeHasher } // Construct the layer tree by resolving the in-disk singleton state // and in-memory layer journal. @@ -300,6 +327,8 @@ func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint6 // Commit traverses downwards the layer tree from a specified layer with the // provided state root and all the layers below are flattened downwards. It // can be used alone and mostly for test purposes. +// +// The supplied root must be a valid trie hash value. func (db *Database) Commit(root common.Hash, report bool) error { // Hold the lock to prevent concurrent mutations. db.lock.Lock() @@ -341,6 +370,8 @@ func (db *Database) Disable() error { // Enable activates database and resets the state tree with the provided persistent // state root once the state sync is finished. +// +// The supplied root must be a valid trie hash value. func (db *Database) Enable(root common.Hash) error { db.lock.Lock() defer db.lock.Unlock() @@ -350,10 +381,9 @@ func (db *Database) Enable(root common.Hash) error { return errDatabaseReadOnly } // Ensure the provided state root matches the stored one. - root = types.TrieRootHash(root) - stored := types.EmptyRootHash - if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { - stored = crypto.Keccak256Hash(blob) + stored, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil)) + if err != nil { + return err } if stored != root { return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) @@ -389,6 +419,8 @@ func (db *Database) Enable(root common.Hash) error { // Recover rollbacks the database to a specified historical point. // The state is supported as the rollback destination only if it's // canonical state and the corresponding trie histories are existent. +// +// The supplied root must be a valid trie hash value. func (db *Database) Recover(root common.Hash) error { db.lock.Lock() defer db.lock.Unlock() @@ -401,7 +433,6 @@ func (db *Database) Recover(root common.Hash) error { return errors.New("state rollback is non-supported") } // Short circuit if the target state is not recoverable - root = types.TrieRootHash(root) if !db.Recoverable(root) { return errStateUnrecoverable } @@ -434,9 +465,10 @@ func (db *Database) Recover(root common.Hash) error { } // Recoverable returns the indicator if the specified state is recoverable. +// +// The supplied root must be a valid trie hash value. func (db *Database) Recoverable(root common.Hash) bool { // Ensure the requested state is a known state. - root = types.TrieRootHash(root) id := rawdb.ReadStateID(db.diskdb, root) if id == nil { return false @@ -504,7 +536,7 @@ func (db *Database) Size() (diffs common.StorageSize, nodes common.StorageSize) func (db *Database) Initialized(genesisRoot common.Hash) bool { var inited bool db.tree.forEach(func(layer layer) { - if layer.rootHash() != types.EmptyRootHash { + if layer.rootHash() != types.EmptyRootHash(db.isVerkle) { inited = true } }) diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go index 648230df1560b..6cd130c95c252 100644 --- a/triedb/pathdb/database_test.go +++ b/triedb/pathdb/database_test.go @@ -91,6 +91,7 @@ func newCtx(stateRoot common.Hash) *genctx { } } +// TODO(rjl493456442) support verkle for testing type tester struct { db *Database roots []common.Hash @@ -121,7 +122,7 @@ func newTester(t *testing.T, historyLimit uint64) *tester { } ) for i := 0; i < 12; i++ { - var parent = types.EmptyRootHash + var parent = types.EmptyMerkleHash if len(obj.roots) != 0 { parent = obj.roots[len(obj.roots)-1] } @@ -159,7 +160,7 @@ func (t *tester) generateStorage(ctx *genctx, addr common.Address) common.Hash { storage[hash] = v origin[hash] = nil } - root, set := updateTrie(t.db, ctx.stateRoot, addrHash, types.EmptyRootHash, storage) + root, set := updateTrie(t.db, ctx.stateRoot, addrHash, types.EmptyMerkleHash, storage) ctx.storages[addrHash] = storage ctx.storageOrigin[addr] = origin @@ -207,7 +208,7 @@ func (t *tester) clearStorage(ctx *genctx, addr common.Address, root common.Hash storage[hash] = nil } root, set := updateTrie(t.db, ctx.stateRoot, addrHash, root, storage) - if root != types.EmptyRootHash { + if root != types.EmptyMerkleHash { panic("failed to clear storage trie") } ctx.storages[addrHash] = storage @@ -252,7 +253,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode } dirties[addrHash] = struct{}{} - acct, _ := types.FullAccount(account) + acct, _ := types.FullAccount(account, false) stRoot := t.mutateStorage(ctx, addr, acct.Root) newAccount := types.SlimAccountRLP(generateAccount(stRoot)) @@ -271,8 +272,8 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode } dirties[addrHash] = struct{}{} - acct, _ := types.FullAccount(account) - if acct.Root != types.EmptyRootHash { + acct, _ := types.FullAccount(account, false) + if acct.Root != types.EmptyMerkleHash { t.clearStorage(ctx, addr, acct.Root) } ctx.accounts[addrHash] = nil @@ -371,7 +372,7 @@ func (t *tester) verifyHistory() error { if err != nil { return err } - parent := types.EmptyRootHash + parent := types.EmptyMerkleHash if i != 0 { parent = t.roots[i-1] } @@ -412,7 +413,7 @@ func TestDatabaseRollback(t *testing.T) { } // Revert database from top to bottom for i := tester.bottomIndex(); i >= 0; i-- { - parent := types.EmptyRootHash + parent := types.EmptyMerkleHash if i > 0 { parent = tester.roots[i-1] } @@ -451,10 +452,10 @@ func TestDatabaseRecoverable(t *testing.T) { {common.Hash{0x1}, false}, // Initial state should be recoverable - {types.EmptyRootHash, true}, + {types.EmptyMerkleHash, true}, - // Initial state should be recoverable - {common.Hash{}, true}, + // Invalid (unknown) state should be rejected + {common.Hash{}, false}, // Layers below current disk layer are recoverable {tester.roots[index-1], true}, @@ -489,7 +490,7 @@ func TestDisable(t *testing.T) { if err := tester.db.Disable(); err != nil { t.Fatalf("Failed to deactivate database: %v", err) } - if err := tester.db.Enable(types.EmptyRootHash); err == nil { + if err := tester.db.Enable(types.EmptyMerkleHash); err == nil { t.Fatal("Invalid activation should be rejected") } if err := tester.db.Enable(stored); err != nil { diff --git a/triedb/pathdb/execute.go b/triedb/pathdb/execute.go index e24d0710f3da3..a59fbf0b484ea 100644 --- a/triedb/pathdb/execute.go +++ b/triedb/pathdb/execute.go @@ -87,7 +87,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) defer h.release() addrHash := h.hash(addr.Bytes()) - prev, err := types.FullAccount(ctx.accounts[addr]) + prev, err := types.FullAccount(ctx.accounts[addr], false) // TODO support verkle mode if err != nil { return err } @@ -97,7 +97,7 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address) if err != nil { return err } - post := types.NewEmptyStateAccount() + post := types.NewEmptyStateAccount(false) // TODO support verkle mode if len(blob) != 0 { if err := rlp.DecodeBytes(blob, &post); err != nil { return err @@ -171,7 +171,7 @@ func deleteAccount(ctx *context, db database.NodeDatabase, addr common.Address) } } root, result := st.Commit(false) - if root != types.EmptyRootHash { + if root != types.EmptyMerkleHash { // TODO (rjl493456442) support verkle return errors.New("failed to clear storage trie") } // The returned set can be nil if storage trie is not changed diff --git a/triedb/pathdb/history_test.go b/triedb/pathdb/history_test.go index d430706dee8ae..d9439ee0725cd 100644 --- a/triedb/pathdb/history_test.go +++ b/triedb/pathdb/history_test.go @@ -43,7 +43,7 @@ func randomStateSet(n int) (map[common.Address][]byte, map[common.Address]map[co v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32))) storages[addr][testrand.Hash()] = v } - account := generateAccount(types.EmptyRootHash) + account := generateAccount(types.EmptyMerkleHash) accounts[addr] = types.SlimAccountRLP(account) } return accounts, storages @@ -51,12 +51,12 @@ func randomStateSet(n int) (map[common.Address][]byte, map[common.Address]map[co func makeHistory() *history { accounts, storages := randomStateSet(3) - return newHistory(testrand.Hash(), types.EmptyRootHash, 0, accounts, storages) + return newHistory(testrand.Hash(), types.EmptyMerkleHash, 0, accounts, storages) } func makeHistories(n int) []*history { var ( - parent = types.EmptyRootHash + parent = types.EmptyMerkleHash result []*history ) for i := 0; i < n; i++ { diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 779a262fdd053..7f7eb5a123ef8 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -26,7 +26,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -93,9 +92,9 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) { // loadLayers loads a pre-existing state layer backed by a key-value store. func (db *Database) loadLayers() layer { // Retrieve the root node of persistent state. - var root = types.EmptyRootHash - if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { - root = crypto.Keccak256Hash(blob) + root, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil)) + if err != nil { + log.Crit("Failed to compute node hash", "err", err) } // Load the layers by resolving the journal head, err := db.loadJournal(root) @@ -105,7 +104,7 @@ func (db *Database) loadLayers() layer { // journal is not matched(or missing) with the persistent state, discard // it. Display log for discarding journal, but try to avoid showing // useless information when the db is created from scratch. - if !(root == types.EmptyRootHash && errors.Is(err, errMissJournal)) { + if !(root == types.EmptyRootHash(db.isVerkle) && errors.Is(err, errMissJournal)) { log.Info("Failed to load journal, discard it", "err", err) } // Return single layer with persistent state. @@ -265,9 +264,9 @@ func (db *Database) Journal(root common.Hash) error { } // Secondly write out the state root in disk, ensure all layers // on top are continuous with disk. - diskRoot := types.EmptyRootHash - if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { - diskRoot = crypto.Keccak256Hash(blob) + diskRoot, err := db.hasher(rawdb.ReadAccountTrieNode(db.diskdb, nil)) + if err != nil { + return err } if err := rlp.Encode(journal, diskRoot); err != nil { return err diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go index cf6b14e744ef6..51e4b46c905c4 100644 --- a/triedb/pathdb/layertree.go +++ b/triedb/pathdb/layertree.go @@ -22,7 +22,6 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/trie/trienode" ) @@ -58,11 +57,13 @@ func (tree *layerTree) reset(head layer) { } // get retrieves a layer belonging to the given state root. +// +// The supplied root must be a valid trie hash value. func (tree *layerTree) get(root common.Hash) layer { tree.lock.RLock() defer tree.lock.RUnlock() - return tree.layers[types.TrieRootHash(root)] + return tree.layers[root] } // forEach iterates the stored layers inside and applies the @@ -85,6 +86,8 @@ func (tree *layerTree) len() int { } // add inserts a new layer into the tree if it can be linked to an existing old parent. +// +// The supplied root and parentRoot must be a valid trie hash value. func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *StateSetWithOrigin) error { // Reject noop updates to avoid self-loops. This is a special case that can // happen for clique networks and proof-of-stake networks where empty blocks @@ -92,7 +95,6 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6 // // Although we could silently ignore this internally, it should be the caller's // responsibility to avoid even attempting to insert such a layer. - root, parentRoot = types.TrieRootHash(root), types.TrieRootHash(parentRoot) if root == parentRoot { return errors.New("layer cycle") } @@ -112,7 +114,6 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6 // are crossed. All diffs beyond the permitted number are flattened downwards. func (tree *layerTree) cap(root common.Hash, layers int) error { // Retrieve the head layer to cap from - root = types.TrieRootHash(root) l := tree.get(root) if l == nil { return fmt.Errorf("triedb layer [%#x] missing", root)