trie: use unified emptyRootHash and emptyCodeHash (#26718)

This commit is contained in:
Daniel Liu 2025-03-25 21:43:02 +08:00 committed by Daniel Liu
parent c8b39cabae
commit 5328a637c0
8 changed files with 24 additions and 29 deletions

View file

@ -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)

View file

@ -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))
}

View file

@ -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
}

View file

@ -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

View file

@ -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) {

View file

@ -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 {

View file

@ -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)

View file

@ -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})