Skip to content

Commit

Permalink
core, trie, triedb: minor changes from snapshot integration (#30599)
Browse files Browse the repository at this point in the history
This change ports some non-important changes from #30159, including interface renaming and some trivial refactorings.
  • Loading branch information
rjl493456442 authored and holiman committed Nov 19, 2024
1 parent 56d14b2 commit 6412bee
Show file tree
Hide file tree
Showing 40 changed files with 991 additions and 787 deletions.
2 changes: 1 addition & 1 deletion cmd/geth/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Failed to open iterator", "root", root, "err", err)
return err
}
reader, err := triedb.Reader(root)
reader, err := triedb.NodeReader(root)
if err != nil {
log.Error("State is non-existent", "root", root)
return nil
Expand Down
6 changes: 3 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config {
}
if c.StateScheme == rawdb.PathScheme {
config.PathDB = &pathdb.Config{
StateHistory: c.StateHistory,
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
StateHistory: c.StateHistory,
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024,
}
}
return config
Expand Down
17 changes: 5 additions & 12 deletions core/state/snapshot/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ 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"
"github.com/ethereum/go-ethereum/triedb"
)

Expand Down Expand Up @@ -353,20 +352,14 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
// main account trie as a primary lookup when resolving hashes
var resolver trie.NodeResolver
if len(result.keys) > 0 {
mdb := rawdb.NewMemoryDatabase()
tdb := triedb.NewDatabase(mdb, triedb.HashDefaults)
defer tdb.Close()
snapTrie := trie.NewEmpty(tdb)
tr := trie.NewEmpty(nil)
for i, key := range result.keys {
snapTrie.Update(key, result.vals[i])
}
root, nodes := snapTrie.Commit(false)
if nodes != nil {
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
tdb.Commit(root, false)
tr.Update(key, result.vals[i])
}
_, nodes := tr.Commit(false)
hashSet := nodes.HashSet()
resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte {
return rawdb.ReadTrieNode(mdb, owner, path, hash, tdb.Scheme())
return hashSet[hash]
}
}
// Construct the trie for state iteration, reuse the trie
Expand Down
94 changes: 55 additions & 39 deletions core/state/snapshot/generate_test.go

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/holiman/uint256"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -1282,8 +1281,7 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool) (*stateU
// If trie database is enabled, commit the state update as a new layer
if db := s.db.TrieDB(); db != nil {
start := time.Now()
set := triestate.New(ret.accountsOrigin, ret.storagesOrigin)
if err := db.Update(ret.root, ret.originRoot, block, ret.nodes, set); err != nil {
if err := db.Update(ret.root, ret.originRoot, block, ret.nodes, ret.stateSet()); err != nil {
return nil, err
}
s.TrieDBCommits += time.Since(start)
Expand Down
4 changes: 2 additions & 2 deletions core/state/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,8 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
)
if scheme == rawdb.PathScheme {
tdb = triedb.NewDatabase(memDb, &triedb.Config{PathDB: &pathdb.Config{
CleanCacheSize: 0,
DirtyCacheSize: 0,
CleanCacheSize: 0,
WriteBufferSize: 0,
}}) // disable caching
} else {
tdb = triedb.NewDatabase(memDb, &triedb.Config{HashDB: &hashdb.Config{
Expand Down
15 changes: 15 additions & 0 deletions core/state/stateupdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"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"
)

// contractCode represents a contract code with associated metadata.
Expand Down Expand Up @@ -131,3 +132,17 @@ func newStateUpdate(originRoot common.Hash, root common.Hash, deletes map[common
nodes: nodes,
}
}

// stateSet converts the current stateUpdate object into a triedb.StateSet
// object. This function extracts the necessary data from the stateUpdate
// struct and formats it into the StateSet structure consumed by the triedb
// package.
func (sc *stateUpdate) stateSet() *triedb.StateSet {
return &triedb.StateSet{
Destructs: sc.destructs,
Accounts: sc.accounts,
AccountsOrigin: sc.accountsOrigin,
Storages: sc.storages,
StoragesOrigin: sc.storagesOrigin,
}
}
10 changes: 5 additions & 5 deletions core/state/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s
for i := 0; i < len(codes); i++ {
codeElements = append(codeElements, stateElement{code: codes[i]})
}
reader, err := ndb.Reader(srcRoot)
reader, err := ndb.NodeReader(srcRoot)
if err != nil {
t.Fatalf("state is not existent, %#x", srcRoot)
}
Expand Down Expand Up @@ -326,7 +326,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) {
for i := 0; i < len(codes); i++ {
codeElements = append(codeElements, stateElement{code: codes[i]})
}
reader, err := ndb.Reader(srcRoot)
reader, err := ndb.NodeReader(srcRoot)
if err != nil {
t.Fatalf("state is not existent, %#x", srcRoot)
}
Expand Down Expand Up @@ -430,7 +430,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
for _, hash := range codes {
codeQueue[hash] = struct{}{}
}
reader, err := ndb.Reader(srcRoot)
reader, err := ndb.NodeReader(srcRoot)
if err != nil {
t.Fatalf("state is not existent, %#x", srcRoot)
}
Expand Down Expand Up @@ -523,7 +523,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
for _, hash := range codes {
codeQueue[hash] = struct{}{}
}
reader, err := ndb.Reader(srcRoot)
reader, err := ndb.NodeReader(srcRoot)
if err != nil {
t.Fatalf("state is not existent, %#x", srcRoot)
}
Expand Down Expand Up @@ -628,7 +628,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
addedPaths []string
addedHashes []common.Hash
)
reader, err := ndb.Reader(srcRoot)
reader, err := ndb.NodeReader(srcRoot)
if err != nil {
t.Fatalf("state is not available %x", srcRoot)
}
Expand Down
5 changes: 0 additions & 5 deletions eth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
Expand All @@ -41,7 +40,6 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/triedb/pathdb"
)

const (
Expand Down Expand Up @@ -558,7 +556,4 @@ func (h *handler) enableSyncedFeatures() {
log.Info("Snap sync complete, auto disabling")
h.snapSync.Store(false)
}
if h.chain.TrieDB().Scheme() == rawdb.PathScheme {
h.chain.TrieDB().SetBufferSize(pathdb.DefaultBufferSize)
}
}
8 changes: 4 additions & 4 deletions eth/protocols/snap/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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), nil)
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet())

accTrie, _ = trie.New(trie.StateTrieID(root), db)
return db.Scheme(), accTrie, entries
Expand Down Expand Up @@ -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), nil)
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), triedb.NewStateSet())

accTrie, _ = trie.New(trie.StateTrieID(root), db)
return db.Scheme(), accTrie, entries
Expand Down Expand Up @@ -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, nil)
db.Update(root, types.EmptyRootHash, 0, nodes, triedb.NewStateSet())

// Re-create tries with new root
accTrie, _ = trie.New(trie.StateTrieID(root), db)
Expand Down Expand Up @@ -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, nil)
db.Update(root, types.EmptyRootHash, 0, nodes, triedb.NewStateSet())

// Re-create tries with new root
accTrie, err := trie.New(trie.StateTrieID(root), db)
Expand Down
2 changes: 1 addition & 1 deletion trie/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func newTestDatabase(diskdb ethdb.Database, scheme string) *testDb {
}
}

func (db *testDb) Reader(stateRoot common.Hash) (database.Reader, error) {
func (db *testDb) NodeReader(stateRoot common.Hash) (database.NodeReader, error) {
nodes, _ := db.dirties(stateRoot, true)
return &testReader{db: db.disk, scheme: db.scheme, nodes: nodes}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion trie/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
}
}
// Cross check the hashes and the database itself
reader, err := nodeDb.Reader(trie.Hash())
reader, err := nodeDb.NodeReader(trie.Hash())
if err != nil {
t.Fatalf("state is not available %x", trie.Hash())
}
Expand Down
6 changes: 3 additions & 3 deletions trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type SecureTrie = StateTrie

// NewSecure creates a new StateTrie.
// Deprecated: use NewStateTrie.
func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db database.Database) (*SecureTrie, error) {
func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db database.NodeDatabase) (*SecureTrie, error) {
id := &ID{
StateRoot: stateRoot,
Owner: owner,
Expand All @@ -61,7 +61,7 @@ func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db da
// StateTrie is not safe for concurrent use.
type StateTrie struct {
trie Trie
db database.Database
db database.NodeDatabase
preimages preimageStore
hashKeyBuf [common.HashLength]byte
secKeyCache map[string][]byte
Expand All @@ -73,7 +73,7 @@ type StateTrie struct {
// If root is the zero hash or the sha3 hash of an empty string, the
// trie is initially empty. Otherwise, New will panic if db is nil
// and returns MissingNodeError if the root node cannot be found.
func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) {
if db == nil {
panic("trie.NewStateTrie called without a database")
}
Expand Down
16 changes: 8 additions & 8 deletions trie/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func testIterativeSync(t *testing.T, count int, bypath bool, scheme string) {
syncPath: NewSyncPath([]byte(paths[i])),
})
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -258,7 +258,7 @@ func testIterativeDelayedSync(t *testing.T, scheme string) {
syncPath: NewSyncPath([]byte(paths[i])),
})
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -327,7 +327,7 @@ func testIterativeRandomSync(t *testing.T, count int, scheme string) {
syncPath: NewSyncPath([]byte(paths[i])),
}
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -394,7 +394,7 @@ func testIterativeRandomDelayedSync(t *testing.T, scheme string) {
syncPath: NewSyncPath([]byte(path)),
}
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -466,7 +466,7 @@ func testDuplicateAvoidanceSync(t *testing.T, scheme string) {
syncPath: NewSyncPath([]byte(paths[i])),
})
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -542,7 +542,7 @@ func testIncompleteSync(t *testing.T, scheme string) {
syncPath: NewSyncPath([]byte(paths[i])),
})
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -634,7 +634,7 @@ func testSyncOrdering(t *testing.T, scheme string) {
})
reqs = append(reqs, NewSyncPath([]byte(paths[i])))
}
reader, err := srcDb.Reader(srcTrie.Hash())
reader, err := srcDb.NodeReader(srcTrie.Hash())
if err != nil {
t.Fatalf("State is not available %x", srcTrie.Hash())
}
Expand Down Expand Up @@ -704,7 +704,7 @@ func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb
syncPath: NewSyncPath([]byte(paths[i])),
})
}
reader, err := srcDb.Reader(root)
reader, err := srcDb.NodeReader(root)
if err != nil {
t.Fatalf("State is not available %x", root)
}
Expand Down
4 changes: 2 additions & 2 deletions trie/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (t *Trie) Copy() *Trie {
// zero hash or the sha3 hash of an empty string, then trie is initially
// empty, otherwise, the root node must be present in database or returns
// a MissingNodeError if not.
func New(id *ID, db database.Database) (*Trie, error) {
func New(id *ID, db database.NodeDatabase) (*Trie, error) {
reader, err := newTrieReader(id.StateRoot, id.Owner, db)
if err != nil {
return nil, err
Expand All @@ -104,7 +104,7 @@ func New(id *ID, db database.Database) (*Trie, error) {
}

// NewEmpty is a shortcut to create empty tree. It's mostly used in tests.
func NewEmpty(db database.Database) *Trie {
func NewEmpty(db database.NodeDatabase) *Trie {
tr, _ := New(TrieID(types.EmptyRootHash), db)
return tr
}
Expand Down
9 changes: 6 additions & 3 deletions trie/trie_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@ import (
// for concurrent usage.
type trieReader struct {
owner common.Hash
reader database.Reader
reader database.NodeReader
banned map[string]struct{} // Marker to prevent node from being accessed, for tests
}

// newTrieReader initializes the trie reader with the given node reader.
func newTrieReader(stateRoot, owner common.Hash, db database.Database) (*trieReader, error) {
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!")
}
return &trieReader{owner: owner}, nil
}
reader, err := db.Reader(stateRoot)
reader, err := db.NodeReader(stateRoot)
if err != nil {
return nil, &MissingNodeError{Owner: owner, NodeHash: stateRoot, err: err}
}
Expand All @@ -55,6 +55,9 @@ func newEmptyReader() *trieReader {
// node retrieves the rlp-encoded trie node with the provided trie node
// information. An MissingNodeError will be returned in case the node is
// not found or any error is encountered.
//
// Don't modify the returned byte slice since it's not deep-copied and
// still be referenced by database.
func (r *trieReader) node(path []byte, hash common.Hash) ([]byte, error) {
// Perform the logics in tests for preventing trie node access.
if r.banned != nil {
Expand Down
9 changes: 9 additions & 0 deletions trie/trienode/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ func (set *NodeSet) Size() (int, int) {
return set.updates, set.deletes
}

// HashSet returns a set of trie nodes keyed by node hash.
func (set *NodeSet) HashSet() map[common.Hash][]byte {
ret := make(map[common.Hash][]byte, len(set.Nodes))
for _, n := range set.Nodes {
ret[n.Hash] = n.Blob
}
return ret
}

// Summary returns a string-representation of the NodeSet.
func (set *NodeSet) Summary() string {
var out = new(strings.Builder)
Expand Down
Loading

0 comments on commit 6412bee

Please sign in to comment.