forked from cerc-io/plugeth
all: port boring changes from pbss (#27176)
* all: port boring changes from pbss * core, trie: address comments from martin * trie: minor fixes * core/rawdb: update comment * core, eth, tests, trie: address comments * tests, trie: add extra check when update trie database * trie/triedb/hashdb: degrade the error to warning
This commit is contained in:
+2
-2
@@ -982,8 +982,8 @@ func (bc *BlockChain) Stop() {
|
||||
}
|
||||
}
|
||||
// Flush the collected preimages to disk
|
||||
if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil {
|
||||
log.Error("Failed to commit trie preimages", "err", err)
|
||||
if err := bc.stateCache.TrieDB().Close(); err != nil {
|
||||
log.Error("Failed to close trie db", "err", err)
|
||||
}
|
||||
// Ensure all live cached entries be saved into disk, so that we can skip
|
||||
// cache warmup when node restarts.
|
||||
|
||||
@@ -1701,7 +1701,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
|
||||
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
|
||||
}
|
||||
if len(chain.stateCache.TrieDB().Nodes()) > 0 {
|
||||
if nodes, _ := chain.TrieDB().Size(); nodes > 0 {
|
||||
t.Fatalf("stale tries still alive after garbase collection")
|
||||
}
|
||||
}
|
||||
|
||||
+47
-1
@@ -22,6 +22,7 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
)
|
||||
|
||||
@@ -100,7 +101,7 @@ var (
|
||||
CodePrefix = []byte("c") // CodePrefix + code hash -> account code
|
||||
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
|
||||
|
||||
// Path-based trie node scheme.
|
||||
// Path-based storage scheme of merkle patricia trie.
|
||||
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
|
||||
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node
|
||||
|
||||
@@ -248,3 +249,48 @@ func accountTrieNodeKey(path []byte) []byte {
|
||||
func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte {
|
||||
return append(append(trieNodeStoragePrefix, accountHash.Bytes()...), path...)
|
||||
}
|
||||
|
||||
// IsLegacyTrieNode reports whether a provided database entry is a legacy trie
|
||||
// node. The characteristics of legacy trie node are:
|
||||
// - the key length is 32 bytes
|
||||
// - the key is the hash of val
|
||||
func IsLegacyTrieNode(key []byte, val []byte) bool {
|
||||
if len(key) != common.HashLength {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(key, crypto.Keccak256(val))
|
||||
}
|
||||
|
||||
// IsAccountTrieNode reports whether a provided database entry is an account
|
||||
// trie node in path-based state scheme.
|
||||
func IsAccountTrieNode(key []byte) (bool, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeAccountPrefix) {
|
||||
return false, nil
|
||||
}
|
||||
// The remaining key should only consist a hex node path
|
||||
// whose length is in the range 0 to 64 (64 is excluded
|
||||
// since leaves are always wrapped with shortNode).
|
||||
if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 {
|
||||
return false, nil
|
||||
}
|
||||
return true, key[len(trieNodeAccountPrefix):]
|
||||
}
|
||||
|
||||
// IsStorageTrieNode reports whether a provided database entry is a storage
|
||||
// trie node in path-based state scheme.
|
||||
func IsStorageTrieNode(key []byte) (bool, common.Hash, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeStoragePrefix) {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
// The remaining key consists of 2 parts:
|
||||
// - 32 bytes account hash
|
||||
// - hex node path whose length is in the range 0 to 64
|
||||
if len(key) < len(trieNodeStoragePrefix)+common.HashLength {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength])
|
||||
return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:]
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -109,7 +110,7 @@ type Trie interface {
|
||||
// The returned nodeset can be nil if the trie is clean(nothing to commit).
|
||||
// Once the trie is committed, it's not usable anymore. A new trie must
|
||||
// be created with new root and updated trie database for following usage
|
||||
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet)
|
||||
Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet)
|
||||
|
||||
// NodeIterator returns an iterator that returns nodes of the trie. Iteration
|
||||
// starts at the key after the given start key.
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
// Tests that the node iterator indeed walks over the entire database contents.
|
||||
@@ -85,9 +86,18 @@ func TestNodeIteratorCoverage(t *testing.T) {
|
||||
// database entry belongs to a trie node or not.
|
||||
func isTrieNode(scheme string, key, val []byte) (bool, common.Hash) {
|
||||
if scheme == rawdb.HashScheme {
|
||||
if len(key) == common.HashLength {
|
||||
if rawdb.IsLegacyTrieNode(key, val) {
|
||||
return true, common.BytesToHash(key)
|
||||
}
|
||||
} else {
|
||||
ok, _ := rawdb.IsAccountTrieNode(key)
|
||||
if ok {
|
||||
return true, crypto.Keccak256Hash(val)
|
||||
}
|
||||
ok, _, _ = rawdb.IsStorageTrieNode(key)
|
||||
if ok {
|
||||
return true, crypto.Keccak256Hash(val)
|
||||
}
|
||||
}
|
||||
return false, common.Hash{}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -363,7 +364,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
|
||||
}
|
||||
root, nodes := snapTrie.Commit(false)
|
||||
if nodes != nil {
|
||||
tdb.Update(trie.NewWithNodeSet(nodes))
|
||||
tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
|
||||
tdb.Commit(root, false)
|
||||
}
|
||||
resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte {
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
@@ -144,7 +145,7 @@ type testHelper struct {
|
||||
diskdb ethdb.Database
|
||||
triedb *trie.Database
|
||||
accTrie *trie.StateTrie
|
||||
nodes *trie.MergedNodeSet
|
||||
nodes *trienode.MergedNodeSet
|
||||
}
|
||||
|
||||
func newHelper() *testHelper {
|
||||
@@ -155,7 +156,7 @@ func newHelper() *testHelper {
|
||||
diskdb: diskdb,
|
||||
triedb: triedb,
|
||||
accTrie: accTrie,
|
||||
nodes: trie.NewMergedNodeSet(),
|
||||
nodes: trienode.NewMergedNodeSet(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ func (t *testHelper) Commit() common.Hash {
|
||||
if nodes != nil {
|
||||
t.nodes.Merge(nodes)
|
||||
}
|
||||
t.triedb.Update(t.nodes)
|
||||
t.triedb.Update(root, types.EmptyRootHash, t.nodes)
|
||||
t.triedb.Commit(root, false)
|
||||
return root
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
type Code []byte
|
||||
@@ -350,7 +350,7 @@ func (s *stateObject) updateRoot(db Database) {
|
||||
|
||||
// commitTrie submits the storage changes into the storage trie and re-computes
|
||||
// the root. Besides, all trie changes will be collected in a nodeset and returned.
|
||||
func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) {
|
||||
func (s *stateObject) commitTrie(db Database) (*trienode.NodeSet, error) {
|
||||
tr, err := s.updateTrie(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
||||
type revision struct {
|
||||
@@ -971,7 +972,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
accountTrieNodesDeleted int
|
||||
storageTrieNodesUpdated int
|
||||
storageTrieNodesDeleted int
|
||||
nodes = trie.NewMergedNodeSet()
|
||||
nodes = trienode.NewMergedNodeSet()
|
||||
codeWriter = s.db.DiskDB().NewBatch()
|
||||
)
|
||||
for addr := range s.stateObjectsDirty {
|
||||
@@ -986,7 +987,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Merge the dirty nodes of storage trie into global set
|
||||
// Merge the dirty nodes of storage trie into global set.
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
@@ -1071,7 +1072,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
}
|
||||
if root != origin {
|
||||
start := time.Now()
|
||||
if err := s.db.TrieDB().Update(nodes); err != nil {
|
||||
if err := s.db.TrieDB().Update(root, origin, nodes); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
s.originalRoot = root
|
||||
|
||||
@@ -602,7 +602,8 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||
if len(nodeQueue) > 0 {
|
||||
results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
|
||||
for path, element := range nodeQueue {
|
||||
data, err := srcDb.TrieDB().Node(element.hash)
|
||||
owner, inner := trie.ResolvePath([]byte(element.path))
|
||||
data, err := srcDb.TrieDB().Reader(srcRoot).Node(owner, inner, element.hash)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to retrieve node data for %x", element.hash)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user