core/{,state}: use one triedb per tree

This commit is contained in:
Guillaume Ballet 2025-04-14 22:02:57 +02:00
parent bb038c64a5
commit 159b3bb817
33 changed files with 161 additions and 112 deletions

View file

@ -416,7 +416,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB { func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
sdb := state.NewDatabase(tdb, nil) vdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
sdb := state.NewDatabase(tdb, vdb, nil)
statedb, _ := state.New(types.EmptyRootHash, sdb) statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) statedb.SetCode(addr, a.Code)

View file

@ -221,13 +221,14 @@ func runCmd(ctx *cli.Context) error {
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, &triedb.Config{ triedb := triedb.NewDatabase(db, &triedb.Config{
Preimages: preimages, Preimages: preimages,
HashDB: hashdb.Defaults, HashDB: hashdb.Defaults,
}) })
defer triedb.Close() defer triedb.Close()
genesis := genesisConfig.MustCommit(db, triedb) genesis := genesisConfig.MustCommit(db, triedb, verkledb)
sdb := state.NewDatabase(triedb, nil) sdb := state.NewDatabase(triedb, verkledb, nil)
prestate, _ = state.New(genesis.Root(), sdb) prestate, _ = state.New(genesis.Root(), sdb)
chainConfig = genesisConfig.Config chainConfig = genesisConfig.Config

View file

@ -243,10 +243,11 @@ func initGenesis(ctx *cli.Context) error {
} }
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) triedb, verkledb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
_, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) _, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, verkledb, genesis, &overrides)
if err != nil { if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err) utils.Fatalf("Failed to write genesis block: %v", err)
} }
@ -594,10 +595,11 @@ func dump(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup triedb, verkledb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
state, err := state.New(root, state.NewDatabase(triedb, nil)) state, err := state.New(root, state.NewDatabase(triedb, verkledb, nil))
if err != nil { if err != nil {
return err return err
} }

View file

@ -524,8 +524,9 @@ func dbDumpTrie(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true) db := utils.MakeChainDatabase(ctx, stack, true)
defer db.Close() defer db.Close()
triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, db, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
var ( var (
state []byte state []byte
@ -859,8 +860,9 @@ func inspectHistory(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true) db := utils.MakeChainDatabase(ctx, stack, true)
defer db.Close() defer db.Close()
triedb := utils.MakeTrieDatabase(ctx, db, false, false, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, db, false, false, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
var ( var (
err error err error

View file

@ -217,8 +217,9 @@ func verifyState(ctx *cli.Context) error {
log.Error("Failed to load head block") log.Error("Failed to load head block")
return errors.New("no head block") return errors.New("no head block")
} }
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
snapConfig := snapshot.Config{ snapConfig := snapshot.Config{
CacheSize: 256, CacheSize: 256,
@ -272,8 +273,9 @@ func traverseState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb) headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil { if headBlock == nil {
@ -381,8 +383,9 @@ func traverseRawState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb) headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil { if headBlock == nil {
@ -548,8 +551,9 @@ func dumpState(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, db, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
snapConfig := snapshot.Config{ snapConfig := snapshot.Config{
CacheSize: 256, CacheSize: 256,
@ -630,8 +634,9 @@ func snapshotExportPreimages(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) triedb, verkledb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
defer triedb.Close() defer triedb.Close()
defer verkledb.Close()
var root common.Hash var root common.Hash
if ctx.NArg() > 1 { if ctx.NArg() > 1 {

View file

@ -2262,7 +2262,7 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
} }
// MakeTrieDatabase constructs a trie database based on the configured scheme. // MakeTrieDatabase constructs a trie database based on the configured scheme.
func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database { func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) (*triedb.Database, *triedb.Database) {
config := &triedb.Config{ config := &triedb.Config{
Preimages: preimage, Preimages: preimage,
IsVerkle: isVerkle, IsVerkle: isVerkle,
@ -2276,12 +2276,12 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
// ignore the parameter silently. TODO(rjl493456442) // ignore the parameter silently. TODO(rjl493456442)
// please config it if read mode is implemented. // please config it if read mode is implemented.
config.HashDB = hashdb.Defaults config.HashDB = hashdb.Defaults
return triedb.NewDatabase(disk, config) return triedb.NewDatabase(disk, config), triedb.NewDatabase(disk, triedb.VerkleDefaults)
} }
if readOnly { if readOnly {
config.PathDB = pathdb.ReadOnly config.PathDB = pathdb.ReadOnly
} else { } else {
config.PathDB = pathdb.Defaults config.PathDB = pathdb.Defaults
} }
return triedb.NewDatabase(disk, config) return triedb.NewDatabase(disk, config), triedb.NewDatabase(disk, triedb.VerkleDefaults)
} }

View file

@ -166,7 +166,7 @@ func TestHistoryImportAndExport(t *testing.T) {
db2.Close() db2.Close()
}) })
genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults)) genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults), triedb.NewDatabase(db2, triedb.VerkleDefaults))
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil) imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
if err != nil { if err != nil {
t.Fatalf("unable to initialize chain: %v", err) t.Fatalf("unable to initialize chain: %v", err)

View file

@ -234,6 +234,7 @@ type BlockChain struct {
lastWrite uint64 // Last block when the state was flushed lastWrite uint64 // Last block when the state was flushed
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
triedb *triedb.Database // The database handler for maintaining trie nodes. triedb *triedb.Database // The database handler for maintaining trie nodes.
verkledb *triedb.Database // The database handler for maintaining verkle trie nodes.
statedb *state.CachingDB // State database to reuse between imports (contains state cache) statedb *state.CachingDB // State database to reuse between imports (contains state cache)
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
@ -283,13 +284,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if cacheConfig == nil { if cacheConfig == nil {
cacheConfig = defaultCacheConfig cacheConfig = defaultCacheConfig
} }
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(genesis.IsVerkle())) triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(genesis.IsVerkle()))
// Write the supplied genesis to the database if it has not been initialized // Write the supplied genesis to the database if it has not been initialized
// yet. The corresponding chain config will be returned, either from the // yet. The corresponding chain config will be returned, either from the
// provided genesis or from the locally stored configuration if the genesis // provided genesis or from the locally stored configuration if the genesis
// has already been initialized. // has already been initialized.
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, verkledb, genesis, overrides)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -306,6 +308,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
cacheConfig: cacheConfig, cacheConfig: cacheConfig,
db: db, db: db,
triedb: triedb, triedb: triedb,
verkledb: verkledb,
triegc: prque.New[int64, common.Hash](nil), triegc: prque.New[int64, common.Hash](nil),
quit: make(chan struct{}), quit: make(chan struct{}),
chainmu: syncx.NewClosableMutex(), chainmu: syncx.NewClosableMutex(),
@ -323,7 +326,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
return nil, err return nil, err
} }
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
bc.statedb = state.NewDatabase(bc.triedb, nil) bc.statedb = state.NewDatabase(bc.triedb, bc.verkledb, nil)
bc.validator = NewBlockValidator(chainConfig, bc) bc.validator = NewBlockValidator(chainConfig, bc)
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc) bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
bc.processor = NewStateProcessor(chainConfig, bc.hc) bc.processor = NewStateProcessor(chainConfig, bc.hc)
@ -464,7 +467,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root) bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
// Re-initialize the state database with snapshot // Re-initialize the state database with snapshot
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps) bc.statedb = state.NewDatabase(bc.triedb, bc.verkledb, bc.snaps)
} }
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
@ -1168,6 +1171,9 @@ func (bc *BlockChain) Stop() {
if err := bc.triedb.Close(); err != nil { if err := bc.triedb.Close(); err != nil {
log.Error("Failed to close trie database", "err", err) log.Error("Failed to close trie database", "err", err)
} }
if err := bc.verkledb.Close(); err != nil {
log.Error("Failed to close the verkle trie database", "err", err)
}
log.Info("Blockchain stopped") log.Info("Blockchain stopped")
} }

View file

@ -1846,6 +1846,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
} }
// Pull the plug on the database, simulating a hard crash // Pull the plug on the database, simulating a hard crash
chain.triedb.Close() chain.triedb.Close()
chain.verkledb.Close()
db.Close() db.Close()
chain.stopWithoutSaving() chain.stopWithoutSaving()
@ -1969,6 +1970,7 @@ func testIssue23496(t *testing.T, scheme string) {
// Pull the plug on the database, simulating a hard crash // Pull the plug on the database, simulating a hard crash
chain.triedb.Close() chain.triedb.Close()
chain.verkledb.Close()
db.Close() db.Close()
chain.stopWithoutSaving() chain.stopWithoutSaving()

View file

@ -2034,6 +2034,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
} }
// Reopen the trie database without persisting in-memory dirty nodes. // Reopen the trie database without persisting in-memory dirty nodes.
chain.triedb.Close() chain.triedb.Close()
chain.verkledb.Close()
dbconfig := &triedb.Config{} dbconfig := &triedb.Config{}
if scheme == rawdb.PathScheme { if scheme == rawdb.PathScheme {
dbconfig.PathDB = pathdb.Defaults dbconfig.PathDB = pathdb.Defaults
@ -2041,7 +2042,8 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
dbconfig.HashDB = hashdb.Defaults dbconfig.HashDB = hashdb.Defaults
} }
chain.triedb = triedb.NewDatabase(chain.db, dbconfig) chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
chain.statedb = state.NewDatabase(chain.triedb, chain.snaps) chain.verkledb = triedb.NewDatabase(chain.db, triedb.VerkleDefaults)
chain.statedb = state.NewDatabase(chain.triedb, chain.verkledb, chain.snaps)
// Force run a freeze cycle // Force run a freeze cycle
type freezer interface { type freezer interface {

View file

@ -255,6 +255,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
db.Close() db.Close()
chain.stopWithoutSaving() chain.stopWithoutSaving()
chain.triedb.Close() chain.triedb.Close()
chain.verkledb.Close()
// Start a new blockchain back up and see where the repair leads us // Start a new blockchain back up and see where the repair leads us
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false, true) pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false, true)
@ -410,6 +411,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
// Simulate the blockchain crash. // Simulate the blockchain crash.
tmp.triedb.Close() tmp.triedb.Close()
tmp.verkledb.Close()
tmp.stopWithoutSaving() tmp.stopWithoutSaving()
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil) newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)

View file

@ -422,12 +422,15 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
return block, b.receipts return block, b.receipts
} }
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
defer verkledb.Close()
// Forcibly use hash-based state scheme for retaining all nodes in disk. // Forcibly use hash-based state scheme for retaining all nodes in disk.
triedb := triedb.NewDatabase(db, triedb.HashDefaults) triedb := triedb.NewDatabase(db, triedb.HashDefaults)
defer triedb.Close() defer triedb.Close()
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
statedb, err := state.New(parent.Root(), state.NewDatabase(triedb, nil)) statedb, err := state.New(parent.Root(), state.NewDatabase(triedb, verkledb, nil))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -468,9 +471,11 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
// then generate chain on top. // then generate chain on top.
func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) { func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
defer verkledb.Close()
triedb := triedb.NewDatabase(db, triedb.HashDefaults) triedb := triedb.NewDatabase(db, triedb.HashDefaults)
defer triedb.Close() defer triedb.Close()
_, err := genesis.Commit(db, triedb) _, err := genesis.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -478,7 +483,7 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int,
return db, blocks, receipts return db, blocks, receipts
} }
func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, trdb *triedb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) { func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, trdb, vdb *triedb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
if config == nil { if config == nil {
config = params.TestChainConfig config = params.TestChainConfig
} }
@ -536,7 +541,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
return block, b.receipts return block, b.receipts
} }
sdb := state.NewDatabase(trdb, nil) sdb := state.NewDatabase(trdb, vdb, nil)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
statedb, err := state.New(parent.Root(), sdb) statedb, err := state.New(parent.Root(), sdb)
@ -580,13 +585,14 @@ func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n
saveVerkleTransitionStatusAtVerlkeGenesis(db) saveVerkleTransitionStatusAtVerlkeGenesis(db)
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0 cacheConfig.SnapshotLimit = 0
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) verkledb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
triedb := triedb.NewDatabase(db, triedb.VerkleDefaults)
defer triedb.Close() defer triedb.Close()
genesisBlock, err := genesis.Commit(db, triedb) genesisBlock, err := genesis.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
panic(err) panic(err)
} }
blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen) blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, verkledb, n, gen)
return genesisBlock.Hash(), db, blocks, receipts, proofs, keyvals return genesisBlock.Hash(), db, blocks, receipts, proofs, keyvals
} }

View file

@ -75,7 +75,7 @@ func TestGeneratePOSChain(t *testing.T) {
Storage: storage, Storage: storage,
Code: common.Hex2Bytes("600154600354"), Code: common.Hex2Bytes("600154600354"),
} }
genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, triedb.HashDefaults)) genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, triedb.HashDefaults), triedb.NewDatabase(gendb, triedb.VerkleDefaults))
engine := beacon.New(ethash.NewFaker()) engine := beacon.New(ethash.NewFaker())
genchain, genreceipts := GenerateChain(gspec.Config, genesis, engine, gendb, 4, func(i int, gen *BlockGen) { genchain, genreceipts := GenerateChain(gspec.Config, genesis, engine, gendb, 4, func(i int, gen *BlockGen) {
@ -199,7 +199,7 @@ func ExampleGenerateChain() {
Config: &params.ChainConfig{HomesteadBlock: new(big.Int)}, Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
} }
genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, triedb.HashDefaults)) genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, triedb.HashDefaults), triedb.NewDatabase(genDb, triedb.VerkleDefaults))
// This call generates a chain of 5 blocks. The function runs for // This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the // each block and adds different features to gen based on the

View file

@ -39,7 +39,6 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-ethereum/triedb/pathdb"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -129,16 +128,7 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
// hashAlloc computes the state root according to the genesis specification. // hashAlloc computes the state root according to the genesis specification.
func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// If a genesis-time verkle trie is requested, create a trie config
// with the verkle trie enabled so that the tree can be initialized
// as such.
var config *triedb.Config
if isVerkle {
config = &triedb.Config{
PathDB: pathdb.Defaults,
IsVerkle: true,
}
}
// Create an ephemeral in-memory database for computing hash, // Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk. // all the derived states will be discarded to not pollute disk.
emptyRoot := types.EmptyRootHash emptyRoot := types.EmptyRootHash
@ -149,7 +139,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
if isVerkle { if isVerkle {
saveVerkleTransitionStatusAtVerlkeGenesis(db) saveVerkleTransitionStatusAtVerlkeGenesis(db)
} }
statedb, err := state.New(emptyRoot, state.NewDatabase(triedb.NewDatabase(db, config), nil)) statedb, err := state.New(emptyRoot, state.NewDatabase(triedb.NewDatabase(db, nil), triedb.NewDatabase(db, triedb.VerkleDefaults), nil))
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -168,12 +158,12 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// flushAlloc is very similar with hash, but the main difference is all the // flushAlloc is very similar with hash, but the main difference is all the
// generated states will be persisted into the given database. // generated states will be persisted into the given database.
func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) { func flushAlloc(ga *types.GenesisAlloc, triedb, verkledb *triedb.Database) (common.Hash, error) {
emptyRoot := types.EmptyRootHash emptyRoot := types.EmptyRootHash
if triedb.IsVerkle() { if triedb.IsVerkle() {
emptyRoot = types.EmptyVerkleHash emptyRoot = types.EmptyVerkleHash
} }
statedb, err := state.New(emptyRoot, state.NewDatabase(triedb, nil)) statedb, err := state.New(emptyRoot, state.NewDatabase(triedb, verkledb, nil))
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -309,11 +299,11 @@ func saveVerkleTransitionStatus(db ethdb.Database, root common.Hash, ts *state.T
// The stored chain configuration will be updated if it is compatible (i.e. does not // The stored chain configuration will be updated if it is compatible (i.e. does not
// specify a fork block below the local head block). In case of a conflict, the // specify a fork block below the local head block). In case of a conflict, the
// error is a *params.ConfigCompatError and the new, unwritten config is returned. // error is a *params.ConfigCompatError and the new, unwritten config is returned.
func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { func SetupGenesisBlock(db ethdb.Database, triedb, verkledb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlockWithOverride(db, triedb, genesis, nil) return SetupGenesisBlockWithOverride(db, triedb, verkledb, genesis, nil)
} }
func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { func SetupGenesisBlockWithOverride(db ethdb.Database, triedb, verkledb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// Copy the genesis, so we can operate on a copy. // Copy the genesis, so we can operate on a copy.
genesis = genesis.copy() genesis = genesis.copy()
// Sanitize the supplied genesis, ensuring it has the associated chain // Sanitize the supplied genesis, ensuring it has the associated chain
@ -339,7 +329,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
return nil, common.Hash{}, nil, err return nil, common.Hash{}, nil, err
} }
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
return nil, common.Hash{}, nil, err return nil, common.Hash{}, nil, err
} }
@ -367,7 +357,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
if hash := genesis.ToBlock().Hash(); hash != ghash { if hash := genesis.ToBlock().Hash(); hash != ghash {
return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash} return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
} }
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
return nil, common.Hash{}, nil, err return nil, common.Hash{}, nil, err
} }
@ -548,7 +538,7 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
// Commit writes the block and state of a genesis specification to the database. // Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) { func (g *Genesis) Commit(db ethdb.Database, triedb, verkledb *triedb.Database) (*types.Block, error) {
if g.Number != 0 { if g.Number != 0 {
return nil, errors.New("can't commit genesis block with number > 0") return nil, errors.New("can't commit genesis block with number > 0")
} }
@ -563,7 +553,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
return nil, errors.New("can't start clique chain without signers") return nil, errors.New("can't start clique chain without signers")
} }
// flush the data to disk and compute the state root // flush the data to disk and compute the state root
root, err := flushAlloc(&g.Alloc, triedb) root, err := flushAlloc(&g.Alloc, triedb, verkledb)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -591,8 +581,8 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
// MustCommit writes the genesis block and state to db, panicking on error. // MustCommit writes the genesis block and state to db, panicking on error.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.Block { func (g *Genesis) MustCommit(db ethdb.Database, triedb, verkledb *triedb.Database) *types.Block {
block, err := g.Commit(db, triedb) block, err := g.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -64,14 +64,14 @@ func testSetupGenesis(t *testing.T, scheme string) {
{ {
name: "genesis without ChainConfig", name: "genesis without ChainConfig",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis)) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), triedb.NewDatabase(db, triedb.VerkleDefaults), new(Genesis))
}, },
wantErr: errGenesisNoConfig, wantErr: errGenesisNoConfig,
}, },
{ {
name: "no block in DB, genesis == nil", name: "no block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), triedb.NewDatabase(db, triedb.VerkleDefaults), nil)
}, },
wantHash: params.MainnetGenesisHash, wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig, wantConfig: params.MainnetChainConfig,
@ -79,8 +79,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
{ {
name: "mainnet block in DB, genesis == nil", name: "mainnet block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme))) DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme)), triedb.NewDatabase(db, triedb.VerkleDefaults))
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), triedb.NewDatabase(db, triedb.VerkleDefaults), nil)
}, },
wantHash: params.MainnetGenesisHash, wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig, wantConfig: params.MainnetChainConfig,
@ -88,9 +88,10 @@ func testSetupGenesis(t *testing.T, scheme string) {
{ {
name: "custom block in DB, genesis == nil", name: "custom block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
vdb := triedb.NewDatabase(db, triedb.VerkleDefaults)
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb) customg.Commit(db, tdb, vdb)
return SetupGenesisBlock(db, tdb, nil) return SetupGenesisBlock(db, tdb, vdb, nil)
}, },
wantHash: customghash, wantHash: customghash,
wantConfig: customg.Config, wantConfig: customg.Config,
@ -98,18 +99,20 @@ func testSetupGenesis(t *testing.T, scheme string) {
{ {
name: "custom block in DB, genesis == sepolia", name: "custom block in DB, genesis == sepolia",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
vdb := triedb.NewDatabase(db, triedb.VerkleDefaults)
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb) customg.Commit(db, tdb, vdb)
return SetupGenesisBlock(db, tdb, DefaultSepoliaGenesisBlock()) return SetupGenesisBlock(db, tdb, vdb, DefaultSepoliaGenesisBlock())
}, },
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash}, wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
}, },
{ {
name: "custom block in DB, genesis == hoodi", name: "custom block in DB, genesis == hoodi",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
vdb := triedb.NewDatabase(db, triedb.VerkleDefaults)
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
customg.Commit(db, tdb) customg.Commit(db, tdb, vdb)
return SetupGenesisBlock(db, tdb, DefaultHoodiGenesisBlock()) return SetupGenesisBlock(db, tdb, vdb, DefaultHoodiGenesisBlock())
}, },
wantErr: &GenesisMismatchError{Stored: customghash, New: params.HoodiGenesisHash}, wantErr: &GenesisMismatchError{Stored: customghash, New: params.HoodiGenesisHash},
}, },
@ -117,8 +120,9 @@ func testSetupGenesis(t *testing.T, scheme string) {
name: "compatible config in DB", name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb) vdb := triedb.NewDatabase(db, triedb.VerkleDefaults)
return SetupGenesisBlock(db, tdb, &customg) oldcustomg.Commit(db, tdb, vdb)
return SetupGenesisBlock(db, tdb, vdb, &customg)
}, },
wantHash: customghash, wantHash: customghash,
wantConfig: customg.Config, wantConfig: customg.Config,
@ -128,8 +132,9 @@ func testSetupGenesis(t *testing.T, scheme string) {
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) { fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// Commit the 'old' genesis block with Homestead transition at #2. // Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg. // Advance to block #4, past the homestead transition block of customg.
vdb := triedb.NewDatabase(db, triedb.VerkleDefaults)
tdb := triedb.NewDatabase(db, newDbConfig(scheme)) tdb := triedb.NewDatabase(db, newDbConfig(scheme))
oldcustomg.Commit(db, tdb) oldcustomg.Commit(db, tdb, vdb)
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil) bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil)
defer bc.Stop() defer bc.Stop()
@ -138,7 +143,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
bc.InsertChain(blocks) bc.InsertChain(blocks)
// This should return a compatibility error. // This should return a compatibility error.
return SetupGenesisBlock(db, tdb, &customg) return SetupGenesisBlock(db, tdb, vdb, &customg)
}, },
wantHash: customghash, wantHash: customghash,
wantConfig: customg.Config, wantConfig: customg.Config,
@ -192,7 +197,7 @@ func TestGenesisHashes(t *testing.T) {
} { } {
// Test via MustCommit // Test via MustCommit
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want { if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults), triedb.NewDatabase(db, triedb.VerkleDefaults)).Hash(); have != c.want {
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
} }
// Test via ToBlock // Test via ToBlock
@ -210,7 +215,7 @@ func TestGenesisCommit(t *testing.T) {
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults), triedb.NewDatabase(db, triedb.VerkleDefaults))
if genesis.Difficulty != nil { if genesis.Difficulty != nil {
t.Fatalf("assumption wrong") t.Fatalf("assumption wrong")
@ -314,8 +319,9 @@ func TestVerkleGenesisCommit(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
saveVerkleTransitionStatusAtVerlkeGenesis(db) saveVerkleTransitionStatusAtVerlkeGenesis(db)
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, triedb.VerkleDefaults) triedb := triedb.NewDatabase(db, triedb.VerkleDefaults)
block := genesis.MustCommit(db, triedb) block := genesis.MustCommit(db, triedb, verkledb)
if !bytes.Equal(block.Root().Bytes(), expected) { if !bytes.Equal(block.Root().Bytes(), expected) {
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root()) t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root())
} }

View file

@ -69,7 +69,7 @@ func TestHeaderInsertion(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges} gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges}
) )
gspec.Commit(db, triedb.NewDatabase(db, nil)) gspec.Commit(db, triedb.NewDatabase(db, nil), triedb.NewDatabase(db, triedb.VerkleDefaults))
hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false }) hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -201,6 +201,7 @@ func (ts *TransitionState) Copy() *TransitionState {
type CachingDB struct { type CachingDB struct {
disk ethdb.KeyValueStore disk ethdb.KeyValueStore
triedb *triedb.Database triedb *triedb.Database
verkledb *triedb.Database
snap *snapshot.Tree snap *snapshot.Tree
codeCache *lru.SizeConstrainedCache[common.Hash, []byte] codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
codeSizeCache *lru.Cache[common.Hash, int] codeSizeCache *lru.Cache[common.Hash, int]
@ -211,10 +212,11 @@ type CachingDB struct {
} }
// NewDatabase creates a state database with the provided data sources. // NewDatabase creates a state database with the provided data sources.
func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB { func NewDatabase(triedb, verkledb *triedb.Database, snap *snapshot.Tree) *CachingDB {
return &CachingDB{ return &CachingDB{
disk: triedb.Disk(), disk: triedb.Disk(),
triedb: triedb, triedb: triedb,
verkledb: verkledb,
snap: snap, snap: snap,
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
@ -226,7 +228,8 @@ func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
// NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching // NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching
// db by using an ephemeral memory db with default config for testing. // db by using an ephemeral memory db with default config for testing.
func NewDatabaseForTesting() *CachingDB { func NewDatabaseForTesting() *CachingDB {
return NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil) memdb := rawdb.NewMemoryDatabase()
return NewDatabase(triedb.NewDatabase(memdb, nil), triedb.NewDatabase(memdb, triedb.VerkleDefaults), nil)
} }
// Reader returns a state reader associated with the specified state root. // Reader returns a state reader associated with the specified state root.
@ -274,7 +277,7 @@ func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
panic("transition isn't supported yet") panic("transition isn't supported yet")
} }
if ts.Transitioned() { if ts.Transitioned() {
return trie.NewVerkleTrie(root, db.triedb, db.pointCache) return trie.NewVerkleTrie(root, db.verkledb, db.pointCache)
} }
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil { if err != nil {

View file

@ -40,8 +40,9 @@ func newStateEnv() *stateEnv {
func TestDump(t *testing.T) { func TestDump(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
tdb := NewDatabase(triedb, nil) tdb := NewDatabase(triedb, verkledb, nil)
sdb, _ := New(types.EmptyRootHash, tdb) sdb, _ := New(types.EmptyRootHash, tdb)
s := &stateEnv{state: sdb} s := &stateEnv{state: sdb}
@ -98,8 +99,9 @@ func TestDump(t *testing.T) {
func TestIterativeDump(t *testing.T) { func TestIterativeDump(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true}) triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
tdb := NewDatabase(triedb, nil) tdb := NewDatabase(triedb, verkledb, nil)
sdb, _ := New(types.EmptyRootHash, tdb) sdb, _ := New(types.EmptyRootHash, tdb)
s := &stateEnv{state: sdb} s := &stateEnv{state: sdb}

View file

@ -788,7 +788,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
start = time.Now() start = time.Now()
workers errgroup.Group workers errgroup.Group
) )
if s.db.TrieDB().IsVerkle() { if s.GetTrie().IsVerkle() {
// Whilst MPT storage tries are independent, Verkle has one single trie // Whilst MPT storage tries are independent, Verkle has one single trie
// for all the accounts and all the storage slots merged together. The // for all the accounts and all the storage slots merged together. The
// former can thus be simply parallelized, but updating the latter will // former can thus be simply parallelized, but updating the latter will
@ -802,7 +802,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
} }
obj := s.stateObjects[addr] // closure for the task runner below obj := s.stateObjects[addr] // closure for the task runner below
workers.Go(func() error { workers.Go(func() error {
if s.db.TrieDB().IsVerkle() { if s.GetTrie().IsVerkle() {
obj.updateTrie() obj.updateTrie()
} else { } else {
obj.updateRoot() obj.updateRoot()
@ -819,7 +819,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
// If witness building is enabled, gather all the read-only accesses. // If witness building is enabled, gather all the read-only accesses.
// Skip witness collection in Verkle mode, they will be gathered // Skip witness collection in Verkle mode, they will be gathered
// together at the end. // together at the end.
if s.witness != nil && !s.db.TrieDB().IsVerkle() { if s.witness != nil && !s.GetTrie().IsVerkle() {
// Pull in anything that has been accessed before destruction // Pull in anything that has been accessed before destruction
for _, obj := range s.stateObjectsDestruct { for _, obj := range s.stateObjectsDestruct {
// Skip any objects that haven't touched their storage // Skip any objects that haven't touched their storage

View file

@ -189,6 +189,7 @@ func (test *stateTest) run() bool {
storageOrigin = append(storageOrigin, maps.Clone(update.storagesOrigin)) storageOrigin = append(storageOrigin, maps.Clone(update.storagesOrigin))
} }
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
vdb = triedb.NewDatabase(disk, triedb.VerkleDefaults)
tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults}) tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults})
byzantium = rand.Intn(2) == 0 byzantium = rand.Intn(2) == 0
) )
@ -209,7 +210,7 @@ func (test *stateTest) run() bool {
if i != 0 { if i != 0 {
root = roots[len(roots)-1] root = roots[len(roots)-1]
} }
state, err := New(root, NewDatabase(tdb, snaps)) state, err := New(root, NewDatabase(tdb, vdb, snaps))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -52,7 +52,8 @@ func TestUpdateLeaks(t *testing.T) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(db, nil) tdb = triedb.NewDatabase(db, nil)
sdb = NewDatabase(tdb, nil) vdb = triedb.NewDatabase(db, triedb.VerkleDefaults)
sdb = NewDatabase(tdb, vdb, nil)
) )
state, _ := New(types.EmptyRootHash, sdb) state, _ := New(types.EmptyRootHash, sdb)
@ -89,9 +90,11 @@ func TestIntermediateLeaks(t *testing.T) {
transDb := rawdb.NewMemoryDatabase() transDb := rawdb.NewMemoryDatabase()
finalDb := rawdb.NewMemoryDatabase() finalDb := rawdb.NewMemoryDatabase()
transNdb := triedb.NewDatabase(transDb, nil) transNdb := triedb.NewDatabase(transDb, nil)
transVdb := triedb.NewDatabase(transDb, triedb.VerkleDefaults)
finalNdb := triedb.NewDatabase(finalDb, nil) finalNdb := triedb.NewDatabase(finalDb, nil)
transState, _ := New(types.EmptyRootHash, NewDatabase(transNdb, nil)) finalVdb := triedb.NewDatabase(finalDb, triedb.VerkleDefaults)
finalState, _ := New(types.EmptyRootHash, NewDatabase(finalNdb, nil)) transState, _ := New(types.EmptyRootHash, NewDatabase(transNdb, transVdb, nil))
finalState, _ := New(types.EmptyRootHash, NewDatabase(finalNdb, finalVdb, nil))
modify := func(state *StateDB, addr common.Address, i, tweak byte) { modify := func(state *StateDB, addr common.Address, i, tweak byte) {
state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified) state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified)
@ -987,7 +990,8 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
CleanCacheSize: 0, CleanCacheSize: 0,
}}) // disable caching }}) // disable caching
} }
db := NewDatabase(tdb, nil) vdb := triedb.NewDatabase(memDb, triedb.VerkleDefaults)
db := NewDatabase(tdb, vdb, nil)
var root common.Hash var root common.Hash
state, _ := New(types.EmptyRootHash, db) state, _ := New(types.EmptyRootHash, db)
@ -1204,7 +1208,8 @@ func TestFlushOrderDataLoss(t *testing.T) {
var ( var (
memdb = rawdb.NewMemoryDatabase() memdb = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(memdb, triedb.HashDefaults) tdb = triedb.NewDatabase(memdb, triedb.HashDefaults)
statedb = NewDatabase(tdb, nil) vdb = triedb.NewDatabase(memdb, triedb.VerkleDefaults)
statedb = NewDatabase(tdb, vdb, nil)
state, _ = New(types.EmptyRootHash, statedb) state, _ = New(types.EmptyRootHash, statedb)
) )
for a := byte(0); a < 10; a++ { for a := byte(0); a < 10; a++ {
@ -1225,7 +1230,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
t.Fatalf("failed to commit state trie: %v", err) t.Fatalf("failed to commit state trie: %v", err)
} }
// Reopen the state trie from flushed disk and verify it // Reopen the state trie from flushed disk and verify it
state, err = New(root, NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), nil)) state, err = New(root, NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), triedb.NewDatabase(memdb, triedb.VerkleDefaults), nil))
if err != nil { if err != nil {
t.Fatalf("failed to reopen state trie: %v", err) t.Fatalf("failed to reopen state trie: %v", err)
} }
@ -1275,8 +1280,9 @@ func TestDeleteStorage(t *testing.T) {
var ( var (
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(disk, nil) tdb = triedb.NewDatabase(disk, nil)
vdb = triedb.NewDatabase(disk, triedb.VerkleDefaults)
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
db = NewDatabase(tdb, snaps) db = NewDatabase(tdb, vdb, snaps)
state, _ = New(types.EmptyRootHash, db) state, _ = New(types.EmptyRootHash, db)
addr = common.HexToAddress("0x1") addr = common.HexToAddress("0x1")
) )
@ -1290,8 +1296,8 @@ func TestDeleteStorage(t *testing.T) {
} }
root, _ := state.Commit(0, true, false) root, _ := state.Commit(0, true, false)
// Init phase done, create two states, one with snap and one without // Init phase done, create two states, one with snap and one without
fastState, _ := New(root, NewDatabase(tdb, snaps)) fastState, _ := New(root, NewDatabase(tdb, vdb, snaps))
slowState, _ := New(root, NewDatabase(tdb, nil)) slowState, _ := New(root, NewDatabase(tdb, vdb, nil))
obj := fastState.getOrNewStateObject(addr) obj := fastState.getOrNewStateObject(addr)
storageRoot := obj.data.Root storageRoot := obj.data.Root
@ -1329,7 +1335,8 @@ func TestStorageDirtiness(t *testing.T) {
var ( var (
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(disk, nil) tdb = triedb.NewDatabase(disk, nil)
db = NewDatabase(tdb, nil) vdb = triedb.NewDatabase(disk, triedb.VerkleDefaults)
db = NewDatabase(tdb, vdb, nil)
state, _ = New(types.EmptyRootHash, db) state, _ = New(types.EmptyRootHash, db)
addr = common.HexToAddress("0x1") addr = common.HexToAddress("0x1")
checkDirty = func(key common.Hash, value common.Hash, dirty bool) { checkDirty = func(key common.Hash, value common.Hash, dirty bool) {

View file

@ -52,7 +52,8 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
nodeDb := triedb.NewDatabase(db, config) nodeDb := triedb.NewDatabase(db, config)
sdb := NewDatabase(nodeDb, nil) verkleNodedb := triedb.NewDatabase(db, triedb.VerkleDefaults)
sdb := NewDatabase(nodeDb, verkleNodedb, nil)
state, _ := New(types.EmptyRootHash, sdb) state, _ := New(types.EmptyRootHash, sdb)
// Fill it with some arbitrary data // Fill it with some arbitrary data
@ -93,7 +94,7 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root com
config.PathDB = pathdb.Defaults config.PathDB = pathdb.Defaults
} }
// Check root availability and state contents // Check root availability and state contents
state, err := New(root, NewDatabase(triedb.NewDatabase(db, &config), nil)) state, err := New(root, NewDatabase(triedb.NewDatabase(db, &config), triedb.NewDatabase(db, triedb.VerkleDefaults), nil))
if err != nil { if err != nil {
t.Fatalf("failed to create state trie at %x: %v", root, err) t.Fatalf("failed to create state trie at %x: %v", root, err)
} }
@ -119,7 +120,7 @@ func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) e
if scheme == rawdb.PathScheme { if scheme == rawdb.PathScheme {
config.PathDB = pathdb.Defaults config.PathDB = pathdb.Defaults
} }
state, err := New(root, NewDatabase(triedb.NewDatabase(db, config), nil)) state, err := New(root, NewDatabase(triedb.NewDatabase(db, config), triedb.NewDatabase(db, triedb.VerkleDefaults), nil))
if err != nil { if err != nil {
return err return err
} }

View file

@ -68,8 +68,9 @@ func TestUseAfterTerminate(t *testing.T) {
func TestVerklePrefetcher(t *testing.T) { func TestVerklePrefetcher(t *testing.T) {
disk := rawdb.NewMemoryDatabase() disk := rawdb.NewMemoryDatabase()
db := triedb.NewDatabase(disk, triedb.VerkleDefaults) tdb := triedb.NewDatabase(disk, nil)
sdb := NewDatabase(db, nil) vdb := triedb.NewDatabase(disk, triedb.VerkleDefaults)
sdb := NewDatabase(tdb, vdb, nil)
state, err := New(types.EmptyRootHash, sdb) state, err := New(types.EmptyRootHash, sdb)
if err != nil { if err != nil {

View file

@ -51,7 +51,7 @@ func ExecuteStateless(config *params.ChainConfig, vmconfig vm.Config, block *typ
} }
// Create and populate the state database to serve as the stateless backend // Create and populate the state database to serve as the stateless backend
memdb := witness.MakeHashDB() memdb := witness.MakeHashDB()
db, err := state.New(witness.Root(), state.NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), nil)) db, err := state.New(witness.Root(), state.NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), triedb.NewDatabase(memdb, triedb.VerkleDefaults), nil))
if err != nil { if err != nil {
return common.Hash{}, common.Hash{}, err return common.Hash{}, common.Hash{}, err
} }

View file

@ -259,8 +259,9 @@ func TestProcessParentBlockHash(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0 cacheConfig.SnapshotLimit = 0
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil)) statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, verkledb, nil))
checkBlockHashes(statedb, true) checkBlockHashes(statedb, true)
}) })
} }

View file

@ -65,7 +65,7 @@ func TestAccountRange(t *testing.T) {
var ( var (
mdb = rawdb.NewMemoryDatabase() mdb = rawdb.NewMemoryDatabase()
statedb = state.NewDatabase(triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}), nil) statedb = state.NewDatabase(triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}), triedb.NewDatabase(mdb, triedb.VerkleDefaults), nil)
sdb, _ = state.New(types.EmptyRootHash, statedb) sdb, _ = state.New(types.EmptyRootHash, statedb)
addrs = [AccountRangeMaxResults * 2]common.Address{} addrs = [AccountRangeMaxResults * 2]common.Address{}
m = map[common.Address]bool{} m = map[common.Address]bool{}
@ -164,7 +164,8 @@ func TestStorageRangeAt(t *testing.T) {
var ( var (
mdb = rawdb.NewMemoryDatabase() mdb = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}) tdb = triedb.NewDatabase(mdb, &triedb.Config{Preimages: true})
db = state.NewDatabase(tdb, nil) vdb = triedb.NewDatabase(mdb, triedb.VerkleDefaults)
db = state.NewDatabase(tdb, vdb, nil)
sdb, _ = state.New(types.EmptyRootHash, db) sdb, _ = state.New(types.EmptyRootHash, db)
addr = common.Address{0x01} addr = common.Address{0x01}
keys = []common.Hash{ // hashes of Keys of storage keys = []common.Hash{ // hashes of Keys of storage

View file

@ -44,7 +44,7 @@ var (
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
} }
testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults)) testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults), triedb.NewDatabase(testDB, triedb.VerkleDefaults))
) )
// The common prefix of all test chains: // The common prefix of all test chains:

View file

@ -99,7 +99,7 @@ func benchmarkFilters(b *testing.B, history uint64, noHistory bool) {
// The test txs are not properly signed, can't simply create a chain // The test txs are not properly signed, can't simply create a chain
// and then import blocks. TODO(rjl493456442) try to get rid of the // and then import blocks. TODO(rjl493456442) try to get rid of the
// manual database writes. // manual database writes.
gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults), triedb.NewDatabase(db, triedb.VerkleDefaults))
for i, block := range chain { for i, block := range chain {
rawdb.WriteBlock(db, block) rawdb.WriteBlock(db, block)
@ -209,7 +209,7 @@ func testFilters(t *testing.T, history uint64, noHistory bool) {
// Hack: GenerateChainWithGenesis creates a new db. // Hack: GenerateChainWithGenesis creates a new db.
// Commit the genesis manually and use GenerateChain. // Commit the genesis manually and use GenerateChain.
_, err = gspec.Commit(db, triedb.NewDatabase(db, nil)) _, err = gspec.Commit(db, triedb.NewDatabase(db, nil), triedb.NewDatabase(db, triedb.VerkleDefaults))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -429,7 +429,7 @@ func TestRangeLogs(t *testing.T) {
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
} }
) )
_, err := gspec.Commit(db, triedb.NewDatabase(db, nil)) _, err := gspec.Commit(db, triedb.NewDatabase(db, nil), triedb.NewDatabase(db, triedb.VerkleDefaults))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -68,8 +68,9 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk. // the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak, // TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance. // please re-enable it for better performance.
vdb := triedb.NewDatabase(eth.chainDb, triedb.VerkleDefaults)
tdb := triedb.NewDatabase(eth.chainDb, triedb.HashDefaults) tdb := triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
database = state.NewDatabase(tdb, nil) database = state.NewDatabase(tdb, vdb, nil)
if statedb, err = state.New(block.Root(), database); err == nil { if statedb, err = state.New(block.Root(), database); err == nil {
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
return statedb, noopReleaser, nil return statedb, noopReleaser, nil
@ -86,8 +87,9 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk. // the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak, // TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance. // please re-enable it for better performance.
vdb := triedb.NewDatabase(eth.chainDb, triedb.VerkleDefaults)
tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults) tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
database = state.NewDatabase(tdb, nil) database = state.NewDatabase(tdb, vdb, nil)
// If we didn't check the live database, do check state over ephemeral database, // If we didn't check the live database, do check state over ephemeral database,
// otherwise we would rewind past a persisted block (specific corner case is // otherwise we would rewind past a persisted block (specific corner case is

View file

@ -36,7 +36,8 @@ func (p *precompileContract) RequiredGas(input []byte) uint64 { return 0 }
func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil } func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil }
func TestStateOverrideMovePrecompile(t *testing.T) { func TestStateOverrideMovePrecompile(t *testing.T) {
db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil) memdb := rawdb.NewMemoryDatabase()
db := state.NewDatabase(triedb.NewDatabase(memdb, nil), triedb.NewDatabase(memdb, triedb.VerkleDefaults), nil)
statedb, err := state.New(types.EmptyRootHash, db) statedb, err := state.New(types.EmptyRootHash, db)
if err != nil { if err != nil {
t.Fatalf("failed to create statedb: %v", err) t.Fatalf("failed to create statedb: %v", err)

View file

@ -143,9 +143,10 @@ func createMiner(t *testing.T) *Miner {
} }
// Create chainConfig // Create chainConfig
chainDB := rawdb.NewMemoryDatabase() chainDB := rawdb.NewMemoryDatabase()
verkledb := triedb.NewDatabase(chainDB, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(chainDB, nil) triedb := triedb.NewDatabase(chainDB, nil)
genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345")) genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345"))
chainConfig, _, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis) chainConfig, _, _, err := core.SetupGenesisBlock(chainDB, triedb, verkledb, genesis)
if err != nil { if err != nil {
t.Fatalf("can't create new chain config: %v", err) t.Fatalf("can't create new chain config: %v", err)
} }

View file

@ -135,8 +135,9 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
if gspec.Config.TerminalTotalDifficulty == nil { if gspec.Config.TerminalTotalDifficulty == nil {
gspec.Config.TerminalTotalDifficulty = big.NewInt(stdmath.MaxInt64) gspec.Config.TerminalTotalDifficulty = big.NewInt(stdmath.MaxInt64)
} }
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, tconf) triedb := triedb.NewDatabase(db, tconf)
gblock, err := gspec.Commit(db, triedb) gblock, err := gspec.Commit(db, triedb, verkledb)
if err != nil { if err != nil {
return err return err
} }

View file

@ -496,6 +496,7 @@ func vmTestBlockHash(n uint64) common.Hash {
type StateTestState struct { type StateTestState struct {
StateDB *state.StateDB StateDB *state.StateDB
TrieDB *triedb.Database TrieDB *triedb.Database
VerkleDB *triedb.Database
Snapshots *snapshot.Tree Snapshots *snapshot.Tree
} }
@ -507,8 +508,9 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
} else { } else {
tconf.PathDB = pathdb.Defaults tconf.PathDB = pathdb.Defaults
} }
verkledb := triedb.NewDatabase(db, triedb.VerkleDefaults)
triedb := triedb.NewDatabase(db, tconf) triedb := triedb.NewDatabase(db, tconf)
sdb := state.NewDatabase(triedb, nil) sdb := state.NewDatabase(triedb, verkledb, nil)
statedb, _ := state.New(types.EmptyRootHash, sdb) statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) statedb.SetCode(addr, a.Code)
@ -532,9 +534,9 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
} }
snaps, _ = snapshot.New(snapconfig, db, triedb, root) snaps, _ = snapshot.New(snapconfig, db, triedb, root)
} }
sdb = state.NewDatabase(triedb, snaps) sdb = state.NewDatabase(triedb, verkledb, snaps)
statedb, _ = state.New(root, sdb) statedb, _ = state.New(root, sdb)
return StateTestState{statedb, triedb, snaps} return StateTestState{statedb, triedb, verkledb, snaps}
} }
// Close should be called when the state is no longer needed, ie. after running the test. // Close should be called when the state is no longer needed, ie. after running the test.