diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index b4afe0b4c6..b65827f5bc 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -20,7 +20,6 @@ import ( "encoding/json" "errors" "fmt" - "math/big" "os" "runtime" "strconv" @@ -212,7 +211,7 @@ func initGenesis(ctx *cli.Context) error { } defer chaindb.Close() - triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.Config.IsVerkle(big.NewInt(0), genesis.Timestamp)) + triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) defer triedb.Close() _, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) diff --git a/core/genesis_test.go b/core/genesis_test.go index f8d1558505..9f2c527cc0 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -17,6 +17,7 @@ package core import ( + "bytes" "encoding/json" "math/big" "reflect" @@ -261,3 +262,50 @@ func newDbConfig(scheme string) *trie.Config { } return &trie.Config{PathDB: pathdb.Defaults} } + +func TestVerkleGenesisCommit(t *testing.T) { + var verkleTime uint64 = 0 + verkleConfig := ¶ms.ChainConfig{ + ChainID: big.NewInt(1), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: false, + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + BerlinBlock: big.NewInt(0), + LondonBlock: big.NewInt(0), + ArrowGlacierBlock: big.NewInt(0), + GrayGlacierBlock: big.NewInt(0), + MergeNetsplitBlock: nil, + ShanghaiTime: nil, + CancunTime: nil, + PragueTime: nil, + VerkleTime: &verkleTime, + TerminalTotalDifficulty: nil, + TerminalTotalDifficultyPassed: true, + Ethash: nil, + Clique: nil, + } + + genesis := &Genesis{ + BaseFee: big.NewInt(params.InitialBaseFee), + Config: verkleConfig, + Timestamp: verkleTime, + // difficulty is nil + Alloc: GenesisAlloc{ + {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, + }, + } + + expected := common.Hex2Bytes("14398d42be3394ff8d50681816a4b7bf8d8283306f577faba2d5bc57498de23b") + got := genesis.ToBlock().Root().Bytes() + if !bytes.Equal(got, expected) { + t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got) + } +} diff --git a/core/state/database.go b/core/state/database.go index 986e6f39b7..9f183da0f7 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -177,15 +177,21 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { if err != nil { return nil, fmt.Errorf("failed to get node reader in OpenTrie: %w", err) } - verklerootbytes, err := reader.Node(common.Hash{}, nil, common.Hash{}) - if err != nil { - return nil, fmt.Errorf("failed to get serialized root node in OpenTrie: %w", err) + + var verkleroot verkle.VerkleNode + if root != (common.Hash{}) && root != types.EmptyRootHash { + verklerootbytes, err := reader.Node(common.Hash{}, nil, common.Hash{}) + if err != nil { + return nil, fmt.Errorf("failed to get serialized root node in OpenTrie: %w", err) + } + verkleroot, err = verkle.ParseNode(verklerootbytes, 0) + if err != nil { + return nil, fmt.Errorf("failed to deserialize root node in OpenTrie: %w", err) + } + } else { + verkleroot = verkle.New() } - verkleroot, err := verkle.ParseNode(verklerootbytes, 0) - if err != nil { - return nil, fmt.Errorf("failed to deserialize root node in OpenTrie: %w", err) - } - return trie.NewVerkleTrie(verkleroot, db.triedb, utils.NewPointCache(), true) + return trie.NewVerkleTrie(root, verkleroot, db.triedb, utils.NewPointCache(), true) } tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) if err != nil { diff --git a/trie/verkle.go b/trie/verkle.go index c10dee3f3d..9e780c7048 100644 --- a/trie/verkle.go +++ b/trie/verkle.go @@ -17,7 +17,6 @@ package trie import ( - "crypto/sha256" "encoding/binary" "errors" "fmt" @@ -39,6 +38,7 @@ type VerkleTrie struct { db *Database pointCache *utils.PointCache ended bool + rootHash common.Hash reader *trieReader } @@ -46,9 +46,7 @@ func (vt *VerkleTrie) ToDot() string { return verkle.ToDot(vt.root) } -func NewVerkleTrie(root verkle.VerkleNode, db *Database, pointCache *utils.PointCache, ended bool) (*VerkleTrie, error) { - comm := root.Commit().Bytes() - rootHash := sha256.Sum256(comm[:]) +func NewVerkleTrie(rootHash common.Hash, root verkle.VerkleNode, db *Database, pointCache *utils.PointCache, ended bool) (*VerkleTrie, error) { reader, err := newTrieReader(rootHash, common.Hash{}, db) if err != nil { return nil, err @@ -58,14 +56,12 @@ func NewVerkleTrie(root verkle.VerkleNode, db *Database, pointCache *utils.Point db: db, pointCache: pointCache, ended: ended, + rootHash: rootHash, reader: reader, }, nil } func (trie *VerkleTrie) FlatdbNodeResolver(path []byte) ([]byte, error) { - // NOTE: I use common.Hash{} as the hash, as I expect it to be ignored - // since we are using the pathdb. @rjl493456442 please confirm that this - // works. return trie.reader.reader.Node(trie.reader.owner, path, common.Hash{}) } @@ -248,14 +244,13 @@ func (trie *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) { nodeset := trienode.NewNodeSet(common.Hash{}) for _, node := range nodes { - comm := node.Node.Commitment().Bytes() - hash := sha256.Sum256(comm[:]) - nodeset.AddNode(node.Path, trienode.New(common.BytesToHash(hash[:]), node.SerializedBytes)) + // hash parameter is not used in pathdb + nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes)) } // Serialize root commitment form - rootH := root.Hash().BytesLE() - return common.BytesToHash(rootH[:]), nodeset, nil + trie.rootHash = trie.Hash() + return trie.rootHash, nodeset, nil } // NodeIterator returns an iterator that returns nodes of the trie. Iteration