From 5328a637c02489ef910df5cfb13f3274d911a82d Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Tue, 25 Mar 2025 21:43:02 +0800 Subject: [PATCH] trie: use unified emptyRootHash and emptyCodeHash (#26718) --- trie/iterator.go | 5 +++-- trie/iterator_test.go | 5 +++-- trie/proof.go | 3 ++- trie/stacktrie.go | 3 ++- trie/sync.go | 5 +++-- trie/sync_test.go | 7 ++++--- trie/trie.go | 20 ++++---------------- trie/trie_test.go | 5 +++-- 8 files changed, 24 insertions(+), 29 deletions(-) diff --git a/trie/iterator.go b/trie/iterator.go index 7c57dacc11..032e668c30 100644 --- a/trie/iterator.go +++ b/trie/iterator.go @@ -22,6 +22,7 @@ import ( "errors" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" ) // Iterator is a key-value trie iterator that traverses a Trie. @@ -134,7 +135,7 @@ func (e seekError) Error() string { } func newNodeIterator(trie *Trie, start []byte) NodeIterator { - if trie.Hash() == emptyState { + if trie.Hash() == types.EmptyCodeHash { return new(nodeIterator) } it := &nodeIterator{trie: trie} @@ -259,7 +260,7 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er // Initialize the iterator if we've just started. root := it.trie.Hash() state := &nodeIteratorState{node: it.trie.root, index: -1} - if root != emptyRoot { + if root != types.EmptyRootHash { state.hash = root } err := state.resolve(it.trie, nil) diff --git a/trie/iterator_test.go b/trie/iterator_test.go index 37e6473be9..8a8401c222 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -23,6 +23,7 @@ import ( "testing" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb" ) @@ -295,7 +296,7 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool) { diskdb := memorydb.New() triedb := NewDatabase(diskdb) - tr, _ := New(emptyRoot, triedb) + tr, _ := New(types.EmptyRootHash, triedb) for _, val := range testdata1 { tr.Update([]byte(val.k), []byte(val.v)) } @@ -386,7 +387,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool) { diskdb := memorydb.New() triedb := NewDatabase(diskdb) - ctr, _ := New(emptyRoot, triedb) + ctr, _ := New(types.EmptyRootHash, triedb) for _, val := range testdata1 { ctr.Update([]byte(val.k), []byte(val.v)) } diff --git a/trie/proof.go b/trie/proof.go index 1760f6572c..dbf3ddad47 100644 --- a/trie/proof.go +++ b/trie/proof.go @@ -22,6 +22,7 @@ import ( "fmt" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb" "github.com/XinFinOrg/XDPoSChain/log" @@ -418,7 +419,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, valu // Special case, there is no edge proof at all. The given range is expected // to be the whole leaf-set in the trie. if firstProof == nil && lastProof == nil { - emptytrie, err := New(emptyRoot, NewDatabase(memorydb.New())) + emptytrie, err := New(types.EmptyRootHash, NewDatabase(memorydb.New())) if err != nil { return err, false } diff --git a/trie/stacktrie.go b/trie/stacktrie.go index 22af10b5ab..c6ff3f84b7 100644 --- a/trie/stacktrie.go +++ b/trie/stacktrie.go @@ -26,6 +26,7 @@ import ( "sync" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/log" ) @@ -383,7 +384,7 @@ func (st *StackTrie) hashRec(hasher *hasher) { return case emptyNode: - st.val = emptyRoot.Bytes() + st.val = types.EmptyRootHash.Bytes() st.key = st.key[:0] st.nodeType = hashedNode return diff --git a/trie/sync.go b/trie/sync.go index 1771777349..f34cf4d68e 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -23,6 +23,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/core/rawdb" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb" ) @@ -109,7 +110,7 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb // AddSubTrie registers a new trie to the sync code, rooted at the designated parent. func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callback LeafCallback) { // Short circuit if the trie is empty or already known - if root == emptyRoot { + if root == types.EmptyRootHash { return } if s.membatch.hasNode(root) { @@ -149,7 +150,7 @@ func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callb // as is. func (s *Sync) AddCodeEntry(hash common.Hash, depth int, parent common.Hash) { // Short circuit if the entry is empty or already known - if hash == emptyState { + if hash == types.EmptyCodeHash { return } if s.membatch.hasCode(hash) { diff --git a/trie/sync_test.go b/trie/sync_test.go index 21aca3fb1b..f0c6d65e9e 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb" ) @@ -28,7 +29,7 @@ import ( func makeTestTrie() (*Database, *Trie, map[string][]byte) { // Create an empty trie triedb := NewDatabase(memorydb.New()) - trie, _ := New(emptyRoot, triedb) + trie, _ := New(types.EmptyRootHash, triedb) // Fill it with some arbitrary data content := make(map[string][]byte) @@ -90,8 +91,8 @@ func checkTrieConsistency(db *Database, root common.Hash) error { func TestEmptySync(t *testing.T) { dbA := NewDatabase(memorydb.New()) dbB := NewDatabase(memorydb.New()) - emptyA, _ := New(emptyRoot, dbA) - emptyB, _ := New(emptyRoot, dbB) + emptyA, _ := New(types.EmptyRootHash, dbA) + emptyB, _ := New(types.EmptyRootHash, dbB) for i, trie := range []*Trie{emptyA, emptyB} { if req := NewSync(trie.Hash(), memorydb.New(), nil, NewSyncBloom(1, memorydb.New())).Missing(1); len(req) != 0 { diff --git a/trie/trie.go b/trie/trie.go index 000e1ec368..0e49b4a7a8 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -23,22 +23,10 @@ import ( "sync" "github.com/XinFinOrg/XDPoSChain/common" - "github.com/XinFinOrg/XDPoSChain/crypto" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/log" ) -var ( - // TODO(daniel): - // 1. remove file core/types/derive_sha.go, Ref: #21502 - // 2. then replace emptyRoot, emptyState with types.EmptyRootHash, types.EmptyCodeHash, Ref: #26718 - - // emptyRoot is the known root hash of an empty trie. - emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // emptyState is the known hash of an empty state trie entry. - emptyState = crypto.Keccak256Hash(nil) -) - // LeafCallback is a callback type invoked when a trie operation reaches a leaf // Node. It's used by state sync and commit to allow handling external references // between account and storage tries. @@ -76,7 +64,7 @@ func New(root common.Hash, db *Database) (*Trie, error) { trie := &Trie{ Db: db, } - if root != (common.Hash{}) && root != emptyRoot { + if root != (common.Hash{}) && root != types.EmptyRootHash { rootnode, err := trie.resolveHash(root[:], nil) if err != nil { return nil, err @@ -591,7 +579,7 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) { panic("commit called on trie with nil database") } if t.root == nil { - return emptyRoot, nil + return types.EmptyRootHash, nil } // Derive the hash for all dirty nodes first. We hold the assumption // in the following procedure that all nodes are hashed. @@ -635,7 +623,7 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) { // hashRoot calculates the root hash of the given trie func (t *Trie) hashRoot() (node, node, error) { if t.root == nil { - return hashNode(emptyRoot.Bytes()), nil, nil + return hashNode(types.EmptyRootHash.Bytes()), nil, 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_test.go b/trie/trie_test.go index 8dda9d5b8d..27977b0d38 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -29,6 +29,7 @@ import ( "testing/quick" "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/ethdb" "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb" @@ -51,7 +52,7 @@ func newEmpty() *Trie { func TestEmptyTrie(t *testing.T) { var trie Trie res := trie.Hash() - exp := emptyRoot + exp := types.EmptyRootHash if res != exp { t.Errorf("expected %x got %x", exp, res) } @@ -503,7 +504,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { var ( nonce = uint64(random.Int63()) balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) - root = emptyRoot + root = types.EmptyRootHash code = crypto.Keccak256(nil) ) accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code})