cmd, core, trie, triedb: split CachingDB into merkle + binary dbs. (#34700)

This Pr implements some prerequisite changes for #34004 : split the
`CachingDB` into a `MerkleDB` and a `UBTDB`, so that very different
behaviors don't clash as much.

The transition isn't handled by this PR, but after talking to Gary we
agreed that `UBTDB` should receive another `triedb`, which will only be
loaded if the `Ended` flag is set to false in the conversion contract.
If this is too hard to achieve, it makes sense to load it regardless,
and then loading can be prevented at a later stage by adding a
`UBTTransitionFinalizationTime` in `ChainConfig`.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
Guillaume Ballet 2026-04-17 02:55:54 +02:00 committed by GitHub
parent f63e9f3a80
commit ba215fd927
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 703 additions and 463 deletions

View file

@ -146,7 +146,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return h return h
} }
var ( var (
isEIP4762 = chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) isEIP4762 = chainConfig.IsUBT(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre, isEIP4762) statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre, isEIP4762)
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
gaspool = core.NewGasPool(pre.Env.GasLimit) gaspool = core.NewGasPool(pre.Env.GasLimit)
@ -378,7 +378,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, isBintrie bool) *state.StateDB { func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, isBintrie bool) *state.StateDB {
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true, IsVerkle: isBintrie}) tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true, IsUBT: isBintrie})
sdb := state.NewDatabase(tdb, nil) sdb := state.NewDatabase(tdb, nil)
root := types.EmptyRootHash root := types.EmptyRootHash

View file

@ -228,7 +228,7 @@ func Transition(ctx *cli.Context) error {
collector = make(Alloc) collector = make(Alloc)
btleaves map[common.Hash]hexutil.Bytes btleaves map[common.Hash]hexutil.Bytes
) )
isBinary := chainConfig.IsVerkle(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) isBinary := chainConfig.IsUBT(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
if !isBinary { if !isBinary {
s.DumpToCollector(collector, nil) s.DumpToCollector(collector, nil)
} else { } else {
@ -452,7 +452,7 @@ func BinKeys(ctx *cli.Context) error {
return err return err
} }
} }
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.VerkleDefaults) db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
defer db.Close() defer db.Close()
bt, err := genBinTrieFromAlloc(alloc, db) bt, err := genBinTrieFromAlloc(alloc, db)
@ -496,7 +496,7 @@ func BinTrieRoot(ctx *cli.Context) error {
return err return err
} }
} }
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.VerkleDefaults) db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
defer db.Close() defer db.Close()
bt, err := genBinTrieFromAlloc(alloc, db) bt, err := genBinTrieFromAlloc(alloc, db)

View file

@ -144,7 +144,7 @@ func convertToBinaryTrie(ctx *cli.Context) error {
defer srcTriedb.Close() defer srcTriedb.Close()
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{ destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
IsVerkle: true, IsUBT: true,
PathDB: &pathdb.Config{ PathDB: &pathdb.Config{
JournalDirectory: stack.ResolvePath("triedb-bintrie"), JournalDirectory: stack.ResolvePath("triedb-bintrie"),
}, },

View file

@ -82,8 +82,8 @@ func TestBintrieConvert(t *testing.T) {
defer srcTriedb2.Close() defer srcTriedb2.Close()
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{ destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
IsVerkle: true, IsUBT: true,
PathDB: pathdb.Defaults, PathDB: pathdb.Defaults,
}) })
defer destTriedb.Close() defer destTriedb.Close()
@ -190,8 +190,8 @@ func TestBintrieConvertDeleteSource(t *testing.T) {
}) })
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{ destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
IsVerkle: true, IsUBT: true,
PathDB: pathdb.Defaults, PathDB: pathdb.Defaults,
}) })
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, destTriedb) bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, destTriedb)

View file

@ -64,7 +64,7 @@ var (
utils.OverrideOsaka, utils.OverrideOsaka,
utils.OverrideBPO1, utils.OverrideBPO1,
utils.OverrideBPO2, utils.OverrideBPO2,
utils.OverrideVerkle, utils.OverrideUBT,
}, utils.DatabaseFlags), }, utils.DatabaseFlags),
Description: ` Description: `
The init command initializes a new genesis block and definition for the network. The init command initializes a new genesis block and definition for the network.
@ -297,15 +297,15 @@ func initGenesis(ctx *cli.Context) error {
v := ctx.Uint64(utils.OverrideBPO2.Name) v := ctx.Uint64(utils.OverrideBPO2.Name)
overrides.OverrideBPO2 = &v overrides.OverrideBPO2 = &v
} }
if ctx.IsSet(utils.OverrideVerkle.Name) { if ctx.IsSet(utils.OverrideUBT.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideUBT.Name)
overrides.OverrideVerkle = &v overrides.OverrideUBT = &v
} }
chaindb := utils.MakeChainDatabase(ctx, stack, false) chaindb := utils.MakeChainDatabase(ctx, stack, false)
defer chaindb.Close() defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsUBT())
defer triedb.Close() defer triedb.Close()
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides, nil) _, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides, nil)

View file

@ -235,9 +235,9 @@ func makeFullNode(ctx *cli.Context) *node.Node {
v := ctx.Uint64(utils.OverrideBPO2.Name) v := ctx.Uint64(utils.OverrideBPO2.Name)
cfg.Eth.OverrideBPO2 = &v cfg.Eth.OverrideBPO2 = &v
} }
if ctx.IsSet(utils.OverrideVerkle.Name) { if ctx.IsSet(utils.OverrideUBT.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideUBT.Name)
cfg.Eth.OverrideVerkle = &v cfg.Eth.OverrideUBT = &v
} }
// Start metrics export if enabled. // Start metrics export if enabled.

View file

@ -64,7 +64,7 @@ var (
utils.OverrideOsaka, utils.OverrideOsaka,
utils.OverrideBPO1, utils.OverrideBPO1,
utils.OverrideBPO2, utils.OverrideBPO2,
utils.OverrideVerkle, utils.OverrideUBT,
utils.OverrideGenesisFlag, utils.OverrideGenesisFlag,
utils.EnablePersonal, // deprecated utils.EnablePersonal, // deprecated
utils.TxPoolLocalsFlag, utils.TxPoolLocalsFlag,

View file

@ -264,9 +264,9 @@ var (
Usage: "Manually specify the bpo2 fork timestamp, overriding the bundled setting", Usage: "Manually specify the bpo2 fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideVerkle = &cli.Uint64Flag{ OverrideUBT = &cli.Uint64Flag{
Name: "override.verkle", Name: "override.ubt",
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Usage: "Manually specify the UBT fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideGenesisFlag = &cli.StringFlag{ OverrideGenesisFlag = &cli.StringFlag{
@ -2516,10 +2516,10 @@ 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, stack *node.Node, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database { func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, preimage bool, readOnly bool, isUBT bool) *triedb.Database {
config := &triedb.Config{ config := &triedb.Config{
Preimages: preimage, Preimages: preimage,
IsVerkle: isVerkle, IsUBT: isUBT,
} }
scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk) scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk)
if err != nil { if err != nil {

View file

@ -36,7 +36,7 @@ import (
) )
var ( var (
testVerkleChainConfig = &params.ChainConfig{ testUBTChainConfig = &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
@ -51,16 +51,16 @@ var (
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
Ethash: new(params.EthashConfig), Ethash: new(params.EthashConfig),
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
VerkleTime: u64(0), UBTTime: u64(0),
TerminalTotalDifficulty: common.Big0, TerminalTotalDifficulty: common.Big0,
EnableVerkleAtGenesis: true, EnableUBTAtGenesis: true,
BlobScheduleConfig: &params.BlobScheduleConfig{ BlobScheduleConfig: &params.BlobScheduleConfig{
Verkle: params.DefaultPragueBlobConfig, UBT: params.DefaultPragueBlobConfig,
}, },
} }
) )
func TestProcessVerkle(t *testing.T) { func TestProcessUBT(t *testing.T) {
var ( var (
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`) code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, true, true, true, true) intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, true, true, true, true)
@ -69,12 +69,12 @@ func TestProcessVerkle(t *testing.T) {
// Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985 // Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`) codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, true, true, true) intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, true, true, true)
signer = types.LatestSigner(testVerkleChainConfig) signer = types.LatestSigner(testUBTChainConfig)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
gspec = &Genesis{ gspec = &Genesis{
Config: testVerkleChainConfig, Config: testUBTChainConfig,
Alloc: GenesisAlloc{ Alloc: GenesisAlloc{
coinbase: { coinbase: {
Balance: big.NewInt(1000000000000000000), // 1 ether Balance: big.NewInt(1000000000000000000), // 1 ether
@ -87,7 +87,7 @@ func TestProcessVerkle(t *testing.T) {
}, },
} }
) )
// Verkle trees use the snapshot, which must be enabled before the // UBTs use the snapshot, which must be enabled before the
// data is saved into the tree+database. // data is saved into the tree+database.
// genesis := gspec.MustCommit(bcdb, triedb) // genesis := gspec.MustCommit(bcdb, triedb)
options := DefaultConfig().WithStateScheme(rawdb.PathScheme) options := DefaultConfig().WithStateScheme(rawdb.PathScheme)
@ -188,7 +188,7 @@ func TestProcessParentBlockHash(t *testing.T) {
// block 1 parent hash is 0x0100.... // block 1 parent hash is 0x0100....
// block 2 parent hash is 0x0200.... // block 2 parent hash is 0x0200....
// etc // etc
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) { checkBlockHashes := func(statedb *state.StateDB, isUBT bool) {
statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified) statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified)
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode, tracing.CodeChangeUnspecified) statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode, tracing.CodeChangeUnspecified)
// Process n blocks, from 1 .. num // Process n blocks, from 1 .. num
@ -196,8 +196,8 @@ func TestProcessParentBlockHash(t *testing.T) {
for i := 1; i <= num; i++ { for i := 1; i <= num; i++ {
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)} header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
chainConfig := params.MergedTestChainConfig chainConfig := params.MergedTestChainConfig
if isVerkle { if isUBT {
chainConfig = testVerkleChainConfig chainConfig = testUBTChainConfig
} }
vmContext := NewEVMBlockContext(header, nil, new(common.Address)) vmContext := NewEVMBlockContext(header, nil, new(common.Address))
evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{}) evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{})
@ -205,9 +205,9 @@ func TestProcessParentBlockHash(t *testing.T) {
} }
// Read block hashes for block 0 .. num-1 // Read block hashes for block 0 .. num-1
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
have, want := getContractStoredBlockHash(statedb, uint64(i), isVerkle), common.Hash{byte(i + 1)} have, want := getContractStoredBlockHash(statedb, uint64(i), isUBT), common.Hash{byte(i + 1)}
if have != want { if have != want {
t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isVerkle, have, want) t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isUBT, have, want)
} }
} }
} }
@ -215,22 +215,22 @@ func TestProcessParentBlockHash(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
checkBlockHashes(statedb, false) checkBlockHashes(statedb, false)
}) })
t.Run("Verkle", func(t *testing.T) { t.Run("UBT", func(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme) cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0 cacheConfig.SnapshotLimit = 0
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.EmptyBinaryHash, state.NewDatabase(triedb, nil))
checkBlockHashes(statedb, true) checkBlockHashes(statedb, true)
}) })
} }
// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number' // getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isVerkle bool) common.Hash { func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isUBT bool) common.Hash {
ringIndex := number % params.HistoryServeWindow ringIndex := number % params.HistoryServeWindow
var key common.Hash var key common.Hash
binary.BigEndian.PutUint64(key[24:], ringIndex) binary.BigEndian.PutUint64(key[24:], ringIndex)
if isVerkle { if isUBT {
return statedb.GetState(params.HistoryStorageAddress, key) return statedb.GetState(params.HistoryStorageAddress, key)
} }
return statedb.GetState(params.HistoryStorageAddress, key) return statedb.GetState(params.HistoryStorageAddress, key)

View file

@ -258,10 +258,10 @@ func (cfg BlockChainConfig) WithNoAsyncFlush(on bool) *BlockChainConfig {
} }
// triedbConfig derives the configures for trie database. // triedbConfig derives the configures for trie database.
func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config { func (cfg *BlockChainConfig) triedbConfig(isUBT bool) *triedb.Config {
config := &triedb.Config{ config := &triedb.Config{
Preimages: cfg.Preimages, Preimages: cfg.Preimages,
IsVerkle: isVerkle, IsUBT: isUBT,
} }
if cfg.StateScheme == rawdb.HashScheme { if cfg.StateScheme == rawdb.HashScheme {
config.HashDB = &hashdb.Config{ config.HashDB = &hashdb.Config{
@ -378,7 +378,7 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
} }
// Open trie database with provided config // Open trie database with provided config
enableVerkle, err := EnableVerkleAtGenesis(db, genesis) enableVerkle, err := EnableUBTAtGenesis(db, genesis)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2116,11 +2116,29 @@ func (bc *BlockChain) ProcessBlock(ctx context.Context, parentRoot common.Hash,
startTime = time.Now() startTime = time.Now()
statedb *state.StateDB statedb *state.StateDB
interrupt atomic.Bool interrupt atomic.Bool
sdb = state.NewDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps) sdb state.Database
) )
defer interrupt.Store(true) // terminate the prefetch at the end defer interrupt.Store(true) // terminate the prefetch at the end
if bc.cfg.NoPrefetch { if bc.chainConfig.IsUBT(block.Number(), block.Time()) {
sdb = state.NewUBTDatabase(bc.triedb, bc.codedb)
} else {
sdb = state.NewMPTDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps)
}
// If prefetching is enabled, run that against the current state to pre-cache
// transactions and probabilistically some of the account/storage trie nodes.
//
// Note: the main processor and prefetcher share the same reader with a local
// cache for mitigating the overhead of state access.
type prewarmReader interface {
// ReadersWithCacheStats creates a pair of state readers that share the
// same underlying state reader and internal state cache, while maintaining
// separate statistics respectively.
ReadersWithCacheStats(stateRoot common.Hash) (state.Reader, state.Reader, error)
}
warmer, ok := sdb.(prewarmReader)
if bc.cfg.NoPrefetch || !ok {
statedb, err = state.New(parentRoot, sdb) statedb, err = state.New(parentRoot, sdb)
if err != nil { if err != nil {
return nil, err return nil, err
@ -2131,7 +2149,7 @@ func (bc *BlockChain) ProcessBlock(ctx context.Context, parentRoot common.Hash,
// //
// Note: the main processor and prefetcher share the same reader with a local // Note: the main processor and prefetcher share the same reader with a local
// cache for mitigating the overhead of state access. // cache for mitigating the overhead of state access.
prefetch, process, err := sdb.ReadersWithCacheStats(parentRoot) prefetch, process, err := warmer.ReadersWithCacheStats(parentRoot)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -416,19 +416,42 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) []byte {
// State returns a new mutable state based on the current HEAD block. // State returns a new mutable state based on the current HEAD block.
func (bc *BlockChain) State() (*state.StateDB, error) { func (bc *BlockChain) State() (*state.StateDB, error) {
return bc.StateAt(bc.CurrentBlock().Root) return bc.StateAt(bc.CurrentBlock())
} }
// StateAt returns a new mutable state based on a particular point in time. // StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { func (bc *BlockChain) StateAt(header *types.Header) (*state.StateDB, error) {
return state.New(root, state.NewDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps)) if bc.chainConfig.IsUBT(header.Number, header.Time) {
return state.New(header.Root, state.NewUBTDatabase(bc.triedb, bc.codedb))
}
return state.New(header.Root, state.NewMPTDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps))
} }
// HistoricState returns a historic state specified by the given root. // StateAtForkBoundary returns a new mutable state based on the parent state
// and the given header, handling the transition across the UBT fork.
func (bc *BlockChain) StateAtForkBoundary(parent *types.Header, header *types.Header) (*state.StateDB, error) {
// The parent is already in the UBT fork.
if bc.chainConfig.IsUBT(parent.Number, parent.Time) {
return state.New(parent.Root, state.NewUBTDatabase(bc.triedb, bc.codedb))
}
// The current block is the first block in the UBT fork
// (i.e., the parent is the last MPT block).
if bc.chainConfig.IsUBT(header.Number, header.Time) {
// TODO(gballet): register chain context if needed
return state.New(parent.Root, state.NewUBTDatabase(bc.triedb, bc.codedb))
}
// Both the parent and current block are in the MPT fork.
return state.New(parent.Root, state.NewMPTDatabase(bc.triedb, bc.codedb).WithSnapshot(bc.snaps))
}
// HistoricState returns a historic state specified by the given header.
// Live states are not available and won't be served, please use `State` // Live states are not available and won't be served, please use `State`
// or `StateAt` instead. // or `StateAt` instead.
func (bc *BlockChain) HistoricState(root common.Hash) (*state.StateDB, error) { func (bc *BlockChain) HistoricState(header *types.Header) (*state.StateDB, error) {
return state.New(root, state.NewHistoricDatabase(bc.triedb, bc.codedb)) if bc.chainConfig.IsUBT(header.Number, header.Time) {
return nil, errors.New("historical state over ubt is not yet supported")
}
return state.New(header.Root, state.NewHistoricDatabase(bc.triedb, bc.codedb))
} }
// Config retrieves the chain's fork configuration. // Config retrieves the chain's fork configuration.

View file

@ -3890,7 +3890,7 @@ func TestTransientStorageReset(t *testing.T) {
t.Fatalf("failed to insert into chain: %v", err) t.Fatalf("failed to insert into chain: %v", err)
} }
// Check the storage // Check the storage
state, err := chain.StateAt(chain.CurrentHeader().Root) state, err := chain.StateAt(chain.CurrentHeader())
if err != nil { if err != nil {
t.Fatalf("Failed to load state %v", err) t.Fatalf("Failed to load state %v", err)
} }

View file

@ -126,7 +126,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
// Merge the tx-local access event into the "block-local" one, in order to collect // Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built. // all values, so that the witness can be built.
if b.statedb.Database().TrieDB().IsVerkle() { if b.statedb.Database().Type().Is(state.TypeUBT) {
b.statedb.AccessEvents().Merge(evm.AccessEvents) b.statedb.AccessEvents().Merge(evm.AccessEvents)
} }
b.txs = append(b.txs, tx) b.txs = append(b.txs, tx)
@ -392,7 +392,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) { if config.IsPrague(b.header.Number, b.header.Time) || config.IsUBT(b.header.Number, b.header.Time) {
// EIP-2935 // EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase) blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext.Random = &common.Hash{} // enable post-merge instruction set blockContext.Random = &common.Hash{} // enable post-merge instruction set
@ -430,8 +430,8 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
// Forcibly use hash-based state scheme for retaining all nodes in disk. // Forcibly use hash-based state scheme for retaining all nodes in disk.
var triedbConfig *triedb.Config = triedb.HashDefaults var triedbConfig *triedb.Config = triedb.HashDefaults
if config.IsVerkle(config.ChainID, 0) { if config.IsUBT(config.ChainID, 0) {
triedbConfig = triedb.VerkleDefaults triedbConfig = triedb.UBTDefaults
} }
triedb := triedb.NewDatabase(db, triedbConfig) triedb := triedb.NewDatabase(db, triedbConfig)
defer triedb.Close() defer triedb.Close()
@ -479,8 +479,8 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
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()
var triedbConfig *triedb.Config = triedb.HashDefaults var triedbConfig *triedb.Config = triedb.HashDefaults
if genesis.Config != nil && genesis.Config.IsVerkle(genesis.Config.ChainID, 0) { if genesis.Config != nil && genesis.Config.IsUBT(genesis.Config.ChainID, 0) {
triedbConfig = triedb.VerkleDefaults triedbConfig = triedb.UBTDefaults
} }
genesisTriedb := triedb.NewDatabase(db, triedbConfig) genesisTriedb := triedb.NewDatabase(db, triedbConfig)
block, err := genesis.Commit(db, genesisTriedb, nil) block, err := genesis.Commit(db, genesisTriedb, nil)

View file

@ -129,22 +129,22 @@ 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, isUBT bool) (common.Hash, error) {
// If a genesis-time verkle trie is requested, create a trie config // If a genesis-time verkle trie is requested, create a trie config
// with the verkle trie enabled so that the tree can be initialized // with the verkle trie enabled so that the tree can be initialized
// as such. // as such.
var config *triedb.Config var config *triedb.Config
if isVerkle { if isUBT {
config = &triedb.Config{ config = &triedb.Config{
PathDB: pathdb.Defaults, PathDB: pathdb.Defaults,
IsVerkle: true, IsUBT: 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
if isVerkle { if isUBT {
emptyRoot = types.EmptyVerkleHash emptyRoot = types.EmptyBinaryHash
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
statedb, err := state.New(emptyRoot, state.NewDatabase(triedb.NewDatabase(db, config), nil)) statedb, err := state.New(emptyRoot, state.NewDatabase(triedb.NewDatabase(db, config), nil))
@ -168,8 +168,8 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// 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, tracer *tracing.Hooks) (common.Hash, error) { func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database, tracer *tracing.Hooks) (common.Hash, error) {
emptyRoot := types.EmptyRootHash emptyRoot := types.EmptyRootHash
if triedb.IsVerkle() { if triedb.IsUBT() {
emptyRoot = types.EmptyVerkleHash emptyRoot = types.EmptyBinaryHash
} }
statedb, err := state.New(emptyRoot, state.NewDatabase(triedb, nil)) statedb, err := state.New(emptyRoot, state.NewDatabase(triedb, nil))
if err != nil { if err != nil {
@ -276,10 +276,10 @@ func (e *GenesisMismatchError) Error() string {
// ChainOverrides contains the changes to chain config. // ChainOverrides contains the changes to chain config.
type ChainOverrides struct { type ChainOverrides struct {
OverrideOsaka *uint64 OverrideOsaka *uint64
OverrideBPO1 *uint64 OverrideBPO1 *uint64
OverrideBPO2 *uint64 OverrideBPO2 *uint64
OverrideVerkle *uint64 OverrideUBT *uint64
} }
// apply applies the chain overrides on the supplied chain config. // apply applies the chain overrides on the supplied chain config.
@ -296,8 +296,8 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o.OverrideBPO2 != nil { if o.OverrideBPO2 != nil {
cfg.BPO2Time = o.OverrideBPO2 cfg.BPO2Time = o.OverrideBPO2
} }
if o.OverrideVerkle != nil { if o.OverrideUBT != nil {
cfg.VerkleTime = o.OverrideVerkle cfg.UBTTime = o.OverrideUBT
} }
return cfg.CheckConfigForkOrder() return cfg.CheckConfigForkOrder()
} }
@ -469,15 +469,15 @@ func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainCo
} }
} }
// IsVerkle indicates whether the state is already stored in a verkle // IsUBT indicates whether the state is already stored in a verkle
// tree at genesis time. // tree at genesis time.
func (g *Genesis) IsVerkle() bool { func (g *Genesis) IsUBT() bool {
return g.Config.IsVerkleGenesis() return g.Config.IsUBTGenesis()
} }
// ToBlock returns the genesis block according to genesis specification. // ToBlock returns the genesis block according to genesis specification.
func (g *Genesis) ToBlock() *types.Block { func (g *Genesis) ToBlock() *types.Block {
root, err := hashAlloc(&g.Alloc, g.IsVerkle()) root, err := hashAlloc(&g.Alloc, g.IsUBT())
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -609,24 +609,24 @@ func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.
return block return block
} }
// EnableVerkleAtGenesis indicates whether the verkle fork should be activated // EnableUBTAtGenesis indicates whether the verkle fork should be activated
// at genesis. This is a temporary solution only for verkle devnet testing, where // at genesis. This is a temporary solution only for verkle devnet testing, where
// verkle fork is activated at genesis, and the configured activation date has // verkle fork is activated at genesis, and the configured activation date has
// already passed. // already passed.
// //
// In production networks (mainnet and public testnets), verkle activation always // In production networks (mainnet and public testnets), verkle activation always
// occurs after the genesis block, making this function irrelevant in those cases. // occurs after the genesis block, making this function irrelevant in those cases.
func EnableVerkleAtGenesis(db ethdb.Database, genesis *Genesis) (bool, error) { func EnableUBTAtGenesis(db ethdb.Database, genesis *Genesis) (bool, error) {
if genesis != nil { if genesis != nil {
if genesis.Config == nil { if genesis.Config == nil {
return false, errGenesisNoConfig return false, errGenesisNoConfig
} }
return genesis.Config.EnableVerkleAtGenesis, nil return genesis.Config.EnableUBTAtGenesis, nil
} }
if ghash := rawdb.ReadCanonicalHash(db, 0); ghash != (common.Hash{}) { if ghash := rawdb.ReadCanonicalHash(db, 0); ghash != (common.Hash{}) {
chainCfg := rawdb.ReadChainConfig(db, ghash) chainCfg := rawdb.ReadChainConfig(db, ghash)
if chainCfg != nil { if chainCfg != nil {
return chainCfg.EnableVerkleAtGenesis, nil return chainCfg.EnableUBTAtGenesis, nil
} }
} }
return false, nil return false, nil

View file

@ -285,16 +285,16 @@ func TestVerkleGenesisCommit(t *testing.T) {
CancunTime: &verkleTime, CancunTime: &verkleTime,
PragueTime: &verkleTime, PragueTime: &verkleTime,
OsakaTime: &verkleTime, OsakaTime: &verkleTime,
VerkleTime: &verkleTime, UBTTime: &verkleTime,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
EnableVerkleAtGenesis: true, EnableUBTAtGenesis: true,
Ethash: nil, Ethash: nil,
Clique: nil, Clique: nil,
BlobScheduleConfig: &params.BlobScheduleConfig{ BlobScheduleConfig: &params.BlobScheduleConfig{
Cancun: params.DefaultCancunBlobConfig, Cancun: params.DefaultCancunBlobConfig,
Prague: params.DefaultPragueBlobConfig, Prague: params.DefaultPragueBlobConfig,
Osaka: params.DefaultOsakaBlobConfig, Osaka: params.DefaultOsakaBlobConfig,
Verkle: params.DefaultPragueBlobConfig, UBT: params.DefaultPragueBlobConfig,
}, },
} }
@ -320,8 +320,8 @@ func TestVerkleGenesisCommit(t *testing.T) {
config.NoAsyncFlush = true config.NoAsyncFlush = true
triedb := triedb.NewDatabase(db, &triedb.Config{ triedb := triedb.NewDatabase(db, &triedb.Config{
IsVerkle: true, IsUBT: true,
PathDB: &config, PathDB: &config,
}) })
block := genesis.MustCommit(db, triedb) block := genesis.MustCommit(db, triedb)
if !bytes.Equal(block.Root().Bytes(), expected) { if !bytes.Equal(block.Root().Bytes(), expected) {
@ -329,7 +329,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
} }
// Test that the trie is verkle // Test that the trie is verkle
if !triedb.IsVerkle() { if !triedb.IsUBT() {
t.Fatalf("expected trie to be verkle") t.Fatalf("expected trie to be verkle")
} }
vdb := rawdb.NewTable(db, string(rawdb.VerklePrefix)) vdb := rawdb.NewTable(db, string(rawdb.VerklePrefix))

View file

@ -71,7 +71,7 @@ func (ts *TransitionState) Copy() *TransitionState {
// LoadTransitionState retrieves the Verkle transition state associated with // LoadTransitionState retrieves the Verkle transition state associated with
// the given state root hash from the database. // the given state root hash from the database.
func LoadTransitionState(db ethdb.KeyValueReader, root common.Hash, isVerkle bool) *TransitionState { func LoadTransitionState(db ethdb.KeyValueReader, root common.Hash, isUBT bool) *TransitionState {
var ts *TransitionState var ts *TransitionState
data, _ := rawdb.ReadVerkleTransitionState(db, root) data, _ := rawdb.ReadVerkleTransitionState(db, root)
@ -97,10 +97,10 @@ func LoadTransitionState(db ethdb.KeyValueReader, root common.Hash, isVerkle boo
// Initialize the first transition state, with the "ended" // Initialize the first transition state, with the "ended"
// field set to true if the database was created // field set to true if the database was created
// as a verkle database. // as a verkle database.
log.Debug("no transition state found, starting fresh", "verkle", isVerkle) log.Debug("no transition state found, starting fresh", "verkle", isUBT)
// Start with a fresh state // Start with a fresh state
ts = &TransitionState{Ended: isVerkle} ts = &TransitionState{Ended: isUBT}
} }
return ts return ts
} }

View file

@ -20,22 +20,36 @@ import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/overlay"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"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/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/bintrie"
"github.com/ethereum/go-ethereum/trie/transitiontrie" "github.com/ethereum/go-ethereum/trie/transitiontrie"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
) )
// DatabaseType represents the type of trie backing the state database.
type DatabaseType int
const (
// TypeMPT indicates a Merkle Patricia Trie (MPT) backed database.
TypeMPT DatabaseType = iota
// TypeUBT indicates a Unified Binary Trie (UBT) backed database.
TypeUBT
)
// Is returns the flag indicating the database type equals to the given one.
func (typ DatabaseType) Is(t DatabaseType) bool {
return typ == t
}
// Database wraps access to tries and contract code. // Database wraps access to tries and contract code.
type Database interface { type Database interface {
// Type returns the trie type backing this database (MPT or UBT).
Type() DatabaseType
// Reader returns a state reader associated with the specified state root. // Reader returns a state reader associated with the specified state root.
Reader(root common.Hash) (Reader, error) Reader(root common.Hash) (Reader, error)
@ -139,184 +153,27 @@ type Trie interface {
// with the node that proves the absence of the key. // with the node that proves the absence of the key.
Prove(key []byte, proofDb ethdb.KeyValueWriter) error Prove(key []byte, proofDb ethdb.KeyValueWriter) error
// IsVerkle returns true if the trie is verkle-tree based // IsUBT returns true if the trie is unified binary trie based.
IsVerkle() bool IsUBT() bool
}
// CachingDB is an implementation of Database interface. It leverages both trie and
// state snapshot to provide functionalities for state access. It's meant to be a
// long-live object and has a few caches inside for sharing between blocks.
type CachingDB struct {
triedb *triedb.Database
codedb *CodeDB
snap *snapshot.Tree
} }
// 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, codedb *CodeDB) *CachingDB { //
if codedb == nil { // Deprecated, please use NewMPTDatabase or NewUBTDatabase directly.
codedb = NewCodeDB(triedb.Disk()) func NewDatabase(tdb *triedb.Database, codedb *CodeDB) Database {
} if tdb.IsUBT() {
return &CachingDB{ return NewUBTDatabase(tdb, codedb)
triedb: triedb,
codedb: codedb,
} }
return NewMPTDatabase(tdb, codedb)
} }
// 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() Database {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
return NewDatabase(triedb.NewDatabase(db, nil), NewCodeDB(db)) return NewDatabase(triedb.NewDatabase(db, nil), NewCodeDB(db))
} }
// WithSnapshot configures the provided contract code cache. Note that this
// registration must be performed before the cachingDB is used.
func (db *CachingDB) WithSnapshot(snapshot *snapshot.Tree) *CachingDB {
db.snap = snapshot
return db
}
// StateReader returns a state reader associated with the specified state root.
func (db *CachingDB) StateReader(stateRoot common.Hash) (StateReader, error) {
var readers []StateReader
// Configure the state reader using the standalone snapshot in hash mode.
// This reader offers improved performance but is optional and only
// partially useful if the snapshot is not fully generated.
if db.TrieDB().Scheme() == rawdb.HashScheme && db.snap != nil {
snap := db.snap.Snapshot(stateRoot)
if snap != nil {
readers = append(readers, newFlatReader(snap))
}
}
// Configure the state reader using the path database in path mode.
// This reader offers improved performance but is optional and only
// partially useful if the snapshot data in path database is not
// fully generated.
if db.TrieDB().Scheme() == rawdb.PathScheme {
reader, err := db.triedb.StateReader(stateRoot)
if err == nil {
readers = append(readers, newFlatReader(reader))
}
}
// Configure the trie reader, which is expected to be available as the
// gatekeeper unless the state is corrupted.
tr, err := newTrieReader(stateRoot, db.triedb)
if err != nil {
return nil, err
}
readers = append(readers, tr)
return newMultiStateReader(readers...)
}
// Reader implements Database, returning a reader associated with the specified
// state root.
func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
sr, err := db.StateReader(stateRoot)
if err != nil {
return nil, err
}
return newReader(db.codedb.Reader(), sr), nil
}
// ReadersWithCacheStats creates a pair of state readers that share the same
// underlying state reader and internal state cache, while maintaining separate
// statistics respectively.
func (db *CachingDB) ReadersWithCacheStats(stateRoot common.Hash) (Reader, Reader, error) {
r, err := db.StateReader(stateRoot)
if err != nil {
return nil, nil, err
}
sr := newStateReaderWithCache(r)
ra := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
rb := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
return ra, rb, nil
}
// OpenTrie opens the main account trie at a specific root hash.
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.triedb.IsVerkle() {
ts := overlay.LoadTransitionState(db.TrieDB().Disk(), root, db.triedb.IsVerkle())
if ts.InTransition() {
panic("state tree transition isn't supported yet")
}
if ts.Transitioned() {
// Use BinaryTrie instead of VerkleTrie when IsVerkle is set
// (IsVerkle actually means Binary Trie mode in this codebase)
return bintrie.NewBinaryTrie(root, db.triedb)
}
}
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
}
// OpenStorageTrie opens the storage trie of an account.
func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
if db.triedb.IsVerkle() {
return self, nil
}
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
}
// TrieDB retrieves any intermediate trie-node caching layer.
func (db *CachingDB) TrieDB() *triedb.Database {
return db.triedb
}
// Snapshot returns the underlying state snapshot.
func (db *CachingDB) Snapshot() *snapshot.Tree {
return db.snap
}
// Commit flushes all pending writes and finalizes the state transition,
// committing the changes to the underlying storage. It returns an error
// if the commit fails.
func (db *CachingDB) Commit(update *stateUpdate) error {
// Short circuit if nothing to commit
if update.empty() {
return nil
}
// Commit dirty contract code if any exists
if len(update.codes) > 0 {
batch := db.codedb.NewBatchWithSize(len(update.codes))
for _, code := range update.codes {
batch.Put(code.hash, code.blob)
}
if err := batch.Commit(); err != nil {
return err
}
}
// If snapshotting is enabled, update the snapshot tree with this new version
if db.snap != nil && db.snap.Snapshot(update.originRoot) != nil {
if err := db.snap.Update(update.root, update.originRoot, update.accounts, update.storages); err != nil {
log.Warn("Failed to update snapshot tree", "from", update.originRoot, "to", update.root, "err", err)
}
// Keep 128 diff layers in the memory, persistent layer is 129th.
// - head layer is paired with HEAD state
// - head-1 layer is paired with HEAD-1 state
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
if err := db.snap.Cap(update.root, TriesInMemory); err != nil {
log.Warn("Failed to cap snapshot tree", "root", update.root, "layers", TriesInMemory, "err", err)
}
}
return db.triedb.Update(update.root, update.originRoot, update.blockNumber, update.nodes, update.stateSet())
}
// Iteratee returns a state iteratee associated with the specified state root,
// through which the account iterator and storage iterator can be created.
func (db *CachingDB) Iteratee(root common.Hash) (Iteratee, error) {
return newStateIteratee(!db.triedb.IsVerkle(), root, db.triedb, db.snap)
}
// mustCopyTrie returns a deep-copied trie. // mustCopyTrie returns a deep-copied trie.
func mustCopyTrie(t Trie) Trie { func mustCopyTrie(t Trie) Trie {
switch t := t.(type) { switch t := t.(type) {

View file

@ -223,6 +223,12 @@ type HistoricDB struct {
codedb *CodeDB codedb *CodeDB
} }
// Type returns the trie type of the underlying database.
func (db *HistoricDB) Type() DatabaseType {
// TODO(rjl493456442) support UBT in the future
return TypeMPT
}
// NewHistoricDatabase creates a historic state database. // NewHistoricDatabase creates a historic state database.
func NewHistoricDatabase(triedb *triedb.Database, codedb *CodeDB) *HistoricDB { func NewHistoricDatabase(triedb *triedb.Database, codedb *CodeDB) *HistoricDB {
return &HistoricDB{ return &HistoricDB{

178
core/state/database_mpt.go Normal file
View file

@ -0,0 +1,178 @@
// Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package state
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/triedb"
)
// MPTDatabase is an implementation of Database interface for Merkle Patricia Tries.
// It leverages both trie and state snapshot to provide functionalities for state
// access.
type MPTDatabase struct {
triedb *triedb.Database
codedb *CodeDB
snap *snapshot.Tree
}
// Type returns Merkle, indicating this database is backed by a Merkle Patricia Trie.
func (db *MPTDatabase) Type() DatabaseType { return TypeMPT }
// NewMPTDatabase creates a state database with the Merkle Patricia Trie manner.
func NewMPTDatabase(tdb *triedb.Database, codedb *CodeDB) *MPTDatabase {
if codedb == nil {
codedb = NewCodeDB(tdb.Disk())
}
return &MPTDatabase{
triedb: tdb,
codedb: codedb,
}
}
// WithSnapshot configures the provided state snapshot. Note that this
// registration must be performed before the MPTDatabase is used.
func (db *MPTDatabase) WithSnapshot(snapshot *snapshot.Tree) Database {
db.snap = snapshot
return db
}
// StateReader returns a state reader associated with the specified state root.
func (db *MPTDatabase) StateReader(stateRoot common.Hash) (StateReader, error) {
var readers []StateReader
// Configure the state reader using the standalone snapshot in hash mode.
// This reader offers improved performance but is optional and only
// partially useful if the snapshot is not fully generated.
if db.TrieDB().Scheme() == rawdb.HashScheme && db.snap != nil {
snap := db.snap.Snapshot(stateRoot)
if snap != nil {
readers = append(readers, newFlatReader(snap))
}
}
// Configure the state reader using the path database in path mode.
// This reader offers improved performance but is optional and only
// partially useful if the snapshot data in path database is not
// fully generated.
if db.TrieDB().Scheme() == rawdb.PathScheme {
reader, err := db.triedb.StateReader(stateRoot)
if err == nil {
readers = append(readers, newFlatReader(reader))
}
}
// Configure the trie reader, which is expected to be available as the
// gatekeeper unless the state is corrupted.
tr, err := newTrieReader(stateRoot, db.triedb)
if err != nil {
return nil, err
}
readers = append(readers, tr)
return newMultiStateReader(readers...)
}
// Reader implements Database, returning a reader associated with the specified
// state root.
func (db *MPTDatabase) Reader(stateRoot common.Hash) (Reader, error) {
sr, err := db.StateReader(stateRoot)
if err != nil {
return nil, err
}
return newReader(db.codedb.Reader(), sr), nil
}
// ReadersWithCacheStats creates a pair of state readers that share the same
// underlying state reader and internal state cache, while maintaining separate
// statistics respectively.
func (db *MPTDatabase) ReadersWithCacheStats(stateRoot common.Hash) (Reader, Reader, error) {
r, err := db.StateReader(stateRoot)
if err != nil {
return nil, nil, err
}
sr := newStateReaderWithCache(r)
ra := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
rb := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
return ra, rb, nil
}
// OpenTrie opens the main account trie at a specific root hash.
func (db *MPTDatabase) OpenTrie(root common.Hash) (Trie, error) {
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
}
// OpenStorageTrie opens the storage trie of an account.
func (db *MPTDatabase) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
}
// TrieDB retrieves any intermediate trie-node caching layer.
func (db *MPTDatabase) TrieDB() *triedb.Database {
return db.triedb
}
// Commit flushes all pending writes and finalizes the state transition,
// committing the changes to the underlying storage. It returns an error
// if the commit fails.
func (db *MPTDatabase) Commit(update *stateUpdate) error {
// Short circuit if nothing to commit
if update.empty() {
return nil
}
// Commit dirty contract code if any exists
if len(update.codes) > 0 {
batch := db.codedb.NewBatchWithSize(len(update.codes))
for _, code := range update.codes {
batch.Put(code.hash, code.blob)
}
if err := batch.Commit(); err != nil {
return err
}
}
// If snapshotting is enabled, update the snapshot tree with this new version
if db.snap != nil && db.snap.Snapshot(update.originRoot) != nil {
if err := db.snap.Update(update.root, update.originRoot, update.accounts, update.storages); err != nil {
log.Warn("Failed to update snapshot tree", "from", update.originRoot, "to", update.root, "err", err)
}
// Keep 128 diff layers in the memory, persistent layer is 129th.
// - head layer is paired with HEAD state
// - head-1 layer is paired with HEAD-1 state
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
if err := db.snap.Cap(update.root, TriesInMemory); err != nil {
log.Warn("Failed to cap snapshot tree", "root", update.root, "layers", TriesInMemory, "err", err)
}
}
return db.triedb.Update(update.root, update.originRoot, update.blockNumber, update.nodes, update.stateSet())
}
// Iteratee returns a state iteratee associated with the specified state root,
// through which the account iterator and storage iterator can be created.
func (db *MPTDatabase) Iteratee(root common.Hash) (Iteratee, error) {
return newStateIteratee(true, root, db.triedb, db.snap)
}

138
core/state/database_ubt.go Normal file
View file

@ -0,0 +1,138 @@
// Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package state
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/trie/bintrie"
"github.com/ethereum/go-ethereum/triedb"
)
// UBTDatabase is an implementation of Database interface for Unified Binary Trie.
// It provides the same functionality as MPTDatabase but uses unified binary
// trie for state hashing instead of Merkle Patricia Tries.
type UBTDatabase struct {
triedb *triedb.Database
codedb *CodeDB
}
// Type returns Binary, indicating this database is backed by a Universal Binary Trie.
func (db *UBTDatabase) Type() DatabaseType { return TypeUBT }
// NewUBTDatabase creates a state database with the Unified binary trie manner.
func NewUBTDatabase(triedb *triedb.Database, codedb *CodeDB) *UBTDatabase {
if codedb == nil {
codedb = NewCodeDB(triedb.Disk())
}
return &UBTDatabase{
triedb: triedb,
codedb: codedb,
}
}
// StateReader returns a state reader associated with the specified state root.
func (db *UBTDatabase) StateReader(stateRoot common.Hash) (StateReader, error) {
var readers []StateReader
// Configure the state reader using the path database in path mode.
// This reader offers improved performance but is optional and only
// partially useful if the snapshot data in path database is not
// fully generated.
if db.TrieDB().Scheme() == rawdb.PathScheme {
reader, err := db.triedb.StateReader(stateRoot)
if err == nil {
readers = append(readers, newFlatReader(reader))
}
}
// Configure the trie reader, which is expected to be available as the
// gatekeeper unless the state is corrupted.
tr, err := newTrieReader(stateRoot, db.triedb)
if err != nil {
return nil, err
}
readers = append(readers, tr)
return newMultiStateReader(readers...)
}
// Reader implements Database, returning a reader associated with the specified
// state root.
func (db *UBTDatabase) Reader(stateRoot common.Hash) (Reader, error) {
sr, err := db.StateReader(stateRoot)
if err != nil {
return nil, err
}
return newReader(db.codedb.Reader(), sr), nil
}
// ReadersWithCacheStats creates a pair of state readers that share the same
// underlying state reader and internal state cache, while maintaining separate
// statistics respectively.
func (db *UBTDatabase) ReadersWithCacheStats(stateRoot common.Hash) (Reader, Reader, error) {
r, err := db.StateReader(stateRoot)
if err != nil {
return nil, nil, err
}
sr := newStateReaderWithCache(r)
ra := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
rb := newReader(db.codedb.Reader(), newStateReaderWithStats(sr))
return ra, rb, nil
}
// OpenTrie opens the main account trie at a specific root hash.
func (db *UBTDatabase) OpenTrie(root common.Hash) (Trie, error) {
return bintrie.NewBinaryTrie(root, db.triedb)
}
// OpenStorageTrie opens the storage trie of an account. In binary trie mode,
// all state objects share one unified trie, so the main trie is returned.
func (db *UBTDatabase) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
return self, nil
}
// TrieDB retrieves any intermediate trie-node caching layer.
func (db *UBTDatabase) TrieDB() *triedb.Database {
return db.triedb
}
// Commit flushes all pending writes and finalizes the state transition,
// committing the changes to the underlying storage. It returns an error
// if the commit fails.
func (db *UBTDatabase) Commit(update *stateUpdate) error {
// Short circuit if nothing to commit
if update.empty() {
return nil
}
// Commit dirty contract code if any exists
if len(update.codes) > 0 {
batch := db.codedb.NewBatchWithSize(len(update.codes))
for _, code := range update.codes {
batch.Put(code.hash, code.blob)
}
if err := batch.Commit(); err != nil {
return err
}
}
return db.triedb.Update(update.root, update.originRoot, update.blockNumber, update.nodes, update.stateSet())
}
// Iteratee returns a state iteratee associated with the specified state root,
// through which the account iterator and storage iterator can be created.
func (db *UBTDatabase) Iteratee(root common.Hash) (Iteratee, error) {
return newStateIteratee(false, root, db.triedb, nil)
}

View file

@ -172,10 +172,10 @@ func newTrieReader(root common.Hash, db *triedb.Database) (*trieReader, error) {
tr Trie tr Trie
err error err error
) )
if !db.IsVerkle() { if !db.IsUBT() {
tr, err = trie.NewStateTrie(trie.StateTrieID(root), db) tr, err = trie.NewStateTrie(trie.StateTrieID(root), db)
} else { } else {
// When IsVerkle() is true, create a BinaryTrie wrapped in TransitionTrie // When IsUBT() is true, create a BinaryTrie wrapped in TransitionTrie
binTrie, binErr := bintrie.NewBinaryTrie(root, db) binTrie, binErr := bintrie.NewBinaryTrie(root, db)
if binErr != nil { if binErr != nil {
return nil, binErr return nil, binErr
@ -259,7 +259,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash,
found bool found bool
value common.Hash value common.Hash
) )
if r.db.IsVerkle() { if r.db.IsUBT() {
tr = r.mainTrie tr = r.mainTrie
} else { } else {
tr, found = r.subTries[addr] tr, found = r.subTries[addr]

View file

@ -154,7 +154,7 @@ func (s *stateObject) getTrie() (Trie, error) {
func (s *stateObject) getPrefetchedTrie() Trie { func (s *stateObject) getPrefetchedTrie() Trie {
// If there's nothing to meaningfully return, let the user figure it out by // If there's nothing to meaningfully return, let the user figure it out by
// pulling the trie from disk. // pulling the trie from disk.
if (s.data.Root == types.EmptyRootHash && !s.db.db.TrieDB().IsVerkle()) || s.db.prefetcher == nil { if (s.data.Root == types.EmptyRootHash && s.db.db.Type().Is(TypeMPT)) || s.db.prefetcher == nil {
return nil return nil
} }
// Attempt to retrieve the trie from the prefetcher // Attempt to retrieve the trie from the prefetcher
@ -478,7 +478,7 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
// The main account trie commit in stateDB.commit() already calls // The main account trie commit in stateDB.commit() already calls
// CollectNodes on this trie, so calling Commit here again would // CollectNodes on this trie, so calling Commit here again would
// redundantly traverse and serialize the entire tree per dirty account. // redundantly traverse and serialize the entire tree per dirty account.
if s.db.GetTrie().IsVerkle() { if s.db.GetTrie().IsUBT() {
s.origin = s.data.Copy() s.origin = s.data.Copy()
return op, nil, nil return op, nil, nil
} }

View file

@ -190,7 +190,7 @@ func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, erro
accessList: newAccessList(), accessList: newAccessList(),
transientStorage: newTransientStorage(), transientStorage: newTransientStorage(),
} }
if db.TrieDB().IsVerkle() { if db.Type().Is(TypeUBT) {
sdb.accessEvents = NewAccessEvents() sdb.accessEvents = NewAccessEvents()
} }
return sdb, nil return sdb, nil
@ -861,7 +861,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.db.Type().Is(TypeUBT) {
// Bypass per-account updateTrie() for binary trie. In binary trie mode // Bypass per-account updateTrie() for binary trie. In binary trie mode
// there is only one unified trie (OpenStorageTrie returns self), so the // there is only one unified trie (OpenStorageTrie returns self), so the
// per-account trie setup in updateTrie() (getPrefetchedTrie, getTrie, // per-account trie setup in updateTrie() (getPrefetchedTrie, getTrie,
@ -925,9 +925,9 @@ 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 Unified-binary-trie mode, they will be
// together at the end. // gathered together at the end.
if s.witness != nil && !s.db.TrieDB().IsVerkle() { if s.witness != nil && s.db.Type().Is(TypeMPT) {
// 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
@ -968,7 +968,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
// only a single trie is used for state hashing. Replacing a non-nil verkle tree // only a single trie is used for state hashing. Replacing a non-nil verkle tree
// here could result in losing uncommitted changes from storage. // here could result in losing uncommitted changes from storage.
start = time.Now() start = time.Now()
if s.prefetcher != nil && !s.db.TrieDB().IsVerkle() { if s.prefetcher != nil && s.db.Type().Is(TypeMPT) {
if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil { if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil {
log.Error("Failed to retrieve account pre-fetcher trie") log.Error("Failed to retrieve account pre-fetcher trie")
} else { } else {
@ -1129,7 +1129,7 @@ func (s *StateDB) handleDestruction(noStorageWiping bool) (map[common.Hash]*acco
deletes[addrHash] = op deletes[addrHash] = op
// Short circuit if the origin storage was empty. // Short circuit if the origin storage was empty.
if prev.Root == types.EmptyRootHash || s.db.TrieDB().IsVerkle() { if prev.Root == types.EmptyRootHash || s.db.Type().Is(TypeUBT) {
continue continue
} }
if noStorageWiping { if noStorageWiping {

View file

@ -209,7 +209,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, nil).WithSnapshot(snaps)) state, err := New(root, NewMPTDatabase(tdb, nil).WithSnapshot(snaps))
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -1274,7 +1274,7 @@ func TestDeleteStorage(t *testing.T) {
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = triedb.NewDatabase(disk, nil) tdb = triedb.NewDatabase(disk, nil)
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, nil).WithSnapshot(snaps) db = NewMPTDatabase(tdb, nil).WithSnapshot(snaps)
state, _ = New(types.EmptyRootHash, db) state, _ = New(types.EmptyRootHash, db)
addr = common.HexToAddress("0x1") addr = common.HexToAddress("0x1")
) )
@ -1288,8 +1288,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, nil).WithSnapshot(snaps)) fastState, _ := New(root, NewMPTDatabase(tdb, nil).WithSnapshot(snaps))
slowState, _ := New(root, NewDatabase(tdb, nil)) slowState, _ := New(root, NewMPTDatabase(tdb, nil))
obj := fastState.getOrNewStateObject(addr) obj := fastState.getOrNewStateObject(addr)
storageRoot := obj.data.Root storageRoot := obj.data.Root

View file

@ -40,7 +40,7 @@ var (
// //
// Note, the prefetcher's API is not thread safe. // Note, the prefetcher's API is not thread safe.
type triePrefetcher struct { type triePrefetcher struct {
verkle bool // Flag whether the prefetcher is in verkle mode isUBT bool // Flag whether the prefetcher is in UBT mode
db Database // Database to fetch trie nodes through db Database // Database to fetch trie nodes through
root common.Hash // Root hash of the account trie for metrics root common.Hash // Root hash of the account trie for metrics
fetchers map[string]*subfetcher // Subfetchers for each trie fetchers map[string]*subfetcher // Subfetchers for each trie
@ -67,7 +67,7 @@ type triePrefetcher struct {
func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher { func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher {
prefix := triePrefetchMetricsPrefix + namespace prefix := triePrefetchMetricsPrefix + namespace
return &triePrefetcher{ return &triePrefetcher{
verkle: db.TrieDB().IsVerkle(), isUBT: db.Type().Is(TypeUBT),
db: db, db: db,
root: root, root: root,
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
@ -206,8 +206,8 @@ func (p *triePrefetcher) used(owner common.Hash, root common.Hash, usedAddr []co
// trieID returns an unique trie identifier consists the trie owner and root hash. // trieID returns an unique trie identifier consists the trie owner and root hash.
func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string { func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string {
// The trie in verkle is only identified by state root // The trie in ubt is only identified by state root
if p.verkle { if p.isUBT {
return p.root.Hex() return p.root.Hex()
} }
// The trie in merkle is either identified by state root (account trie), // The trie in merkle is either identified by state root (account trie),
@ -340,12 +340,12 @@ func (sf *subfetcher) terminate(async bool) {
// openTrie resolves the target trie from database for prefetching. // openTrie resolves the target trie from database for prefetching.
func (sf *subfetcher) openTrie() error { func (sf *subfetcher) openTrie() error {
// Open the verkle tree if the sub-fetcher is in verkle mode. Note, there is // Open the ubt tree if the sub-fetcher is in ubt mode. Note, there is
// only a single fetcher for verkle. // only a single fetcher for ubt.
if sf.db.TrieDB().IsVerkle() { if sf.db.Type().Is(TypeUBT) {
tr, err := sf.db.OpenTrie(sf.state) tr, err := sf.db.OpenTrie(sf.state)
if err != nil { if err != nil {
log.Warn("Trie prefetcher failed opening verkle trie", "root", sf.root, "err", err) log.Warn("Trie prefetcher failed opening UBT trie", "root", sf.root, "err", err)
return err return err
} }
sf.trie = tr sf.trie = tr

View file

@ -68,7 +68,7 @@ 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) db := triedb.NewDatabase(disk, triedb.UBTDefaults)
sdb := NewDatabase(db, nil) sdb := NewDatabase(db, nil)
state, err := New(types.EmptyRootHash, sdb) state, err := New(types.EmptyRootHash, sdb)

View file

@ -90,7 +90,7 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, evm) ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if config.IsPrague(block.Number(), block.Time()) || config.IsVerkle(block.Number(), block.Time()) { if config.IsPrague(block.Number(), block.Time()) || config.IsUBT(block.Number(), block.Time()) {
ProcessParentBlockHash(block.ParentHash(), evm) ProcessParentBlockHash(block.ParentHash(), evm)
} }
@ -182,7 +182,7 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
} }
// Merge the tx-local access event into the "block-local" one, in order to collect // Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built. // all values, so that the witness can be built.
if statedb.Database().TrieDB().IsVerkle() { if statedb.Database().Type().Is(state.TypeUBT) {
statedb.AccessEvents().Merge(evm.AccessEvents) statedb.AccessEvents().Merge(evm.AccessEvents)
} }
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, gp.CumulativeUsed(), root), nil return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, gp.CumulativeUsed(), root), nil

View file

@ -441,9 +441,9 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
// Initialize the state with head block, or fallback to empty one in // Initialize the state with head block, or fallback to empty one in
// case the head state is not available (might occur when node is not // case the head state is not available (might occur when node is not
// fully synced). // fully synced).
state, err := p.chain.StateAt(head.Root) state, err := p.chain.StateAt(head)
if err != nil { if err != nil {
state, err = p.chain.StateAt(types.EmptyRootHash) state, err = p.chain.StateAt(p.chain.Genesis().Header())
} }
if err != nil { if err != nil {
return err return err
@ -894,7 +894,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
// Handle reorg buffer timeouts evicting old gapped transactions // Handle reorg buffer timeouts evicting old gapped transactions
p.evictGapped() p.evictGapped()
statedb, err := p.chain.StateAt(newHead.Root) statedb, err := p.chain.StateAt(newHead)
if err != nil { if err != nil {
log.Error("Failed to reset blobpool state", "err", err) log.Error("Failed to reset blobpool state", "err", err)
return return

View file

@ -45,6 +45,7 @@ import (
"github.com/ethereum/go-ethereum/internal/testrand" "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/billy" "github.com/holiman/billy"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -180,10 +181,14 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return bc.blocks[number] return bc.blocks[number]
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(header *types.Header) (*state.StateDB, error) {
return bc.statedb, nil return bc.statedb, nil
} }
func (bc *testBlockChain) Genesis() *types.Block {
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
}
// reserver is a utility struct to sanity check that accounts are // reserver is a utility struct to sanity check that accounts are
// properly reserved by the blobpool (no duplicate reserves or unreserves). // properly reserved by the blobpool (no duplicate reserves or unreserves).
type reserver struct { type reserver struct {

View file

@ -32,6 +32,9 @@ type BlockChain interface {
// CurrentBlock returns the current head of the chain. // CurrentBlock returns the current head of the chain.
CurrentBlock() *types.Header CurrentBlock() *types.Header
// Genesis returns the genesis block of the chain.
Genesis() *types.Block
// CurrentFinalBlock returns the current block below which blobs should not // CurrentFinalBlock returns the current block below which blobs should not
// be maintained anymore for reorg purposes. // be maintained anymore for reorg purposes.
CurrentFinalBlock() *types.Header CurrentFinalBlock() *types.Header
@ -39,6 +42,6 @@ type BlockChain interface {
// GetBlock retrieves a specific block, used during pool resets. // GetBlock retrieves a specific block, used during pool resets.
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given chain header (generally the head).
StateAt(root common.Hash) (*state.StateDB, error) StateAt(header *types.Header) (*state.StateDB, error)
} }

View file

@ -129,11 +129,14 @@ type BlockChain interface {
// CurrentBlock returns the current head of the chain. // CurrentBlock returns the current head of the chain.
CurrentBlock() *types.Header CurrentBlock() *types.Header
// Genesis returns the genesis block of the chain.
Genesis() *types.Block
// GetBlock retrieves a specific block, used during pool resets. // GetBlock retrieves a specific block, used during pool resets.
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given chain header (generally the head).
StateAt(root common.Hash) (*state.StateDB, error) StateAt(header *types.Header) (*state.StateDB, error)
} }
// Config are the configuration parameters of the transaction pool. // Config are the configuration parameters of the transaction pool.
@ -317,9 +320,9 @@ func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserver txpool.
// Initialize the state with head block, or fallback to empty one in // Initialize the state with head block, or fallback to empty one in
// case the head state is not available (might occur when node is not // case the head state is not available (might occur when node is not
// fully synced). // fully synced).
statedb, err := pool.chain.StateAt(head.Root) statedb, err := pool.chain.StateAt(head)
if err != nil { if err != nil {
statedb, err = pool.chain.StateAt(types.EmptyRootHash) statedb, err = pool.chain.StateAt(pool.chain.Genesis().Header())
} }
if err != nil { if err != nil {
return err return err
@ -1379,7 +1382,7 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) {
if newHead == nil { if newHead == nil {
newHead = pool.chain.CurrentBlock() // Special case during testing newHead = pool.chain.CurrentBlock() // Special case during testing
} }
statedb, err := pool.chain.StateAt(newHead.Root) statedb, err := pool.chain.StateAt(newHead)
if err != nil { if err != nil {
log.Error("Failed to reset txpool state", "err", err) log.Error("Failed to reset txpool state", "err", err)
return return

View file

@ -91,10 +91,14 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil)) return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(header *types.Header) (*state.StateDB, error) {
return bc.statedb, nil return bc.statedb, nil
} }
func (bc *testBlockChain) Genesis() *types.Block {
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
}
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return bc.chainHeadFeed.Subscribe(ch) return bc.chainHeadFeed.Subscribe(ch)
} }

View file

@ -102,7 +102,7 @@ func (env *testEnv) setGasTip(gasTip uint64) {
func (env *testEnv) makeTx(nonce uint64, gasPrice *big.Int) *types.Transaction { func (env *testEnv) makeTx(nonce uint64, gasPrice *big.Int) *types.Transaction {
if nonce == 0 { if nonce == 0 {
head := env.chain.CurrentHeader() head := env.chain.CurrentHeader()
state, _ := env.chain.StateAt(head.Root) state, _ := env.chain.StateAt(head)
nonce = state.GetNonce(address) nonce = state.GetNonce(address)
} }
if gasPrice == nil { if gasPrice == nil {
@ -114,7 +114,7 @@ func (env *testEnv) makeTx(nonce uint64, gasPrice *big.Int) *types.Transaction {
func (env *testEnv) makeTxs(n int) []*types.Transaction { func (env *testEnv) makeTxs(n int) []*types.Transaction {
head := env.chain.CurrentHeader() head := env.chain.CurrentHeader()
state, _ := env.chain.StateAt(head.Root) state, _ := env.chain.StateAt(head)
nonce := state.GetNonce(address) nonce := state.GetNonce(address)
var txs []*types.Transaction var txs []*types.Transaction

View file

@ -50,11 +50,14 @@ type BlockChain interface {
// CurrentBlock returns the current head of the chain. // CurrentBlock returns the current head of the chain.
CurrentBlock() *types.Header CurrentBlock() *types.Header
// Genesis returns the genesis block of the chain.
Genesis() *types.Block
// SubscribeChainHeadEvent subscribes to new blocks being added to the chain. // SubscribeChainHeadEvent subscribes to new blocks being added to the chain.
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given chain header (generally the head).
StateAt(root common.Hash) (*state.StateDB, error) StateAt(header *types.Header) (*state.StateDB, error)
} }
// TxPool is an aggregator for various transaction specific pools, collectively // TxPool is an aggregator for various transaction specific pools, collectively
@ -87,9 +90,9 @@ func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) {
// Initialize the state with head block, or fallback to empty one in // Initialize the state with head block, or fallback to empty one in
// case the head state is not available (might occur when node is not // case the head state is not available (might occur when node is not
// fully synced). // fully synced).
statedb, err := chain.StateAt(head.Root) statedb, err := chain.StateAt(head)
if err != nil { if err != nil {
statedb, err = chain.StateAt(types.EmptyRootHash) statedb, err = chain.StateAt(chain.Genesis().Header())
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -185,7 +188,7 @@ func (p *TxPool) loop(head *types.Header) {
case resetBusy <- struct{}{}: case resetBusy <- struct{}{}:
// Updates the statedb with the new chain head. The head state may be // Updates the statedb with the new chain head. The head state may be
// unavailable if the initial state sync has not yet completed. // unavailable if the initial state sync has not yet completed.
if statedb, err := p.chain.StateAt(newHead.Root); err != nil { if statedb, err := p.chain.StateAt(newHead); err != nil {
log.Error("Failed to reset txpool state", "err", err) log.Error("Failed to reset txpool state", "err", err)
} else { } else {
p.stateLock.Lock() p.stateLock.Lock()

View file

@ -43,9 +43,6 @@ var (
// EmptyRequestsHash is the known hash of an empty request set, sha256(""). // EmptyRequestsHash is the known hash of an empty request set, sha256("").
EmptyRequestsHash = common.HexToHash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") EmptyRequestsHash = common.HexToHash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
// EmptyVerkleHash is the known hash of an empty verkle trie.
EmptyVerkleHash = common.Hash{}
// EmptyBinaryHash is the known hash of an empty binary trie. // EmptyBinaryHash is the known hash of an empty binary trie.
EmptyBinaryHash = common.Hash{} EmptyBinaryHash = common.Hash{}
) )

View file

@ -213,7 +213,7 @@ func init() {
func activePrecompiledContracts(rules params.Rules) PrecompiledContracts { func activePrecompiledContracts(rules params.Rules) PrecompiledContracts {
switch { switch {
case rules.IsVerkle: case rules.IsUBT:
return PrecompiledContractsVerkle return PrecompiledContractsVerkle
case rules.IsOsaka: case rules.IsOsaka:
return PrecompiledContractsOsaka return PrecompiledContractsOsaka

View file

@ -149,7 +149,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
evm.table = &amsterdamInstructionSet evm.table = &amsterdamInstructionSet
case evm.chainRules.IsOsaka: case evm.chainRules.IsOsaka:
evm.table = &osakaInstructionSet evm.table = &osakaInstructionSet
case evm.chainRules.IsVerkle: case evm.chainRules.IsUBT:
// TODO replace with proper instruction set when fork is specified // TODO replace with proper instruction set when fork is specified
evm.table = &verkleInstructionSet evm.table = &verkleInstructionSet
case evm.chainRules.IsPrague: case evm.chainRules.IsPrague:

View file

@ -26,7 +26,7 @@ import (
// the rules. // the rules.
func LookupInstructionSet(rules params.Rules) (JumpTable, error) { func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
switch { switch {
case rules.IsVerkle: case rules.IsUBT:
return newCancunInstructionSet(), errors.New("verkle-fork not defined yet") return newCancunInstructionSet(), errors.New("verkle-fork not defined yet")
case rules.IsAmsterdam: case rules.IsAmsterdam:
return newAmsterdamInstructionSet(), nil return newAmsterdamInstructionSet(), nil

View file

@ -236,9 +236,9 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
if header == nil { if header == nil {
return nil, nil, errors.New("header not found") return nil, nil, errors.New("header not found")
} }
stateDb, err := b.eth.BlockChain().StateAt(header.Root) stateDb, err := b.eth.BlockChain().StateAt(header)
if err != nil { if err != nil {
stateDb, err = b.eth.BlockChain().HistoricState(header.Root) stateDb, err = b.eth.BlockChain().HistoricState(header)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -261,9 +261,9 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
return nil, nil, errors.New("hash is not currently canonical") return nil, nil, errors.New("hash is not currently canonical")
} }
stateDb, err := b.eth.BlockChain().StateAt(header.Root) stateDb, err := b.eth.BlockChain().StateAt(header)
if err != nil { if err != nil {
stateDb, err = b.eth.BlockChain().HistoricState(header.Root) stateDb, err = b.eth.BlockChain().HistoricState(header)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View file

@ -82,7 +82,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
if header == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
} }
stateDb, err := api.eth.BlockChain().StateAt(header.Root) stateDb, err := api.eth.BlockChain().StateAt(header)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
@ -167,7 +167,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if header == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", number) return state.Dump{}, fmt.Errorf("block #%d not found", number)
} }
stateDb, err = api.eth.BlockChain().StateAt(header.Root) stateDb, err = api.eth.BlockChain().StateAt(header)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
@ -177,7 +177,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if block == nil { if block == nil {
return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex()) return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex())
} }
stateDb, err = api.eth.BlockChain().StateAt(block.Root()) stateDb, err = api.eth.BlockChain().StateAt(block.Header())
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }

View file

@ -277,8 +277,8 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.OverrideBPO2 != nil { if config.OverrideBPO2 != nil {
overrides.OverrideBPO2 = config.OverrideBPO2 overrides.OverrideBPO2 = config.OverrideBPO2
} }
if config.OverrideVerkle != nil { if config.OverrideUBT != nil {
overrides.OverrideVerkle = config.OverrideVerkle overrides.OverrideUBT = config.OverrideUBT
} }
options.Overrides = &overrides options.Overrides = &overrides

View file

@ -299,7 +299,7 @@ func TestEth2NewBlock(t *testing.T) {
ethservice.BlockChain().SubscribeRemovedLogsEvent(rmLogsCh) ethservice.BlockChain().SubscribeRemovedLogsEvent(rmLogsCh)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) statedb, _ := ethservice.BlockChain().StateAt(parent.Header())
nonce := statedb.GetNonce(testAddr) nonce := statedb.GetNonce(testAddr)
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
ethservice.TxPool().Add([]*types.Transaction{tx}, true) ethservice.TxPool().Add([]*types.Transaction{tx}, true)
@ -478,7 +478,7 @@ func TestFullAPI(t *testing.T) {
) )
callback := func(parent *types.Header) { callback := func(parent *types.Header) {
statedb, _ := ethservice.BlockChain().StateAt(parent.Root) statedb, _ := ethservice.BlockChain().StateAt(parent)
nonce := statedb.GetNonce(testAddr) nonce := statedb.GetNonce(testAddr)
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
ethservice.TxPool().Add([]*types.Transaction{tx}, false) ethservice.TxPool().Add([]*types.Transaction{tx}, false)
@ -604,7 +604,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
) )
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
statedb, _ := ethservice.BlockChain().StateAt(parent.Root) statedb, _ := ethservice.BlockChain().StateAt(parent)
tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{ tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{
Nonce: statedb.GetNonce(testAddr), Nonce: statedb.GetNonce(testAddr),
Value: new(big.Int), Value: new(big.Int),
@ -1263,7 +1263,7 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
// Each block, this callback will include two txs that generate body values like logs and requests. // Each block, this callback will include two txs that generate body values like logs and requests.
callback := func(parent *types.Header) { callback := func(parent *types.Header) {
var ( var (
statedb, _ = ethservice.BlockChain().StateAt(parent.Root) statedb, _ = ethservice.BlockChain().StateAt(parent)
// Create tx to trigger log generator. // Create tx to trigger log generator.
tx1, _ = types.SignTx(types.NewContractCreation(statedb.GetNonce(testAddr), new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) tx1, _ = types.SignTx(types.NewContractCreation(statedb.GetNonce(testAddr), new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
// Create tx to trigger deposit generator. // Create tx to trigger deposit generator.

View file

@ -200,8 +200,8 @@ type Config struct {
// OverrideBPO2 (TODO: remove after the fork) // OverrideBPO2 (TODO: remove after the fork)
OverrideBPO2 *uint64 `toml:",omitempty"` OverrideBPO2 *uint64 `toml:",omitempty"`
// OverrideVerkle (TODO: remove after the fork) // OverrideUBT (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"` OverrideUBT *uint64 `toml:",omitempty"`
// EIP-7966: eth_sendRawTransactionSync timeouts // EIP-7966: eth_sendRawTransactionSync timeouts
TxSyncDefaultTimeout time.Duration `toml:",omitempty"` TxSyncDefaultTimeout time.Duration `toml:",omitempty"`

View file

@ -64,7 +64,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
OverrideOsaka *uint64 `toml:",omitempty"` OverrideOsaka *uint64 `toml:",omitempty"`
OverrideBPO1 *uint64 `toml:",omitempty"` OverrideBPO1 *uint64 `toml:",omitempty"`
OverrideBPO2 *uint64 `toml:",omitempty"` OverrideBPO2 *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideUBT *uint64 `toml:",omitempty"`
TxSyncDefaultTimeout time.Duration `toml:",omitempty"` TxSyncDefaultTimeout time.Duration `toml:",omitempty"`
TxSyncMaxTimeout time.Duration `toml:",omitempty"` TxSyncMaxTimeout time.Duration `toml:",omitempty"`
RangeLimit uint64 `toml:",omitempty"` RangeLimit uint64 `toml:",omitempty"`
@ -117,7 +117,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.OverrideOsaka = c.OverrideOsaka enc.OverrideOsaka = c.OverrideOsaka
enc.OverrideBPO1 = c.OverrideBPO1 enc.OverrideBPO1 = c.OverrideBPO1
enc.OverrideBPO2 = c.OverrideBPO2 enc.OverrideBPO2 = c.OverrideBPO2
enc.OverrideVerkle = c.OverrideVerkle enc.OverrideUBT = c.OverrideUBT
enc.TxSyncDefaultTimeout = c.TxSyncDefaultTimeout enc.TxSyncDefaultTimeout = c.TxSyncDefaultTimeout
enc.TxSyncMaxTimeout = c.TxSyncMaxTimeout enc.TxSyncMaxTimeout = c.TxSyncMaxTimeout
enc.RangeLimit = c.RangeLimit enc.RangeLimit = c.RangeLimit
@ -174,7 +174,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
OverrideOsaka *uint64 `toml:",omitempty"` OverrideOsaka *uint64 `toml:",omitempty"`
OverrideBPO1 *uint64 `toml:",omitempty"` OverrideBPO1 *uint64 `toml:",omitempty"`
OverrideBPO2 *uint64 `toml:",omitempty"` OverrideBPO2 *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideUBT *uint64 `toml:",omitempty"`
TxSyncDefaultTimeout *time.Duration `toml:",omitempty"` TxSyncDefaultTimeout *time.Duration `toml:",omitempty"`
TxSyncMaxTimeout *time.Duration `toml:",omitempty"` TxSyncMaxTimeout *time.Duration `toml:",omitempty"`
RangeLimit *uint64 `toml:",omitempty"` RangeLimit *uint64 `toml:",omitempty"`
@ -324,8 +324,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.OverrideBPO2 != nil { if dec.OverrideBPO2 != nil {
c.OverrideBPO2 = dec.OverrideBPO2 c.OverrideBPO2 = dec.OverrideBPO2
} }
if dec.OverrideVerkle != nil { if dec.OverrideUBT != nil {
c.OverrideVerkle = dec.OverrideVerkle c.OverrideUBT = dec.OverrideUBT
} }
if dec.TxSyncDefaultTimeout != nil { if dec.TxSyncDefaultTimeout != nil {
c.TxSyncDefaultTimeout = *dec.TxSyncDefaultTimeout c.TxSyncDefaultTimeout = *dec.TxSyncDefaultTimeout

View file

@ -104,7 +104,7 @@ func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.
func (b *testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { func (b *testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
if b.pending { if b.pending {
block := b.chain.GetBlockByNumber(testHead + 1) block := b.chain.GetBlockByNumber(testHead + 1)
state, _ := b.chain.StateAt(block.Root()) state, _ := b.chain.StateAt(block.Header())
return block, b.chain.GetReceiptsByHash(block.Hash()), state return block, b.chain.GetReceiptsByHash(block.Hash()), state
} }
return nil, nil, nil return nil, nil, nil

View file

@ -56,7 +56,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, base *st
// The state is available in live database, create a reference // The state is available in live database, create a reference
// on top to prevent garbage collection and return a release // on top to prevent garbage collection and return a release
// function to deref it. // function to deref it.
if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil { if statedb, err = eth.blockchain.StateAt(block.Header()); err == nil {
eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{}) eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{})
return statedb, func() { return statedb, func() {
eth.blockchain.TrieDB().Dereference(block.Root()) eth.blockchain.TrieDB().Dereference(block.Root())
@ -182,11 +182,12 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, base *st
func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) { func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) {
// Check if the requested state is available in the live chain. // Check if the requested state is available in the live chain.
statedb, err := eth.blockchain.StateAt(block.Root()) header := block.Header()
statedb, err := eth.blockchain.StateAt(header)
if err == nil { if err == nil {
return statedb, noopReleaser, nil return statedb, noopReleaser, nil
} }
statedb, err = eth.blockchain.HistoricState(block.Root()) statedb, err = eth.blockchain.HistoricState(header)
if err == nil { if err == nil {
return statedb, noopReleaser, nil return statedb, noopReleaser, nil
} }

View file

@ -1086,8 +1086,8 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig)
copy.OsakaTime = timestamp copy.OsakaTime = timestamp
canon = false canon = false
} }
if timestamp := override.VerkleTime; timestamp != nil { if timestamp := override.UBTTime; timestamp != nil {
copy.VerkleTime = timestamp copy.UBTTime = timestamp
canon = false canon = false
} }

View file

@ -152,7 +152,7 @@ func (b *testBackend) teardown() {
} }
func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) { func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) {
statedb, err := b.chain.StateAt(block.Root()) statedb, err := b.chain.StateAt(block.Header())
if err != nil { if err != nil {
return nil, nil, errStateNotFound return nil, nil, errStateNotFound
} }

View file

@ -162,7 +162,7 @@ func setupTestBlockchain(t *testing.T, genesis *core.Genesis, tx *types.Transact
if genesisBlock == nil { if genesisBlock == nil {
t.Fatalf("failed to get genesis block") t.Fatalf("failed to get genesis block")
} }
statedb, err := blockchain.StateAt(genesisBlock.Root()) statedb, err := blockchain.StateAt(genesisBlock.Header())
if err != nil { if err != nil {
t.Fatalf("failed to get state: %v", err) t.Fatalf("failed to get state: %v", err)
} }

View file

@ -572,7 +572,7 @@ func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.Bloc
if header == nil { if header == nil {
return nil, nil, errors.New("header not found") return nil, nil, errors.New("header not found")
} }
stateDb, err := b.chain.StateAt(header.Root) stateDb, err := b.chain.StateAt(header)
return stateDb, header, err return stateDb, header, err
} }
func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {

View file

@ -317,7 +317,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
if precompiles != nil { if precompiles != nil {
evm.SetPrecompiles(precompiles) evm.SetPrecompiles(precompiles)
} }
if sim.chainConfig.IsPrague(header.Number, header.Time) || sim.chainConfig.IsVerkle(header.Number, header.Time) { if sim.chainConfig.IsPrague(header.Number, header.Time) || sim.chainConfig.IsUBT(header.Number, header.Time) {
core.ProcessParentBlockHash(header.ParentHash, evm) core.ProcessParentBlockHash(header.ParentHash, evm)
} }
if header.ParentBeaconRoot != nil { if header.ParentBeaconRoot != nil {

View file

@ -80,10 +80,14 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil)) return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(header *types.Header) (*state.StateDB, error) {
return bc.statedb, nil return bc.statedb, nil
} }
func (bc *testBlockChain) Genesis() *types.Block {
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
}
func (bc *testBlockChain) HasState(root common.Hash) bool { func (bc *testBlockChain) HasState(root common.Hash) bool {
return bc.root == root return bc.root == root
} }

View file

@ -324,7 +324,7 @@ func (miner *Miner) prepareWork(ctx context.Context, genParams *generateParams,
// makeEnv creates a new environment for the sealing block. // makeEnv creates a new environment for the sealing block.
func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address, witness bool) (*environment, error) { func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address, witness bool) (*environment, error) {
// Retrieve the parent state to execute on top. // Retrieve the parent state to execute on top.
state, err := miner.chain.StateAt(parent.Root) state, err := miner.chain.StateAtForkBoundary(parent, header)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -207,7 +207,7 @@ var (
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
OsakaTime: nil, OsakaTime: nil,
VerkleTime: nil, UBTTime: nil,
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
} }
@ -263,7 +263,7 @@ var (
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
OsakaTime: nil, OsakaTime: nil,
VerkleTime: nil, UBTTime: nil,
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: nil, Ethash: nil,
Clique: &CliqueConfig{Period: 0, Epoch: 30000}, Clique: &CliqueConfig{Period: 0, Epoch: 30000},
@ -293,7 +293,7 @@ var (
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
OsakaTime: nil, OsakaTime: nil,
VerkleTime: nil, UBTTime: nil,
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
@ -323,7 +323,7 @@ var (
CancunTime: newUint64(0), CancunTime: newUint64(0),
PragueTime: newUint64(0), PragueTime: newUint64(0),
OsakaTime: newUint64(0), OsakaTime: newUint64(0),
VerkleTime: nil, UBTTime: nil,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
@ -358,7 +358,7 @@ var (
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
OsakaTime: nil, OsakaTime: nil,
VerkleTime: nil, UBTTime: nil,
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
@ -466,7 +466,7 @@ type ChainConfig struct {
BPO4Time *uint64 `json:"bpo4Time,omitempty"` // BPO4 switch time (nil = no fork, 0 = already on bpo4) BPO4Time *uint64 `json:"bpo4Time,omitempty"` // BPO4 switch time (nil = no fork, 0 = already on bpo4)
BPO5Time *uint64 `json:"bpo5Time,omitempty"` // BPO5 switch time (nil = no fork, 0 = already on bpo5) BPO5Time *uint64 `json:"bpo5Time,omitempty"` // BPO5 switch time (nil = no fork, 0 = already on bpo5)
AmsterdamTime *uint64 `json:"amsterdamTime,omitempty"` // Amsterdam switch time (nil = no fork, 0 = already on amsterdam) AmsterdamTime *uint64 `json:"amsterdamTime,omitempty"` // Amsterdam switch time (nil = no fork, 0 = already on amsterdam)
VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle) UBTTime *uint64 `json:"ubtTime,omitempty"` // UBT switch time (nil = no fork, 0 = already on UBT)
// TerminalTotalDifficulty is the amount of total difficulty reached by // TerminalTotalDifficulty is the amount of total difficulty reached by
// the network that triggers the consensus upgrade. // the network that triggers the consensus upgrade.
@ -474,18 +474,18 @@ type ChainConfig struct {
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"` DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
// EnableVerkleAtGenesis is a flag that specifies whether the network uses // EnableUBTAtGenesis is a flag that specifies whether the network uses
// the Verkle tree starting from the genesis block. If set to true, the // the Verkle tree starting from the genesis block. If set to true, the
// genesis state will be committed using the Verkle tree, eliminating the // genesis state will be committed using the Binary tree, eliminating the
// need for any Verkle transition later. // need for any Binary transition later.
// //
// This is a temporary flag only for verkle devnet testing, where verkle is // This is a temporary flag only for binary devnet testing, where binary is
// activated at genesis, and the configured activation date has already passed. // activated at genesis, and the configured activation date has already passed.
// //
// In production networks (mainnet and public testnets), verkle activation // In production networks (mainnet and public testnets), binary activation
// always occurs after the genesis block, making this flag irrelevant in // always occurs after the genesis block, making this flag irrelevant in
// those cases. // those cases.
EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"` EnableUBTAtGenesis bool `json:"enableUBTAtGenesis,omitempty"`
// Various consensus engines // Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"` Ethash *EthashConfig `json:"ethash,omitempty"`
@ -595,8 +595,8 @@ func (c *ChainConfig) String() string {
if c.AmsterdamTime != nil { if c.AmsterdamTime != nil {
result += fmt.Sprintf(", AmsterdamTime: %v", *c.AmsterdamTime) result += fmt.Sprintf(", AmsterdamTime: %v", *c.AmsterdamTime)
} }
if c.VerkleTime != nil { if c.UBTTime != nil {
result += fmt.Sprintf(", VerkleTime: %v", *c.VerkleTime) result += fmt.Sprintf(", UBTTime: %v", *c.UBTTime)
} }
result += "}" result += "}"
return result return result
@ -690,8 +690,8 @@ func (c *ChainConfig) Description() string {
if c.AmsterdamTime != nil { if c.AmsterdamTime != nil {
banner += fmt.Sprintf(" - Amsterdam: @%-10v blob: (%s)\n", *c.AmsterdamTime, c.BlobScheduleConfig.Amsterdam) banner += fmt.Sprintf(" - Amsterdam: @%-10v blob: (%s)\n", *c.AmsterdamTime, c.BlobScheduleConfig.Amsterdam)
} }
if c.VerkleTime != nil { if c.UBTTime != nil {
banner += fmt.Sprintf(" - Verkle: @%-10v blob: (%s)\n", *c.VerkleTime, c.BlobScheduleConfig.Verkle) banner += fmt.Sprintf(" - UBT: @%-10v blob: (%s)\n", *c.UBTTime, c.BlobScheduleConfig.UBT)
} }
banner += fmt.Sprintf("\nAll fork specifications can be found at https://ethereum.github.io/execution-specs/src/ethereum/forks/\n") banner += fmt.Sprintf("\nAll fork specifications can be found at https://ethereum.github.io/execution-specs/src/ethereum/forks/\n")
return banner return banner
@ -717,13 +717,13 @@ type BlobScheduleConfig struct {
Cancun *BlobConfig `json:"cancun,omitempty"` Cancun *BlobConfig `json:"cancun,omitempty"`
Prague *BlobConfig `json:"prague,omitempty"` Prague *BlobConfig `json:"prague,omitempty"`
Osaka *BlobConfig `json:"osaka,omitempty"` Osaka *BlobConfig `json:"osaka,omitempty"`
Verkle *BlobConfig `json:"verkle,omitempty"`
BPO1 *BlobConfig `json:"bpo1,omitempty"` BPO1 *BlobConfig `json:"bpo1,omitempty"`
BPO2 *BlobConfig `json:"bpo2,omitempty"` BPO2 *BlobConfig `json:"bpo2,omitempty"`
BPO3 *BlobConfig `json:"bpo3,omitempty"` BPO3 *BlobConfig `json:"bpo3,omitempty"`
BPO4 *BlobConfig `json:"bpo4,omitempty"` BPO4 *BlobConfig `json:"bpo4,omitempty"`
BPO5 *BlobConfig `json:"bpo5,omitempty"` BPO5 *BlobConfig `json:"bpo5,omitempty"`
Amsterdam *BlobConfig `json:"amsterdam,omitempty"` Amsterdam *BlobConfig `json:"amsterdam,omitempty"`
UBT *BlobConfig `json:"ubt,omitempty"`
} }
// IsHomestead returns whether num is either equal to the homestead block or greater. // IsHomestead returns whether num is either equal to the homestead block or greater.
@ -866,12 +866,12 @@ func (c *ChainConfig) IsAmsterdam(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.AmsterdamTime, time) return c.IsLondon(num) && isTimestampForked(c.AmsterdamTime, time)
} }
// IsVerkle returns whether time is either equal to the Verkle fork time or greater. // IsUBT returns whether time is either equal to the Verkle fork time or greater.
func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool { func (c *ChainConfig) IsUBT(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time) return c.IsLondon(num) && isTimestampForked(c.UBTTime, time)
} }
// IsVerkleGenesis checks whether the verkle fork is activated at the genesis block. // IsUBTGenesis checks whether the verkle fork is activated at the genesis block.
// //
// Verkle mode is considered enabled if the verkle fork time is configured, // Verkle mode is considered enabled if the verkle fork time is configured,
// regardless of whether the local time has surpassed the fork activation time. // regardless of whether the local time has surpassed the fork activation time.
@ -881,13 +881,13 @@ func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
// In production networks (mainnet and public testnets), verkle activation // In production networks (mainnet and public testnets), verkle activation
// always occurs after the genesis block, making this function irrelevant in // always occurs after the genesis block, making this function irrelevant in
// those cases. // those cases.
func (c *ChainConfig) IsVerkleGenesis() bool { func (c *ChainConfig) IsUBTGenesis() bool {
return c.EnableVerkleAtGenesis return c.EnableUBTAtGenesis
} }
// IsEIP4762 returns whether eip 4762 has been activated at given block. // IsEIP4762 returns whether eip 4762 has been activated at given block.
func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool { func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool {
return c.IsVerkle(num, time) return c.IsUBT(num, time)
} }
// CheckCompatible checks whether scheduled fork transitions have been imported // CheckCompatible checks whether scheduled fork transitions have been imported
@ -945,7 +945,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "cancunTime", timestamp: c.CancunTime, optional: true}, {name: "cancunTime", timestamp: c.CancunTime, optional: true},
{name: "pragueTime", timestamp: c.PragueTime, optional: true}, {name: "pragueTime", timestamp: c.PragueTime, optional: true},
{name: "osakaTime", timestamp: c.OsakaTime, optional: true}, {name: "osakaTime", timestamp: c.OsakaTime, optional: true},
{name: "verkleTime", timestamp: c.VerkleTime, optional: true}, {name: "ubtTime", timestamp: c.UBTTime, optional: true},
{name: "bpo1", timestamp: c.BPO1Time, optional: true}, {name: "bpo1", timestamp: c.BPO1Time, optional: true},
{name: "bpo2", timestamp: c.BPO2Time, optional: true}, {name: "bpo2", timestamp: c.BPO2Time, optional: true},
{name: "bpo3", timestamp: c.BPO3Time, optional: true}, {name: "bpo3", timestamp: c.BPO3Time, optional: true},
@ -1104,8 +1104,8 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
if isForkTimestampIncompatible(c.OsakaTime, newcfg.OsakaTime, headTimestamp) { if isForkTimestampIncompatible(c.OsakaTime, newcfg.OsakaTime, headTimestamp) {
return newTimestampCompatError("Osaka fork timestamp", c.OsakaTime, newcfg.OsakaTime) return newTimestampCompatError("Osaka fork timestamp", c.OsakaTime, newcfg.OsakaTime)
} }
if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) { if isForkTimestampIncompatible(c.UBTTime, newcfg.UBTTime, headTimestamp) {
return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime) return newTimestampCompatError("UBT fork timestamp", c.UBTTime, newcfg.UBTTime)
} }
if isForkTimestampIncompatible(c.BPO1Time, newcfg.BPO1Time, headTimestamp) { if isForkTimestampIncompatible(c.BPO1Time, newcfg.BPO1Time, headTimestamp) {
return newTimestampCompatError("BPO1 fork timestamp", c.BPO1Time, newcfg.BPO1Time) return newTimestampCompatError("BPO1 fork timestamp", c.BPO1Time, newcfg.BPO1Time)
@ -1380,14 +1380,14 @@ type Rules struct {
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon bool IsBerlin, IsLondon bool
IsMerge, IsShanghai, IsCancun, IsPrague, IsOsaka bool IsMerge, IsShanghai, IsCancun, IsPrague, IsOsaka bool
IsAmsterdam, IsVerkle bool IsAmsterdam, IsUBT bool
} }
// Rules ensures c's ChainID is not nil. // Rules ensures c's ChainID is not nil.
func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules { func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules {
// disallow setting Merge out of order // disallow setting Merge out of order
isMerge = isMerge && c.IsLondon(num) isMerge = isMerge && c.IsLondon(num)
isVerkle := isMerge && c.IsVerkle(num, timestamp) isUBT := isMerge && c.IsUBT(num, timestamp)
return Rules{ return Rules{
IsHomestead: c.IsHomestead(num), IsHomestead: c.IsHomestead(num),
IsEIP150: c.IsEIP150(num), IsEIP150: c.IsEIP150(num),
@ -1398,7 +1398,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsPetersburg: c.IsPetersburg(num), IsPetersburg: c.IsPetersburg(num),
IsIstanbul: c.IsIstanbul(num), IsIstanbul: c.IsIstanbul(num),
IsBerlin: c.IsBerlin(num), IsBerlin: c.IsBerlin(num),
IsEIP2929: c.IsBerlin(num) && !isVerkle, IsEIP2929: c.IsBerlin(num) && !isUBT,
IsLondon: c.IsLondon(num), IsLondon: c.IsLondon(num),
IsMerge: isMerge, IsMerge: isMerge,
IsShanghai: isMerge && c.IsShanghai(num, timestamp), IsShanghai: isMerge && c.IsShanghai(num, timestamp),
@ -1406,7 +1406,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsPrague: isMerge && c.IsPrague(num, timestamp), IsPrague: isMerge && c.IsPrague(num, timestamp),
IsOsaka: isMerge && c.IsOsaka(num, timestamp), IsOsaka: isMerge && c.IsOsaka(num, timestamp),
IsAmsterdam: isMerge && c.IsAmsterdam(num, timestamp), IsAmsterdam: isMerge && c.IsAmsterdam(num, timestamp),
IsVerkle: isVerkle, IsUBT: isUBT,
IsEIP4762: isVerkle, IsEIP4762: isUBT,
} }
} }

View file

@ -126,10 +126,10 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
tconf = &triedb.Config{ tconf = &triedb.Config{
Preimages: true, Preimages: true,
IsVerkle: gspec.Config.VerkleTime != nil && *gspec.Config.VerkleTime <= gspec.Timestamp, IsUBT: gspec.Config.UBTTime != nil && *gspec.Config.UBTTime <= gspec.Timestamp,
} }
) )
if scheme == rawdb.PathScheme || tconf.IsVerkle { if scheme == rawdb.PathScheme || tconf.IsUBT {
tconf.PathDB = pathdb.Defaults tconf.PathDB = pathdb.Defaults
} else { } else {
tconf.HashDB = hashdb.Defaults tconf.HashDB = hashdb.Defaults

View file

@ -774,7 +774,7 @@ var Forks = map[string]*params.ChainConfig{
MergeNetsplitBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
VerkleTime: u64(0), UBTTime: u64(0),
}, },
} }

View file

@ -544,7 +544,7 @@ 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, nil).WithSnapshot(snaps) sdb = state.NewMPTDatabase(triedb, nil).WithSnapshot(snaps)
statedb, _ = state.New(root, sdb) statedb, _ = state.New(root, sdb)
return StateTestState{statedb, triedb, snaps} return StateTestState{statedb, triedb, snaps}
} }

View file

@ -377,8 +377,8 @@ func (t *BinaryTrie) Copy() *BinaryTrie {
} }
} }
// IsVerkle returns true if the trie is a Verkle tree. // IsUBT returns true if the trie is a Verkle tree.
func (t *BinaryTrie) IsVerkle() bool { func (t *BinaryTrie) IsUBT() bool {
// TODO @gballet This is technically NOT a verkle tree, but it has the same // TODO @gballet This is technically NOT a verkle tree, but it has the same
// behavior and basic structure, so for all intents and purposes, it can be // behavior and basic structure, so for all intents and purposes, it can be
// treated as such. Rename this when verkle gets removed. // treated as such. Rename this when verkle gets removed.

View file

@ -324,6 +324,6 @@ func (t *StateTrie) MustNodeIterator(start []byte) NodeIterator {
return t.trie.MustNodeIterator(start) return t.trie.MustNodeIterator(start)
} }
func (t *StateTrie) IsVerkle() bool { func (t *StateTrie) IsUBT() bool {
return false return false
} }

View file

@ -202,8 +202,8 @@ func (t *TransitionTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
panic("not implemented") // TODO: Implement panic("not implemented") // TODO: Implement
} }
// IsVerkle returns true if the trie is verkle-tree based // IsUBT returns true if the trie is verkle-tree based
func (t *TransitionTrie) IsVerkle() bool { func (t *TransitionTrie) IsUBT() bool {
// For all intents and purposes, the calling code should treat this as a verkle trie // For all intents and purposes, the calling code should treat this as a verkle trie
return true return true
} }

View file

@ -32,7 +32,7 @@ import (
// Config defines all necessary options for database. // Config defines all necessary options for database.
type Config struct { type Config struct {
Preimages bool // Flag whether the preimage of node key is recorded Preimages bool // Flag whether the preimage of node key is recorded
IsVerkle bool // Flag whether the db is holding a verkle tree IsUBT bool // Flag whether the db is holding a verkle tree
HashDB *hashdb.Config // Configs for hash-based scheme HashDB *hashdb.Config // Configs for hash-based scheme
PathDB *pathdb.Config // Configs for experimental path-based scheme PathDB *pathdb.Config // Configs for experimental path-based scheme
} }
@ -41,15 +41,15 @@ type Config struct {
// default settings. // default settings.
var HashDefaults = &Config{ var HashDefaults = &Config{
Preimages: false, Preimages: false,
IsVerkle: false, IsUBT: false,
HashDB: hashdb.Defaults, HashDB: hashdb.Defaults,
} }
// VerkleDefaults represents a config for holding verkle trie data // UBTDefaults represents a config for holding verkle trie data
// using path-based scheme with default settings. // using path-based scheme with default settings.
var VerkleDefaults = &Config{ var UBTDefaults = &Config{
Preimages: false, Preimages: false,
IsVerkle: true, IsUBT: true,
PathDB: pathdb.Defaults, PathDB: pathdb.Defaults,
} }
@ -109,7 +109,7 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
log.Crit("Both 'hash' and 'path' mode are configured") log.Crit("Both 'hash' and 'path' mode are configured")
} }
if config.PathDB != nil { if config.PathDB != nil {
db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle) db.backend = pathdb.New(diskdb, config.PathDB, config.IsUBT)
} else { } else {
db.backend = hashdb.New(diskdb, config.HashDB) db.backend = hashdb.New(diskdb, config.HashDB)
} }
@ -375,9 +375,9 @@ func (db *Database) IndexProgress() (uint64, uint64, error) {
return pdb.IndexProgress() return pdb.IndexProgress()
} }
// IsVerkle returns the indicator if the database is holding a verkle tree. // IsUBT returns the indicator if the database is holding a verkle tree.
func (db *Database) IsVerkle() bool { func (db *Database) IsUBT() bool {
return db.config.IsVerkle return db.config.IsUBT
} }
// Disk returns the underlying disk database. // Disk returns the underlying disk database.

View file

@ -100,7 +100,7 @@ func merkleNodeHasher(blob []byte) (common.Hash, error) {
// binaryNodeHasher computes the hash of the given verkle node. // binaryNodeHasher computes the hash of the given verkle node.
func binaryNodeHasher(blob []byte) (common.Hash, error) { func binaryNodeHasher(blob []byte) (common.Hash, error) {
if len(blob) == 0 { if len(blob) == 0 {
return types.EmptyVerkleHash, nil return types.EmptyBinaryHash, nil
} }
n, err := bintrie.DeserializeNode(blob, 0) n, err := bintrie.DeserializeNode(blob, 0)
if err != nil { if err != nil {
@ -127,7 +127,7 @@ type Database struct {
// the shutdown to reject all following unexpected mutations. // the shutdown to reject all following unexpected mutations.
readOnly bool // Flag if database is opened in read only mode readOnly bool // Flag if database is opened in read only mode
waitSync bool // Flag if database is deactivated due to initial state sync waitSync bool // Flag if database is deactivated due to initial state sync
isVerkle bool // Flag if database is used for verkle tree isUBT bool // Flag if database is used for verkle tree
hasher nodeHasher // Trie node hasher hasher nodeHasher // Trie node hasher
config *Config // Configuration for database config *Config // Configuration for database
@ -146,7 +146,7 @@ type Database struct {
// New attempts to load an already existing layer from a persistent key-value // New attempts to load an already existing layer from a persistent key-value
// store (with a number of memory layers from a journal). If the journal is not // store (with a number of memory layers from a journal). If the journal is not
// matched with the base persistent layer, all the recorded diff layers are discarded. // matched with the base persistent layer, all the recorded diff layers are discarded.
func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database { func New(diskdb ethdb.Database, config *Config, isUBT bool) *Database {
if config == nil { if config == nil {
config = Defaults config = Defaults
} }
@ -154,7 +154,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
db := &Database{ db := &Database{
readOnly: config.ReadOnly, readOnly: config.ReadOnly,
isVerkle: isVerkle, isUBT: isUBT,
config: config, config: config,
diskdb: diskdb, diskdb: diskdb,
hasher: merkleNodeHasher, hasher: merkleNodeHasher,
@ -164,7 +164,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
// important to note that the introduction of a prefix won't lead to // important to note that the introduction of a prefix won't lead to
// substantial storage overhead, as the underlying database will efficiently // substantial storage overhead, as the underlying database will efficiently
// compress the shared key prefix. // compress the shared key prefix.
if isVerkle { if isUBT {
db.diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix)) db.diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix))
db.hasher = binaryNodeHasher db.hasher = binaryNodeHasher
} }
@ -174,7 +174,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
// Repair the history, which might not be aligned with the persistent // Repair the history, which might not be aligned with the persistent
// state in the key-value store due to an unclean shutdown. // state in the key-value store due to an unclean shutdown.
states, trienodes, err := repairHistory(db.diskdb, isVerkle, db.config.ReadOnly, db.tree.bottom().stateID(), db.config.TrienodeHistory >= 0) states, trienodes, err := repairHistory(db.diskdb, isUBT, db.config.ReadOnly, db.tree.bottom().stateID(), db.config.TrienodeHistory >= 0)
if err != nil { if err != nil {
log.Crit("Failed to repair history", "err", err) log.Crit("Failed to repair history", "err", err)
} }
@ -196,7 +196,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
db.setHistoryIndexer() db.setHistoryIndexer()
fields := config.fields() fields := config.fields()
if db.isVerkle { if db.isUBT {
fields = append(fields, "verkle", true) fields = append(fields, "verkle", true)
} }
log.Info("Initialized path database", fields...) log.Info("Initialized path database", fields...)
@ -265,7 +265,7 @@ func (db *Database) setStateGenerator() error {
// - the database is opened in read only mode // - the database is opened in read only mode
// - the snapshot build is explicitly disabled // - the snapshot build is explicitly disabled
// - the database is opened in verkle tree mode // - the database is opened in verkle tree mode
noBuild := db.readOnly || db.config.SnapshotNoBuild || db.isVerkle noBuild := db.readOnly || db.config.SnapshotNoBuild || db.isUBT
// Construct the generator and link it to the disk layer, ensuring that the // Construct the generator and link it to the disk layer, ensuring that the
// generation progress is resolved to prevent accessing uncovered states // generation progress is resolved to prevent accessing uncovered states
@ -408,7 +408,7 @@ func (db *Database) Enable(root common.Hash) error {
// Re-construct a new disk layer backed by persistent state // Re-construct a new disk layer backed by persistent state
// and schedule the state snapshot generation if it's permitted. // and schedule the state snapshot generation if it's permitted.
db.tree.init(generateSnapshot(db, root, db.isVerkle || db.config.SnapshotNoBuild)) db.tree.init(generateSnapshot(db, root, db.isUBT || db.config.SnapshotNoBuild))
// After snap sync, the state of the database may have changed completely. // After snap sync, the state of the database may have changed completely.
// To ensure the history indexer always matches the current state, we must: // To ensure the history indexer always matches the current state, we must:
@ -586,7 +586,7 @@ func (db *Database) journalPath() string {
return "" return ""
} }
var fname string var fname string
if db.isVerkle { if db.isUBT {
fname = fmt.Sprintf("verkle.journal") fname = fmt.Sprintf("verkle.journal")
} else { } else {
fname = fmt.Sprintf("merkle.journal") fname = fmt.Sprintf("merkle.journal")

View file

@ -143,7 +143,7 @@ type testerConfig struct {
layers int // Number of state transitions to generate for layers int // Number of state transitions to generate for
enableIndex bool // Enable state history indexing or not enableIndex bool // Enable state history indexing or not
journalDir string // Directory path for persisting journal files journalDir string // Directory path for persisting journal files
isVerkle bool // Enables Verkle trie mode if true isUBT bool // Enables Verkle trie mode if true
writeBuffer *int // Optional, the size of memory allocated for write buffer writeBuffer *int // Optional, the size of memory allocated for write buffer
trieCache *int // Optional, the size of memory allocated for trie cache trieCache *int // Optional, the size of memory allocated for trie cache
@ -183,7 +183,7 @@ func newTester(t *testing.T, config *testerConfig) *tester {
NoAsyncFlush: true, NoAsyncFlush: true,
JournalDirectory: config.journalDir, JournalDirectory: config.journalDir,
NoHistoryIndexDelay: true, NoHistoryIndexDelay: true,
}, config.isVerkle) }, config.isUBT)
obj = &tester{ obj = &tester{
db: db, db: db,

View file

@ -376,7 +376,7 @@ func syncHistory(stores ...ethdb.AncientWriter) error {
// persistent state may appear if the trienode history was disabled during the // persistent state may appear if the trienode history was disabled during the
// previous run. This process detects and resolves such gaps, preventing // previous run. This process detects and resolves such gaps, preventing
// unexpected panics. // unexpected panics.
func repairHistory(db ethdb.Database, isVerkle bool, readOnly bool, stateID uint64, enableTrienode bool) (ethdb.ResettableAncientStore, ethdb.ResettableAncientStore, error) { func repairHistory(db ethdb.Database, isUBT bool, readOnly bool, stateID uint64, enableTrienode bool) (ethdb.ResettableAncientStore, ethdb.ResettableAncientStore, error) {
ancient, err := db.AncientDatadir() ancient, err := db.AncientDatadir()
if err != nil { if err != nil {
// TODO error out if ancient store is disabled. A tons of unit tests // TODO error out if ancient store is disabled. A tons of unit tests
@ -386,7 +386,7 @@ func repairHistory(db ethdb.Database, isVerkle bool, readOnly bool, stateID uint
} }
// State history is mandatory as it is the key component that ensures // State history is mandatory as it is the key component that ensures
// resilience to deep reorgs. // resilience to deep reorgs.
states, err := rawdb.NewStateFreezer(ancient, isVerkle, readOnly) states, err := rawdb.NewStateFreezer(ancient, isUBT, readOnly)
if err != nil { if err != nil {
log.Crit("Failed to open state history freezer", "err", err) log.Crit("Failed to open state history freezer", "err", err)
} }
@ -395,7 +395,7 @@ func repairHistory(db ethdb.Database, isVerkle bool, readOnly bool, stateID uint
// node with state proofs. // node with state proofs.
var trienodes ethdb.ResettableAncientStore var trienodes ethdb.ResettableAncientStore
if enableTrienode { if enableTrienode {
trienodes, err = rawdb.NewTrienodeFreezer(ancient, isVerkle, readOnly) trienodes, err = rawdb.NewTrienodeFreezer(ancient, isUBT, readOnly)
if err != nil { if err != nil {
log.Crit("Failed to open trienode history freezer", "err", err) log.Crit("Failed to open trienode history freezer", "err", err)
} }

View file

@ -55,9 +55,9 @@ func TestLayerCap(t *testing.T) {
layers: 2, layers: 2,
base: common.Hash{0x2}, base: common.Hash{0x2},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x2}: {}, {0x2}: {},
common.Hash{0x3}: {}, {0x3}: {},
common.Hash{0x4}: {}, {0x4}: {},
}, },
}, },
{ {
@ -76,8 +76,8 @@ func TestLayerCap(t *testing.T) {
layers: 1, layers: 1,
base: common.Hash{0x3}, base: common.Hash{0x3},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x3}: {}, {0x3}: {},
common.Hash{0x4}: {}, {0x4}: {},
}, },
}, },
{ {
@ -96,7 +96,7 @@ func TestLayerCap(t *testing.T) {
layers: 0, layers: 0,
base: common.Hash{0x4}, base: common.Hash{0x4},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x4}: {}, {0x4}: {},
}, },
}, },
{ {
@ -119,9 +119,9 @@ func TestLayerCap(t *testing.T) {
layers: 2, layers: 2,
base: common.Hash{0x2a}, base: common.Hash{0x2a},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x4a}: {}, {0x4a}: {},
common.Hash{0x3a}: {}, {0x3a}: {},
common.Hash{0x2a}: {}, {0x2a}: {},
}, },
}, },
{ {
@ -144,8 +144,8 @@ func TestLayerCap(t *testing.T) {
layers: 1, layers: 1,
base: common.Hash{0x3a}, base: common.Hash{0x3a},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x4a}: {}, {0x4a}: {},
common.Hash{0x3a}: {}, {0x3a}: {},
}, },
}, },
{ {
@ -168,11 +168,11 @@ func TestLayerCap(t *testing.T) {
layers: 2, layers: 2,
base: common.Hash{0x2}, base: common.Hash{0x2},
snapshot: map[common.Hash]struct{}{ snapshot: map[common.Hash]struct{}{
common.Hash{0x4a}: {}, {0x4a}: {},
common.Hash{0x3a}: {}, {0x3a}: {},
common.Hash{0x4b}: {}, {0x4b}: {},
common.Hash{0x3b}: {}, {0x3b}: {},
common.Hash{0x2}: {}, {0x2}: {},
}, },
}, },
} }
@ -261,7 +261,7 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
}, },
}, },
@ -271,11 +271,11 @@ func TestDescendant(t *testing.T) {
tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false)) tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
common.Hash{0x3}: {}, common.Hash{0x3}: {},
}, },
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3}: {}, common.Hash{0x3}: {},
}, },
}, },
@ -291,16 +291,16 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x3}: { {0x3}: {
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
}, },
@ -310,11 +310,11 @@ func TestDescendant(t *testing.T) {
tr.cap(common.Hash{0x4}, 2) tr.cap(common.Hash{0x4}, 2)
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x3}: { {0x3}: {
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
}, },
@ -330,16 +330,16 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x3}: { {0x3}: {
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
}, },
@ -349,7 +349,7 @@ func TestDescendant(t *testing.T) {
tr.cap(common.Hash{0x4}, 1) tr.cap(common.Hash{0x4}, 1)
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x3}: { {0x3}: {
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
}, },
@ -365,16 +365,16 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3}: {}, common.Hash{0x3}: {},
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
common.Hash{0x3}: { {0x3}: {
common.Hash{0x4}: {}, common.Hash{0x4}: {},
}, },
}, },
@ -400,7 +400,7 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2a}: {}, common.Hash{0x2a}: {},
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
@ -408,18 +408,18 @@ func TestDescendant(t *testing.T) {
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x2a}: { {0x2a}: {
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x2b}: { {0x2b}: {
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x3b}: { {0x3b}: {
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
}, },
@ -429,11 +429,11 @@ func TestDescendant(t *testing.T) {
tr.cap(common.Hash{0x4a}, 2) tr.cap(common.Hash{0x4a}, 2)
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x2a}: { {0x2a}: {
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
}, },
@ -453,7 +453,7 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2a}: {}, common.Hash{0x2a}: {},
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
@ -461,18 +461,18 @@ func TestDescendant(t *testing.T) {
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x2a}: { {0x2a}: {
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x2b}: { {0x2b}: {
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x3b}: { {0x3b}: {
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
}, },
@ -482,7 +482,7 @@ func TestDescendant(t *testing.T) {
tr.cap(common.Hash{0x4a}, 1) tr.cap(common.Hash{0x4a}, 1)
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
}, },
@ -501,23 +501,23 @@ func TestDescendant(t *testing.T) {
return tr return tr
}, },
snapshotA: map[common.Hash]map[common.Hash]struct{}{ snapshotA: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: { {0x1}: {
common.Hash{0x2}: {}, common.Hash{0x2}: {},
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x3b}: { {0x3b}: {
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
}, },
@ -528,16 +528,16 @@ func TestDescendant(t *testing.T) {
tr.cap(common.Hash{0x4a}, 2) tr.cap(common.Hash{0x4a}, 2)
}, },
snapshotB: map[common.Hash]map[common.Hash]struct{}{ snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x2}: { {0x2}: {
common.Hash{0x3a}: {}, common.Hash{0x3a}: {},
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
common.Hash{0x3b}: {}, common.Hash{0x3b}: {},
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
common.Hash{0x3a}: { {0x3a}: {
common.Hash{0x4a}: {}, common.Hash{0x4a}: {},
}, },
common.Hash{0x3b}: { {0x3b}: {
common.Hash{0x4b}: {}, common.Hash{0x4b}: {},
}, },
}, },

View file

@ -177,7 +177,7 @@ func (db *Database) NodeReader(root common.Hash) (database.NodeReader, error) {
return &reader{ return &reader{
db: db, db: db,
state: root, state: root,
noHashCheck: db.isVerkle, noHashCheck: db.isUBT,
layer: layer, layer: layer,
}, nil }, nil
} }