triedb/pathdb: implement nodeToHash

This commit is contained in:
Gary Rong 2024-12-09 15:50:11 +08:00
parent 65255f1651
commit 2d4243082a
2 changed files with 35 additions and 16 deletions

View file

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-verkle"
) )
const ( const (
@ -148,6 +149,18 @@ var Defaults = &Config{
// ReadOnly is the config in order to open database in read only mode. // ReadOnly is the config in order to open database in read only mode.
var ReadOnly = &Config{ReadOnly: true} var ReadOnly = &Config{ReadOnly: true}
// nodeToHash computes the hash of the given node based on the tree structure.
func nodeToHash(blob []byte, isVerkle bool) (common.Hash, error) {
if !isVerkle {
return crypto.Keccak256Hash(blob), nil
}
n, err := verkle.ParseNode(blob, 0)
if err != nil {
return common.Hash{}, err
}
return n.Commit().Bytes(), nil
}
// Database is a multiple-layered structure for maintaining in-memory states // Database is a multiple-layered structure for maintaining in-memory states
// along with its dirty trie nodes. It consists of one persistent base layer // along with its dirty trie nodes. It consists of one persistent base layer
// backed by a key-value store, on top of which arbitrarily many in-memory diff // backed by a key-value store, on top of which arbitrarily many in-memory diff
@ -350,11 +363,17 @@ func (db *Database) Enable(root common.Hash) error {
return errDatabaseReadOnly return errDatabaseReadOnly
} }
// Ensure the provided state root matches the stored one. // Ensure the provided state root matches the stored one.
root = types.TrieRootHash(root) var (
stored := types.EmptyRootHash err error
stored = types.EmptyRootHash
)
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
stored = crypto.Keccak256Hash(blob) stored, err = nodeToHash(blob, db.isVerkle)
if err != nil {
return err
}
} }
root = types.TrieRootHash(root)
if stored != root { if stored != root {
return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root)
} }

View file

@ -26,10 +26,8 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-verkle"
) )
var ( var (
@ -94,16 +92,14 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) {
// loadLayers loads a pre-existing state layer backed by a key-value store. // loadLayers loads a pre-existing state layer backed by a key-value store.
func (db *Database) loadLayers() layer { func (db *Database) loadLayers() layer {
// Retrieve the root node of persistent state. // Retrieve the root node of persistent state.
var root = types.EmptyRootHash var (
err error
root = types.EmptyRootHash
)
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
if db.isVerkle { root, err = nodeToHash(blob, db.isVerkle)
rootnode, err := verkle.ParseNode(blob, 0) if err != nil {
if err != nil { log.Crit("Invalid root verkle node", "err", err)
log.Crit("Could not decode verkle root node")
}
root = rootnode.Commit().Bytes()
} else {
root = crypto.Keccak256Hash(blob)
} }
} }
// Load the layers by resolving the journal // Load the layers by resolving the journal
@ -269,14 +265,18 @@ func (db *Database) Journal(root common.Hash) error {
} }
// Firstly write out the metadata of journal // Firstly write out the metadata of journal
journal := new(bytes.Buffer) journal := new(bytes.Buffer)
if err := rlp.Encode(journal, journalVersion); err != nil { err := rlp.Encode(journal, journalVersion)
if err != nil {
return err return err
} }
// Secondly write out the state root in disk, ensure all layers // Secondly write out the state root in disk, ensure all layers
// on top are continuous with disk. // on top are continuous with disk.
diskRoot := types.EmptyRootHash diskRoot := types.EmptyRootHash
if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 { if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
diskRoot = crypto.Keccak256Hash(blob) diskRoot, err = nodeToHash(blob, db.isVerkle)
if err != nil {
return err
}
} }
if err := rlp.Encode(journal, diskRoot); err != nil { if err := rlp.Encode(journal, diskRoot); err != nil {
return err return err