Skip to content

Commit

Permalink
core: new state trie for dump when state scheme is path
Browse files Browse the repository at this point in the history
  • Loading branch information
VM committed Jan 24, 2024
1 parent 54c1530 commit 458d67c
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 39 deletions.
26 changes: 16 additions & 10 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,9 +617,13 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
}

db := utils.MakeChainDatabase(ctx, stack, true, false)
scheme, err := utils.ParseStateScheme(ctx, db)
provided, err := utils.CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
return nil, nil, common.Hash{}, fmt.Errorf("failed to parse state scheme: %v", err)
return nil, nil, common.Hash{}, err
}
scheme, err := rawdb.ParseStateScheme(provided, db)
if err != nil {
return nil, nil, common.Hash{}, err
}
var header *types.Header
if scheme == rawdb.PathScheme {
Expand All @@ -633,7 +637,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
if header == nil {
return nil, nil, common.Hash{}, fmt.Errorf("no head block found")
}
if contain := triedb.ContainDiffLayer(header.Root); !contain {
if contain := triedb.ContainRootHash(header.Root); !contain {
return nil, nil, common.Hash{}, fmt.Errorf("PBSS doesn't contain specified MPT root hash for block hash %x", hash)
}
} else {
Expand All @@ -649,7 +653,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
if header == nil {
return nil, nil, common.Hash{}, fmt.Errorf("no head block found")
}
if contain := triedb.ContainDiffLayer(header.Root); !contain {
if contain := triedb.ContainRootHash(header.Root); !contain {
return nil, nil, common.Hash{}, fmt.Errorf("PBSS doesn't contain specified MPT root hash for block number %d", number)
}
} else {
Expand All @@ -658,12 +662,13 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
}
} else {
if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) {
if contain := triedb.ContainDiffLayer(stateRoot); !contain {
if contain := triedb.ContainRootHash(stateRoot); !contain {
return nil, nil, common.Hash{}, fmt.Errorf("PBSS doesn't contain specified state root %x", stateRoot)
}
log.Info("State dump configured", "mpt root hash", stateRoot,
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage,
"start", hexutil.Encode(conf.Start), "limit", conf.Max)
conf.StateScheme = rawdb.PathScheme
log.Info("State dump configured", "mpt root hash", stateRoot, "skipcode", conf.SkipCode,
"skipstorage", conf.SkipStorage, "start", hexutil.Encode(conf.Start), "limit", conf.Max,
"state scheme", conf.StateScheme)
return conf, db, stateRoot, nil
} else {
return nil, nil, common.Hash{}, fmt.Errorf("no top state root hash in path db")
Expand Down Expand Up @@ -699,9 +704,10 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
if header == nil {
return nil, nil, common.Hash{}, errors.New("no head block found")
}
conf.StateScheme = scheme
log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(),
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage,
"start", hexutil.Encode(conf.Start), "limit", conf.Max)
"skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, "start", hexutil.Encode(conf.Start),
"limit", conf.Max, "state scheme", conf.StateScheme)
return conf, db, header.Root, nil
}

Expand Down
9 changes: 5 additions & 4 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1884,7 +1884,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(StateHistoryFlag.Name) {
cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name)
}
scheme, err := compareCLIWithConfig(ctx)
scheme, err := CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
Fatalf("%v", err)
}
Expand Down Expand Up @@ -2353,7 +2353,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}
provided, err := compareCLIWithConfig(ctx)
provided, err := CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
Fatalf("%v", err)
}
Expand Down Expand Up @@ -2425,7 +2425,7 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
config := &trie.Config{
Preimages: preimage,
}
provided, err := compareCLIWithConfig(ctx)
provided, err := CompareStateSchemeCLIWithConfig(ctx)
if err != nil {
Fatalf("%v", err)
}
Expand All @@ -2448,7 +2448,8 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
return trie.NewDatabase(disk, config)
}

func compareCLIWithConfig(ctx *cli.Context) (string, error) {
// CompareStateSchemeCLIWithConfig compare state scheme in CLI with config whether are equal.
func CompareStateSchemeCLIWithConfig(ctx *cli.Context) (string, error) {
var (
cfgScheme string
err error
Expand Down
10 changes: 9 additions & 1 deletion core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
Expand All @@ -37,6 +38,7 @@ type DumpConfig struct {
OnlyWithAddresses bool
Start []byte
Max uint64
StateScheme string
}

// DumpCollector interface which the state trie calls during iteration
Expand Down Expand Up @@ -177,7 +179,13 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
}
if !conf.SkipStorage {
account.Storage = make(map[common.Hash]string)
tr, err := obj.getTrie()
var tr Trie
if conf.StateScheme == rawdb.PathScheme {
tr, err = trie.NewStateTrie(trie.StorageTrieID(obj.db.originalRoot, common.BytesToHash(it.Key),
obj.data.Root), obj.db.db.TrieDB())
} else {
tr, err = obj.getTrie()
}
if err != nil {
log.Error("Failed to load storage trie", "err", err)
continue
Expand Down
10 changes: 6 additions & 4 deletions trie/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (db *Database) SetBufferSize(size int) error {
}

// Head return the top non-fork difflayer/disklayer root hash for rewinding.
// It's only supported by path-based database and will return an error for
// It's only supported by path-based database and will return empty hash for
// others.
func (db *Database) Head() common.Hash {
pdb, ok := db.backend.(*pathdb.Database)
Expand All @@ -365,12 +365,14 @@ func (db *Database) Head() common.Hash {
return pdb.Head()
}

// ContainDiffLayer returns whether root is existent.
func (db *Database) ContainDiffLayer(root common.Hash) bool {
// ContainRootHash returns whether MPT root hash is existent.
// It's only supported by path-based database and will return false for
// others.
func (db *Database) ContainRootHash(root common.Hash) bool {
pdb, ok := db.backend.(*pathdb.Database)
if !ok {
log.Error("not supported")
return false
}
return pdb.ContainDiffLayer(root)
return pdb.ContainRootHash(root)
}
2 changes: 0 additions & 2 deletions trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package trie
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
)
Expand Down Expand Up @@ -68,7 +67,6 @@ func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
}
trie, err := New(id, db)
if err != nil {
log.Error("NewStateTrie")
return nil, err
}
return &StateTrie{trie: *trie, preimages: db.preimages}, nil
Expand Down
3 changes: 0 additions & 3 deletions trie/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ func (t *Trie) Copy() *Trie {
func New(id *ID, db *Database) (*Trie, error) {
reader, err := newTrieReader(id.StateRoot, id.Owner, db)
if err != nil {
log.Error("Failed to newTrieReader")
return nil, err
}
trie := &Trie{
Expand All @@ -93,7 +92,6 @@ func New(id *ID, db *Database) (*Trie, error) {
if id.Root != (common.Hash{}) && id.Root != types.EmptyRootHash {
rootnode, err := trie.resolveAndTrack(id.Root[:], nil)
if err != nil {
log.Error("Failed to resolveAndTrack")
return nil, err
}
trie.root = rootnode
Expand Down Expand Up @@ -589,7 +587,6 @@ func (t *Trie) resolve(n node, prefix []byte) (node, error) {
func (t *Trie) resolveAndTrack(n hashNode, prefix []byte) (node, error) {
blob, err := t.reader.node(prefix, common.BytesToHash(n))
if err != nil {
log.Error("resolveAndTrack failed to call node")
return nil, err
}
t.tracer.onRead(prefix, blob)
Expand Down
4 changes: 0 additions & 4 deletions trie/trie_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ func newTrieReader(stateRoot, owner common.Hash, db *Database) (*trieReader, err
}
reader, err := db.Reader(stateRoot)
if err != nil {
log.Error("Failed to newTrieReader")
return nil, &MissingNodeError{Owner: owner, NodeHash: stateRoot, err: err}
}
return &trieReader{owner: owner, reader: reader}, nil
Expand All @@ -73,17 +72,14 @@ 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 {
if _, ok := r.banned[string(path)]; ok {
log.Error("banned")
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path}
}
}
if r.reader == nil {
log.Error("trieReader reader is nil")
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path}
}
blob, err := r.reader.Node(r.owner, path, hash)
if err != nil || len(blob) == 0 {
log.Error("Failed to call trieReader Node", "length", len(blob))
return nil, &MissingNodeError{Owner: r.owner, NodeHash: hash, Path: path, err: err}
}
return blob, nil
Expand Down
7 changes: 3 additions & 4 deletions trie/triedb/pathdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,12 +442,11 @@ func (db *Database) Head() common.Hash {
return db.tree.front()
}

// ContainDiffLayer returns whether root is existent.
func (db *Database) ContainDiffLayer(root common.Hash) bool {
// ContainRootHash returns whether MPT root hash is existent.
func (db *Database) ContainRootHash(root common.Hash) bool {
db.lock.Lock()
defer db.lock.Unlock()

log.Info("print all layer tree", "all", db.tree.layers)
bottom := db.tree.bottom()
if l := db.tree.get(root); l != nil {
if l.rootHash() == bottom.rootHash() {
Expand All @@ -459,7 +458,7 @@ func (db *Database) ContainDiffLayer(root common.Hash) bool {
}
_, err := bottom.Node(common.Hash{}, []byte(""), root)
if err != nil {
log.Error("Failed to retrieve root hash in disk layer", "hash", root, "error", err)
log.Error("Failed to retrieve root hash in disk layer node buffer", "hash", root, "error", err)
return false
}
log.Info("root hash locates in disk layer node buffer")
Expand Down
2 changes: 0 additions & 2 deletions trie/triedb/pathdb/disklayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,8 @@ func (dl *diskLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]b
)
if owner == (common.Hash{}) {
nBlob, nHash = rawdb.ReadAccountTrieNode(dl.db.diskdb, path)
log.Info("owner is empty", "owner", owner, "path", path, "expect", hash, "got", nHash, "blob", nBlob)
} else {
nBlob, nHash = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path)
log.Info("owner is nonempty", "owner", owner, "path", path, "expect", hash, "got", nHash, "blob", nBlob)
}
if nHash != hash {
diskFalseMeter.Mark(1)
Expand Down
7 changes: 2 additions & 5 deletions trie/triedb/pathdb/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,14 @@ func (dl *diskLayer) journal(w io.Writer) error {
for owner, subset := range bufferNodes {
entry := journalNodes{Owner: owner}
for path, node := range subset {
if owner == (common.Hash{}) && path == "" {
log.Info("node is in disk layer node buffer", "owner", owner, "path", path, "node hash", node.Hash.String())
}
entry.Nodes = append(entry.Nodes, journalNode{Path: []byte(path), Blob: node.Blob})
}
nodes = append(nodes, entry)
}
if err := rlp.Encode(w, nodes); err != nil {
return err
}
log.Info("Journaled pathdb disk layer", "root", dl.root, "nodes", len(bufferNodes))
log.Debug("Journaled pathdb disk layer", "root", dl.root, "nodes", len(bufferNodes))
return nil
}

Expand Down Expand Up @@ -332,7 +329,7 @@ func (dl *diffLayer) journal(w io.Writer) error {
if err := rlp.Encode(w, storage); err != nil {
return err
}
log.Info("Journaled pathdb diff layer", "root", dl.root, "parent", dl.parent.rootHash(), "id", dl.stateID(), "block", dl.block, "nodes", len(dl.nodes))
log.Debug("Journaled pathdb diff layer", "root", dl.root, "parent", dl.parent.rootHash(), "id", dl.stateID(), "block", dl.block, "nodes", len(dl.nodes))
return nil
}

Expand Down

0 comments on commit 458d67c

Please sign in to comment.