diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index cfbdb01c49..28bf2af1b9 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -31,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie/trienode" + "github.com/ethereum/go-verkle" ) const ( @@ -148,6 +149,18 @@ var Defaults = &Config{ // ReadOnly is the config in order to open database in read only mode. 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 // 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 @@ -350,11 +363,17 @@ func (db *Database) Enable(root common.Hash) error { return errDatabaseReadOnly } // Ensure the provided state root matches the stored one. - root = types.TrieRootHash(root) - stored := types.EmptyRootHash + var ( + err error + stored = types.EmptyRootHash + ) 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 { return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root) } diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 24edd77047..8a4e4adb4c 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -26,10 +26,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-verkle" ) 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. func (db *Database) loadLayers() layer { // 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 db.isVerkle { - rootnode, err := verkle.ParseNode(blob, 0) - if err != nil { - log.Crit("Could not decode verkle root node") - } - root = rootnode.Commit().Bytes() - } else { - root = crypto.Keccak256Hash(blob) + root, err = nodeToHash(blob, db.isVerkle) + if err != nil { + log.Crit("Invalid root verkle node", "err", err) } } // 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 journal := new(bytes.Buffer) - if err := rlp.Encode(journal, journalVersion); err != nil { + err := rlp.Encode(journal, journalVersion) + if err != nil { return err } // Secondly write out the state root in disk, ensure all layers // on top are continuous with disk. diskRoot := types.EmptyRootHash 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 { return err