mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-16 01:40:44 +00:00
trie: use unified emptyRootHash and emptyCodeHash (#26718)
This commit is contained in:
parent
c8b39cabae
commit
5328a637c0
8 changed files with 24 additions and 29 deletions
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Iterator is a key-value trie iterator that traverses a Trie.
|
// 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 {
|
func newNodeIterator(trie *Trie, start []byte) NodeIterator {
|
||||||
if trie.Hash() == emptyState {
|
if trie.Hash() == types.EmptyCodeHash {
|
||||||
return new(nodeIterator)
|
return new(nodeIterator)
|
||||||
}
|
}
|
||||||
it := &nodeIterator{trie: trie}
|
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.
|
// Initialize the iterator if we've just started.
|
||||||
root := it.trie.Hash()
|
root := it.trie.Hash()
|
||||||
state := &nodeIteratorState{node: it.trie.root, index: -1}
|
state := &nodeIteratorState{node: it.trie.root, index: -1}
|
||||||
if root != emptyRoot {
|
if root != types.EmptyRootHash {
|
||||||
state.hash = root
|
state.hash = root
|
||||||
}
|
}
|
||||||
err := state.resolve(it.trie, nil)
|
err := state.resolve(it.trie, nil)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -295,7 +296,7 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool) {
|
||||||
diskdb := memorydb.New()
|
diskdb := memorydb.New()
|
||||||
triedb := NewDatabase(diskdb)
|
triedb := NewDatabase(diskdb)
|
||||||
|
|
||||||
tr, _ := New(emptyRoot, triedb)
|
tr, _ := New(types.EmptyRootHash, triedb)
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
tr.Update([]byte(val.k), []byte(val.v))
|
tr.Update([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
|
|
@ -386,7 +387,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool) {
|
||||||
diskdb := memorydb.New()
|
diskdb := memorydb.New()
|
||||||
triedb := NewDatabase(diskdb)
|
triedb := NewDatabase(diskdb)
|
||||||
|
|
||||||
ctr, _ := New(emptyRoot, triedb)
|
ctr, _ := New(types.EmptyRootHash, triedb)
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
ctr.Update([]byte(val.k), []byte(val.v))
|
ctr.Update([]byte(val.k), []byte(val.v))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"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
|
// Special case, there is no edge proof at all. The given range is expected
|
||||||
// to be the whole leaf-set in the trie.
|
// to be the whole leaf-set in the trie.
|
||||||
if firstProof == nil && lastProof == nil {
|
if firstProof == nil && lastProof == nil {
|
||||||
emptytrie, err := New(emptyRoot, NewDatabase(memorydb.New()))
|
emptytrie, err := New(types.EmptyRootHash, NewDatabase(memorydb.New()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, false
|
return err, false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
)
|
)
|
||||||
|
|
@ -383,7 +384,7 @@ func (st *StackTrie) hashRec(hasher *hasher) {
|
||||||
return
|
return
|
||||||
|
|
||||||
case emptyNode:
|
case emptyNode:
|
||||||
st.val = emptyRoot.Bytes()
|
st.val = types.EmptyRootHash.Bytes()
|
||||||
st.key = st.key[:0]
|
st.key = st.key[:0]
|
||||||
st.nodeType = hashedNode
|
st.nodeType = hashedNode
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"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.
|
// 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) {
|
func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callback LeafCallback) {
|
||||||
// Short circuit if the trie is empty or already known
|
// Short circuit if the trie is empty or already known
|
||||||
if root == emptyRoot {
|
if root == types.EmptyRootHash {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.membatch.hasNode(root) {
|
if s.membatch.hasNode(root) {
|
||||||
|
|
@ -149,7 +150,7 @@ func (s *Sync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callb
|
||||||
// as is.
|
// as is.
|
||||||
func (s *Sync) AddCodeEntry(hash common.Hash, depth int, parent common.Hash) {
|
func (s *Sync) AddCodeEntry(hash common.Hash, depth int, parent common.Hash) {
|
||||||
// Short circuit if the entry is empty or already known
|
// Short circuit if the entry is empty or already known
|
||||||
if hash == emptyState {
|
if hash == types.EmptyCodeHash {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.membatch.hasCode(hash) {
|
if s.membatch.hasCode(hash) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ import (
|
||||||
func makeTestTrie() (*Database, *Trie, map[string][]byte) {
|
func makeTestTrie() (*Database, *Trie, map[string][]byte) {
|
||||||
// Create an empty trie
|
// Create an empty trie
|
||||||
triedb := NewDatabase(memorydb.New())
|
triedb := NewDatabase(memorydb.New())
|
||||||
trie, _ := New(emptyRoot, triedb)
|
trie, _ := New(types.EmptyRootHash, triedb)
|
||||||
|
|
||||||
// Fill it with some arbitrary data
|
// Fill it with some arbitrary data
|
||||||
content := make(map[string][]byte)
|
content := make(map[string][]byte)
|
||||||
|
|
@ -90,8 +91,8 @@ func checkTrieConsistency(db *Database, root common.Hash) error {
|
||||||
func TestEmptySync(t *testing.T) {
|
func TestEmptySync(t *testing.T) {
|
||||||
dbA := NewDatabase(memorydb.New())
|
dbA := NewDatabase(memorydb.New())
|
||||||
dbB := NewDatabase(memorydb.New())
|
dbB := NewDatabase(memorydb.New())
|
||||||
emptyA, _ := New(emptyRoot, dbA)
|
emptyA, _ := New(types.EmptyRootHash, dbA)
|
||||||
emptyB, _ := New(emptyRoot, dbB)
|
emptyB, _ := New(types.EmptyRootHash, dbB)
|
||||||
|
|
||||||
for i, trie := range []*Trie{emptyA, emptyB} {
|
for i, trie := range []*Trie{emptyA, emptyB} {
|
||||||
if req := NewSync(trie.Hash(), memorydb.New(), nil, NewSyncBloom(1, memorydb.New())).Missing(1); len(req) != 0 {
|
if req := NewSync(trie.Hash(), memorydb.New(), nil, NewSyncBloom(1, memorydb.New())).Missing(1); len(req) != 0 {
|
||||||
|
|
|
||||||
20
trie/trie.go
20
trie/trie.go
|
|
@ -23,22 +23,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"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
|
// 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
|
// Node. It's used by state sync and commit to allow handling external references
|
||||||
// between account and storage tries.
|
// between account and storage tries.
|
||||||
|
|
@ -76,7 +64,7 @@ func New(root common.Hash, db *Database) (*Trie, error) {
|
||||||
trie := &Trie{
|
trie := &Trie{
|
||||||
Db: db,
|
Db: db,
|
||||||
}
|
}
|
||||||
if root != (common.Hash{}) && root != emptyRoot {
|
if root != (common.Hash{}) && root != types.EmptyRootHash {
|
||||||
rootnode, err := trie.resolveHash(root[:], nil)
|
rootnode, err := trie.resolveHash(root[:], nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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")
|
panic("commit called on trie with nil database")
|
||||||
}
|
}
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
return emptyRoot, nil
|
return types.EmptyRootHash, nil
|
||||||
}
|
}
|
||||||
// Derive the hash for all dirty nodes first. We hold the assumption
|
// Derive the hash for all dirty nodes first. We hold the assumption
|
||||||
// in the following procedure that all nodes are hashed.
|
// 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
|
// hashRoot calculates the root hash of the given trie
|
||||||
func (t *Trie) hashRoot() (node, node, error) {
|
func (t *Trie) hashRoot() (node, node, error) {
|
||||||
if t.root == nil {
|
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
|
// If the number of changes is below 100, we let one thread handle it
|
||||||
h := newHasher(t.unhashed >= 100)
|
h := newHasher(t.unhashed >= 100)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
|
||||||
|
|
@ -51,7 +52,7 @@ func newEmpty() *Trie {
|
||||||
func TestEmptyTrie(t *testing.T) {
|
func TestEmptyTrie(t *testing.T) {
|
||||||
var trie Trie
|
var trie Trie
|
||||||
res := trie.Hash()
|
res := trie.Hash()
|
||||||
exp := emptyRoot
|
exp := types.EmptyRootHash
|
||||||
if res != exp {
|
if res != exp {
|
||||||
t.Errorf("expected %x got %x", exp, res)
|
t.Errorf("expected %x got %x", exp, res)
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +504,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
|
||||||
var (
|
var (
|
||||||
nonce = uint64(random.Int63())
|
nonce = uint64(random.Int63())
|
||||||
balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
|
balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
|
||||||
root = emptyRoot
|
root = types.EmptyRootHash
|
||||||
code = crypto.Keccak256(nil)
|
code = crypto.Keccak256(nil)
|
||||||
)
|
)
|
||||||
accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code})
|
accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue