@@ -31,6 +31,7 @@ import (
3131 "github.com/ethereum/go-ethereum/log"
3232 "github.com/ethereum/go-ethereum/params"
3333 "github.com/ethereum/go-ethereum/trie/trienode"
34+ "github.com/ethereum/go-verkle"
3435)
3536
3637const (
@@ -148,6 +149,29 @@ var Defaults = &Config{
148149// ReadOnly is the config in order to open database in read only mode.
149150var ReadOnly = & Config {ReadOnly : true }
150151
152+ // nodeHasher is the function to compute the hash of supplied node blob.
153+ type nodeHasher func ([]byte ) (common.Hash , error )
154+
155+ // merkleNodeHasher computes the hash of the given merkle node.
156+ func merkleNodeHasher (blob []byte ) (common.Hash , error ) {
157+ if len (blob ) == 0 {
158+ return types .EmptyRootHash , nil
159+ }
160+ return crypto .Keccak256Hash (blob ), nil
161+ }
162+
163+ // verkleNodeHasher computes the hash of the given verkle node.
164+ func verkleNodeHasher (blob []byte ) (common.Hash , error ) {
165+ if len (blob ) == 0 {
166+ return types .EmptyVerkleHash , nil
167+ }
168+ n , err := verkle .ParseNode (blob , 0 )
169+ if err != nil {
170+ return common.Hash {}, err
171+ }
172+ return n .Commit ().Bytes (), nil
173+ }
174+
151175// Database is a multiple-layered structure for maintaining in-memory states
152176// along with its dirty trie nodes. It consists of one persistent base layer
153177// backed by a key-value store, on top of which arbitrarily many in-memory diff
@@ -164,9 +188,10 @@ type Database struct {
164188 // readOnly is the flag whether the mutation is allowed to be applied.
165189 // It will be set automatically when the database is journaled during
166190 // the shutdown to reject all following unexpected mutations.
167- readOnly bool // Flag if database is opened in read only mode
168- waitSync bool // Flag if database is deactivated due to initial state sync
169- isVerkle bool // Flag if database is used for verkle tree
191+ readOnly bool // Flag if database is opened in read only mode
192+ waitSync bool // Flag if database is deactivated due to initial state sync
193+ isVerkle bool // Flag if database is used for verkle tree
194+ hasher nodeHasher // Trie node hasher
170195
171196 config * Config // Configuration for database
172197 diskdb ethdb.Database // Persistent storage for matured trie nodes
@@ -184,19 +209,21 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
184209 }
185210 config = config .sanitize ()
186211
212+ db := & Database {
213+ readOnly : config .ReadOnly ,
214+ isVerkle : isVerkle ,
215+ config : config ,
216+ diskdb : diskdb ,
217+ hasher : merkleNodeHasher ,
218+ }
187219 // Establish a dedicated database namespace tailored for verkle-specific
188220 // data, ensuring the isolation of both verkle and merkle tree data. It's
189221 // important to note that the introduction of a prefix won't lead to
190222 // substantial storage overhead, as the underlying database will efficiently
191223 // compress the shared key prefix.
192224 if isVerkle {
193- diskdb = rawdb .NewTable (diskdb , string (rawdb .VerklePrefix ))
194- }
195- db := & Database {
196- readOnly : config .ReadOnly ,
197- isVerkle : isVerkle ,
198- config : config ,
199- diskdb : diskdb ,
225+ db .diskdb = rawdb .NewTable (diskdb , string (rawdb .VerklePrefix ))
226+ db .hasher = verkleNodeHasher
200227 }
201228 // Construct the layer tree by resolving the in-disk singleton state
202229 // and in-memory layer journal.
@@ -277,6 +304,8 @@ func (db *Database) repairHistory() error {
277304//
278305// The passed in maps(nodes, states) will be retained to avoid copying everything.
279306// Therefore, these maps must not be changed afterwards.
307+ //
308+ // The supplied parentRoot and root must be a valid trie hash value.
280309func (db * Database ) Update (root common.Hash , parentRoot common.Hash , block uint64 , nodes * trienode.MergedNodeSet , states * StateSetWithOrigin ) error {
281310 // Hold the lock to prevent concurrent mutations.
282311 db .lock .Lock ()
@@ -350,10 +379,9 @@ func (db *Database) Enable(root common.Hash) error {
350379 return errDatabaseReadOnly
351380 }
352381 // Ensure the provided state root matches the stored one.
353- root = types .TrieRootHash (root )
354- stored := types .EmptyRootHash
355- if blob := rawdb .ReadAccountTrieNode (db .diskdb , nil ); len (blob ) > 0 {
356- stored = crypto .Keccak256Hash (blob )
382+ stored , err := db .hasher (rawdb .ReadAccountTrieNode (db .diskdb , nil ))
383+ if err != nil {
384+ return err
357385 }
358386 if stored != root {
359387 return fmt .Errorf ("state root mismatch: stored %x, synced %x" , stored , root )
@@ -389,6 +417,8 @@ func (db *Database) Enable(root common.Hash) error {
389417// Recover rollbacks the database to a specified historical point.
390418// The state is supported as the rollback destination only if it's
391419// canonical state and the corresponding trie histories are existent.
420+ //
421+ // The supplied root must be a valid trie hash value.
392422func (db * Database ) Recover (root common.Hash ) error {
393423 db .lock .Lock ()
394424 defer db .lock .Unlock ()
@@ -401,7 +431,6 @@ func (db *Database) Recover(root common.Hash) error {
401431 return errors .New ("state rollback is non-supported" )
402432 }
403433 // Short circuit if the target state is not recoverable
404- root = types .TrieRootHash (root )
405434 if ! db .Recoverable (root ) {
406435 return errStateUnrecoverable
407436 }
@@ -434,9 +463,10 @@ func (db *Database) Recover(root common.Hash) error {
434463}
435464
436465// Recoverable returns the indicator if the specified state is recoverable.
466+ //
467+ // The supplied root must be a valid trie hash value.
437468func (db * Database ) Recoverable (root common.Hash ) bool {
438469 // Ensure the requested state is a known state.
439- root = types .TrieRootHash (root )
440470 id := rawdb .ReadStateID (db .diskdb , root )
441471 if id == nil {
442472 return false
0 commit comments