core/state: state reader abstraction (#29761)
This pull request introduces a state.Reader interface for state accessing. The interface could be implemented in various ways. It can be pure trie only reader, or the combination of trie and state snapshot. What's more, this interface allows us to have more flexibility in the future, e.g. the archive reader (for accessing archive state). Additionally, this pull request removes the following metrics - `chain/snapshot/account/reads` - `chain/snapshot/storage/reads`
This commit is contained in:
parent
23973bd3a0
commit
623b17ba20
|
@ -403,7 +403,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
}
|
}
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
statedb, err = state.New(root, statedb.Database(), nil)
|
statedb, err = state.New(root, statedb.Database())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
||||||
}
|
}
|
||||||
|
@ -412,8 +412,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
||||||
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
|
||||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
sdb := state.NewDatabase(tdb, nil)
|
||||||
|
statedb, _ := state.New(types.EmptyRootHash, sdb)
|
||||||
for addr, a := range accounts {
|
for addr, a := range accounts {
|
||||||
statedb.SetCode(addr, a.Code)
|
statedb.SetCode(addr, a.Code)
|
||||||
statedb.SetNonce(addr, a.Nonce)
|
statedb.SetNonce(addr, a.Nonce)
|
||||||
|
@ -424,7 +425,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
|
||||||
}
|
}
|
||||||
// Commit and re-open to start with a clean state.
|
// Commit and re-open to start with a clean state.
|
||||||
root, _ := statedb.Commit(0, false)
|
root, _ := statedb.Commit(0, false)
|
||||||
statedb, _ = state.New(root, sdb, nil)
|
statedb, _ = state.New(root, sdb)
|
||||||
return statedb
|
return statedb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,8 +155,8 @@ func runCmd(ctx *cli.Context) error {
|
||||||
})
|
})
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
genesis := genesisConfig.MustCommit(db, triedb)
|
genesis := genesisConfig.MustCommit(db, triedb)
|
||||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
sdb := state.NewDatabase(triedb, nil)
|
||||||
statedb, _ = state.New(genesis.Root(), sdb, nil)
|
statedb, _ = state.New(genesis.Root(), sdb)
|
||||||
chainConfig = genesisConfig.Config
|
chainConfig = genesisConfig.Config
|
||||||
|
|
||||||
if ctx.String(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
|
@ -277,7 +277,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
fmt.Printf("Failed to commit changes %v\n", err)
|
fmt.Printf("Failed to commit changes %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dumpdb, err := state.New(root, sdb, nil)
|
dumpdb, err := state.New(root, sdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to open statedb %v\n", err)
|
fmt.Printf("Failed to open statedb %v\n", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -107,7 +107,7 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error {
|
||||||
result.Root = &root
|
result.Root = &root
|
||||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||||
if dump { // Dump any state to aid debugging
|
if dump { // Dump any state to aid debugging
|
||||||
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
|
cpy, _ := state.New(root, tstate.StateDB.Database())
|
||||||
dump := cpy.RawDump(nil)
|
dump := cpy.RawDump(nil)
|
||||||
result.State = &dump
|
result.State = &dump
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,7 +584,7 @@ func dump(ctx *cli.Context) error {
|
||||||
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
|
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
state, err := state.New(root, state.NewDatabase(triedb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,14 +72,11 @@ var (
|
||||||
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
|
||||||
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)
|
||||||
|
|
||||||
snapshotAccountReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/account/reads", nil)
|
|
||||||
snapshotStorageReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/storage/reads", nil)
|
|
||||||
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
|
||||||
|
|
||||||
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
|
accountReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/account/single/reads", nil)
|
||||||
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
|
storageReadSingleTimer = metrics.NewRegisteredResettingTimer("chain/storage/single/reads", nil)
|
||||||
|
|
||||||
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
|
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
||||||
|
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
|
||||||
|
|
||||||
blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
|
blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
|
||||||
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
|
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
|
||||||
|
@ -220,7 +217,7 @@ type BlockChain struct {
|
||||||
lastWrite uint64 // Last block when the state was flushed
|
lastWrite uint64 // Last block when the state was flushed
|
||||||
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
|
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
|
||||||
triedb *triedb.Database // The database handler for maintaining trie nodes.
|
triedb *triedb.Database // The database handler for maintaining trie nodes.
|
||||||
stateCache state.Database // State database to reuse between imports (contains state cache)
|
statedb *state.CachingDB // State database to reuse between imports (contains state cache)
|
||||||
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
|
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled
|
||||||
|
|
||||||
hc *HeaderChain
|
hc *HeaderChain
|
||||||
|
@ -311,7 +308,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
||||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
bc.statedb = state.NewDatabase(bc.triedb, nil)
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc)
|
bc.validator = NewBlockValidator(chainConfig, bc)
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
bc.processor = NewStateProcessor(chainConfig, bc.hc)
|
bc.processor = NewStateProcessor(chainConfig, bc.hc)
|
||||||
|
@ -449,7 +446,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
AsyncBuild: !bc.cacheConfig.SnapshotWait,
|
||||||
}
|
}
|
||||||
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)
|
||||||
|
|
||||||
|
// Re-initialize the state database with snapshot
|
||||||
|
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewind the chain in case of an incompatible config upgrade.
|
// Rewind the chain in case of an incompatible config upgrade.
|
||||||
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
||||||
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
||||||
|
@ -1767,7 +1768,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
}
|
}
|
||||||
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
|
statedb, err := state.New(parent.Root, bc.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
@ -1793,7 +1794,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
var followupInterrupt atomic.Bool
|
var followupInterrupt atomic.Bool
|
||||||
if !bc.cacheConfig.TrieCleanNoPrefetch {
|
if !bc.cacheConfig.TrieCleanNoPrefetch {
|
||||||
if followup, err := it.peek(); followup != nil && err == nil {
|
if followup, err := it.peek(); followup != nil && err == nil {
|
||||||
throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps)
|
throwaway, _ := state.New(parent.Root, bc.statedb)
|
||||||
|
|
||||||
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
|
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
|
||||||
// Disable tracing for prefetcher executions.
|
// Disable tracing for prefetcher executions.
|
||||||
|
@ -1914,26 +1915,21 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
proctime := time.Since(start) // processing + validation
|
proctime := time.Since(start) // processing + validation
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||||
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
|
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
|
||||||
snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing)
|
|
||||||
snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing)
|
|
||||||
|
|
||||||
accountRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read
|
|
||||||
storageRead := statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read
|
|
||||||
if statedb.AccountLoaded != 0 {
|
if statedb.AccountLoaded != 0 {
|
||||||
accountReadSingleTimer.Update(accountRead / time.Duration(statedb.AccountLoaded))
|
accountReadSingleTimer.Update(statedb.AccountReads / time.Duration(statedb.AccountLoaded))
|
||||||
}
|
}
|
||||||
if statedb.StorageLoaded != 0 {
|
if statedb.StorageLoaded != 0 {
|
||||||
storageReadSingleTimer.Update(storageRead / time.Duration(statedb.StorageLoaded))
|
storageReadSingleTimer.Update(statedb.StorageReads / time.Duration(statedb.StorageLoaded))
|
||||||
}
|
}
|
||||||
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
|
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
|
||||||
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
|
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
|
||||||
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
|
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
|
||||||
triehash := statedb.AccountHashes // The time spent on tries hashing
|
triehash := statedb.AccountHashes // The time spent on tries hashing
|
||||||
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
||||||
blockExecutionTimer.Update(ptime - (accountRead + storageRead)) // The time spent on EVM processing
|
blockExecutionTimer.Update(ptime - (statedb.AccountReads + statedb.StorageReads)) // The time spent on EVM processing
|
||||||
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
||||||
|
|
||||||
// Write the block to the chain and get the status.
|
// Write the block to the chain and get the status.
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -308,7 +308,7 @@ func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||||
|
|
||||||
// HasState checks if state trie is fully present in the database or not.
|
// HasState checks if state trie is fully present in the database or not.
|
||||||
func (bc *BlockChain) HasState(hash common.Hash) bool {
|
func (bc *BlockChain) HasState(hash common.Hash) bool {
|
||||||
_, err := bc.stateCache.OpenTrie(hash)
|
_, err := bc.statedb.OpenTrie(hash)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,12 +341,9 @@ func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
|
||||||
// If the code doesn't exist in the in-memory cache, check the storage with
|
// If the code doesn't exist in the in-memory cache, check the storage with
|
||||||
// new code scheme.
|
// new code scheme.
|
||||||
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
||||||
type codeReader interface {
|
|
||||||
ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error)
|
|
||||||
}
|
|
||||||
// TODO(rjl493456442) The associated account address is also required
|
// TODO(rjl493456442) The associated account address is also required
|
||||||
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
||||||
return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash)
|
return bc.statedb.ContractCodeWithPrefix(common.Address{}, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// State returns a new mutable state based on the current HEAD block.
|
// State returns a new mutable state based on the current HEAD block.
|
||||||
|
@ -356,7 +353,7 @@ func (bc *BlockChain) State() (*state.StateDB, error) {
|
||||||
|
|
||||||
// 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(root common.Hash) (*state.StateDB, error) {
|
||||||
return state.New(root, bc.stateCache, bc.snaps)
|
return state.New(root, bc.statedb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config retrieves the chain's fork configuration.
|
// Config retrieves the chain's fork configuration.
|
||||||
|
@ -382,7 +379,7 @@ func (bc *BlockChain) Processor() Processor {
|
||||||
|
|
||||||
// StateCache returns the caching database underpinning the blockchain instance.
|
// StateCache returns the caching database underpinning the blockchain instance.
|
||||||
func (bc *BlockChain) StateCache() state.Database {
|
func (bc *BlockChain) StateCache() state.Database {
|
||||||
return bc.stateCache
|
return bc.statedb
|
||||||
}
|
}
|
||||||
|
|
||||||
// GasLimit returns the gas limit of the current HEAD block.
|
// GasLimit returns the gas limit of the current HEAD block.
|
||||||
|
|
|
@ -2040,7 +2040,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
dbconfig.HashDB = hashdb.Defaults
|
dbconfig.HashDB = hashdb.Defaults
|
||||||
}
|
}
|
||||||
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
|
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
|
||||||
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
|
chain.statedb = state.NewDatabase(chain.triedb, chain.snaps)
|
||||||
|
|
||||||
// Force run a freeze cycle
|
// Force run a freeze cycle
|
||||||
type freezer interface {
|
type freezer interface {
|
||||||
|
|
|
@ -160,7 +160,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil)
|
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,7 +379,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil)
|
statedb, err := state.New(parent.Root(), state.NewDatabase(triedb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, trdb), nil)
|
statedb, err := state.New(parent.Root(), state.NewDatabase(trdb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,8 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
||||||
}
|
}
|
||||||
// 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.
|
||||||
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
|
db := rawdb.NewMemoryDatabase()
|
||||||
statedb, err := state.New(types.EmptyRootHash, db, nil)
|
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb.NewDatabase(db, config), nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
@ -147,8 +147,8 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
|
||||||
|
|
||||||
// flushAlloc is very similar with hash, but the main difference is all the
|
// flushAlloc is very similar with hash, but the main difference is all the
|
||||||
// generated states will be persisted into the given database.
|
// generated states will be persisted into the given database.
|
||||||
func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Database) (common.Hash, error) {
|
func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, error) {
|
||||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
|
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(triedb, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
||||||
return nil, errors.New("can't start clique chain without signers")
|
return nil, errors.New("can't start clique chain without signers")
|
||||||
}
|
}
|
||||||
// flush the data to disk and compute the state root
|
// flush the data to disk and compute the state root
|
||||||
root, err := flushAlloc(&g.Alloc, db, triedb)
|
root, err := flushAlloc(&g.Alloc, triedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
@ -45,29 +46,29 @@ const (
|
||||||
|
|
||||||
// Database wraps access to tries and contract code.
|
// Database wraps access to tries and contract code.
|
||||||
type Database interface {
|
type Database interface {
|
||||||
|
// Reader returns a state reader associated with the specified state root.
|
||||||
|
Reader(root common.Hash) (Reader, error)
|
||||||
|
|
||||||
// OpenTrie opens the main account trie.
|
// OpenTrie opens the main account trie.
|
||||||
OpenTrie(root common.Hash) (Trie, error)
|
OpenTrie(root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error)
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
|
||||||
CopyTrie(Trie) Trie
|
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error)
|
ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error)
|
ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error)
|
||||||
|
|
||||||
// DiskDB returns the underlying key-value disk database.
|
|
||||||
DiskDB() ethdb.KeyValueStore
|
|
||||||
|
|
||||||
// PointCache returns the cache holding points used in verkle tree key computation
|
// PointCache returns the cache holding points used in verkle tree key computation
|
||||||
PointCache() *utils.PointCache
|
PointCache() *utils.PointCache
|
||||||
|
|
||||||
// TrieDB returns the underlying trie database for managing trie nodes.
|
// TrieDB returns the underlying trie database for managing trie nodes.
|
||||||
TrieDB() *triedb.Database
|
TrieDB() *triedb.Database
|
||||||
|
|
||||||
|
// Snapshot returns the underlying state snapshot.
|
||||||
|
Snapshot() *snapshot.Tree
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trie is a Ethereum Merkle Patricia trie.
|
// Trie is a Ethereum Merkle Patricia trie.
|
||||||
|
@ -147,47 +148,62 @@ type Trie interface {
|
||||||
IsVerkle() bool
|
IsVerkle() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDatabase creates a backing store for state. The returned database is safe for
|
// CachingDB is an implementation of Database interface. It leverages both trie and
|
||||||
// concurrent use, but does not retain any recent trie nodes in memory. To keep some
|
// state snapshot to provide functionalities for state access. It's meant to be a
|
||||||
// historical state in memory, use the NewDatabaseWithConfig constructor.
|
// long-live object and has a few caches inside for sharing between blocks.
|
||||||
func NewDatabase(db ethdb.Database) Database {
|
type CachingDB struct {
|
||||||
return NewDatabaseWithConfig(db, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDatabaseWithConfig creates a backing store for state. The returned database
|
|
||||||
// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
|
|
||||||
// large memory cache.
|
|
||||||
func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database {
|
|
||||||
return &cachingDB{
|
|
||||||
disk: db,
|
|
||||||
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
|
||||||
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
|
||||||
triedb: triedb.NewDatabase(db, config),
|
|
||||||
pointCache: utils.NewPointCache(pointCacheSize),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDatabaseWithNodeDB creates a state database with an already initialized node database.
|
|
||||||
func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database {
|
|
||||||
return &cachingDB{
|
|
||||||
disk: db,
|
|
||||||
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
|
||||||
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
|
||||||
triedb: triedb,
|
|
||||||
pointCache: utils.NewPointCache(pointCacheSize),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type cachingDB struct {
|
|
||||||
disk ethdb.KeyValueStore
|
disk ethdb.KeyValueStore
|
||||||
codeSizeCache *lru.Cache[common.Hash, int]
|
|
||||||
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
|
|
||||||
triedb *triedb.Database
|
triedb *triedb.Database
|
||||||
|
snap *snapshot.Tree
|
||||||
|
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
|
||||||
|
codeSizeCache *lru.Cache[common.Hash, int]
|
||||||
pointCache *utils.PointCache
|
pointCache *utils.PointCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDatabase creates a state database with the provided data sources.
|
||||||
|
func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
|
||||||
|
return &CachingDB{
|
||||||
|
disk: triedb.Disk(),
|
||||||
|
triedb: triedb,
|
||||||
|
snap: snap,
|
||||||
|
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
|
||||||
|
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
|
||||||
|
pointCache: utils.NewPointCache(pointCacheSize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDatabaseForTesting is similar to NewDatabase, but it initializes the caching
|
||||||
|
// db by using an ephemeral memory db with default config for testing.
|
||||||
|
func NewDatabaseForTesting() *CachingDB {
|
||||||
|
return NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader returns a state reader associated with the specified state root.
|
||||||
|
func (db *CachingDB) Reader(stateRoot common.Hash) (Reader, error) {
|
||||||
|
var readers []Reader
|
||||||
|
|
||||||
|
// Set up the state snapshot reader if available. This feature
|
||||||
|
// is optional and may be partially useful if it's not fully
|
||||||
|
// generated.
|
||||||
|
if db.snap != nil {
|
||||||
|
sr, err := newStateReader(stateRoot, db.snap)
|
||||||
|
if err == nil {
|
||||||
|
readers = append(readers, sr) // snap reader is optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set up the trie reader, which is expected to always be available
|
||||||
|
// as the gatekeeper unless the state is corrupted.
|
||||||
|
tr, err := newTrieReader(stateRoot, db.triedb, db.pointCache)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
readers = append(readers, tr)
|
||||||
|
|
||||||
|
return newMultiReader(readers...)
|
||||||
|
}
|
||||||
|
|
||||||
// OpenTrie opens the main account trie at a specific root hash.
|
// OpenTrie opens the main account trie at a specific root hash.
|
||||||
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
func (db *CachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
if db.triedb.IsVerkle() {
|
if db.triedb.IsVerkle() {
|
||||||
return trie.NewVerkleTrie(root, db.triedb, db.pointCache)
|
return trie.NewVerkleTrie(root, db.triedb, db.pointCache)
|
||||||
}
|
}
|
||||||
|
@ -199,7 +215,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// 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) {
|
func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) {
|
||||||
// In the verkle case, there is only one tree. But the two-tree structure
|
// In the verkle case, there is only one tree. But the two-tree structure
|
||||||
// is hardcoded in the codebase. So we need to return the same trie in this
|
// is hardcoded in the codebase. So we need to return the same trie in this
|
||||||
// case.
|
// case.
|
||||||
|
@ -213,20 +229,8 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
|
||||||
return tr, nil
|
return tr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
|
||||||
func (db *cachingDB) CopyTrie(t Trie) Trie {
|
|
||||||
switch t := t.(type) {
|
|
||||||
case *trie.StateTrie:
|
|
||||||
return t.Copy()
|
|
||||||
case *trie.VerkleTrie:
|
|
||||||
return t.Copy()
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unknown trie type %T", t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
func (db *CachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
code, _ := db.codeCache.Get(codeHash)
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
|
@ -243,7 +247,7 @@ func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash)
|
||||||
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
||||||
// code can't be found in the cache, then check the existence with **new**
|
// code can't be found in the cache, then check the existence with **new**
|
||||||
// db scheme.
|
// db scheme.
|
||||||
func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
|
func (db *CachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
code, _ := db.codeCache.Get(codeHash)
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
|
@ -258,7 +262,7 @@ func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash com
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
|
func (db *CachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
|
||||||
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
||||||
return cached, nil
|
return cached, nil
|
||||||
}
|
}
|
||||||
|
@ -266,17 +270,29 @@ func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash)
|
||||||
return len(code), err
|
return len(code), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskDB returns the underlying key-value disk database.
|
|
||||||
func (db *cachingDB) DiskDB() ethdb.KeyValueStore {
|
|
||||||
return db.disk
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrieDB retrieves any intermediate trie-node caching layer.
|
// TrieDB retrieves any intermediate trie-node caching layer.
|
||||||
func (db *cachingDB) TrieDB() *triedb.Database {
|
func (db *CachingDB) TrieDB() *triedb.Database {
|
||||||
return db.triedb
|
return db.triedb
|
||||||
}
|
}
|
||||||
|
|
||||||
// PointCache returns the cache of evaluated curve points.
|
// PointCache returns the cache of evaluated curve points.
|
||||||
func (db *cachingDB) PointCache() *utils.PointCache {
|
func (db *CachingDB) PointCache() *utils.PointCache {
|
||||||
return db.pointCache
|
return db.pointCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snapshot returns the underlying state snapshot.
|
||||||
|
func (db *CachingDB) Snapshot() *snapshot.Tree {
|
||||||
|
return db.snap
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustCopyTrie returns a deep-copied trie.
|
||||||
|
func mustCopyTrie(t Trie) Trie {
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *trie.StateTrie:
|
||||||
|
return t.Copy()
|
||||||
|
case *trie.VerkleTrie:
|
||||||
|
return t.Copy()
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown trie type %T", t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
|
||||||
db, sdb, ndb, root, _ := makeTestState(scheme)
|
db, sdb, ndb, root, _ := makeTestState(scheme)
|
||||||
ndb.Commit(root, false)
|
ndb.Commit(root, false)
|
||||||
|
|
||||||
state, err := New(root, sdb, nil)
|
state, err := New(root, sdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
// Copyright 2024 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 (
|
||||||
|
"errors"
|
||||||
|
"maps"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/utils"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reader defines the interface for accessing accounts and storage slots
|
||||||
|
// associated with a specific state.
|
||||||
|
type Reader interface {
|
||||||
|
// Account retrieves the account associated with a particular address.
|
||||||
|
//
|
||||||
|
// - Returns a nil account if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned account is safe to modify after the call
|
||||||
|
Account(addr common.Address) (*types.StateAccount, error)
|
||||||
|
|
||||||
|
// Storage retrieves the storage slot associated with a particular account
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// - Returns an empty slot if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned storage slot is safe to modify after the call
|
||||||
|
Storage(addr common.Address, slot common.Hash) (common.Hash, error)
|
||||||
|
|
||||||
|
// Copy returns a deep-copied state reader.
|
||||||
|
Copy() Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// stateReader is a wrapper over the state snapshot and implements the Reader
|
||||||
|
// interface. It provides an efficient way to access flat state.
|
||||||
|
type stateReader struct {
|
||||||
|
snap snapshot.Snapshot
|
||||||
|
buff crypto.KeccakState
|
||||||
|
}
|
||||||
|
|
||||||
|
// newStateReader constructs a flat state reader with on the specified state root.
|
||||||
|
func newStateReader(root common.Hash, snaps *snapshot.Tree) (*stateReader, error) {
|
||||||
|
snap := snaps.Snapshot(root)
|
||||||
|
if snap == nil {
|
||||||
|
return nil, errors.New("snapshot is not available")
|
||||||
|
}
|
||||||
|
return &stateReader{
|
||||||
|
snap: snap,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements Reader, retrieving the account specified by the address.
|
||||||
|
//
|
||||||
|
// An error will be returned if the associated snapshot is already stale or
|
||||||
|
// the requested account is not yet covered by the snapshot.
|
||||||
|
//
|
||||||
|
// The returned account might be nil if it's not existent.
|
||||||
|
func (r *stateReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
ret, err := r.snap.Account(crypto.HashData(r.buff, addr.Bytes()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ret == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
acct := &types.StateAccount{
|
||||||
|
Nonce: ret.Nonce,
|
||||||
|
Balance: ret.Balance,
|
||||||
|
CodeHash: ret.CodeHash,
|
||||||
|
Root: common.BytesToHash(ret.Root),
|
||||||
|
}
|
||||||
|
if len(acct.CodeHash) == 0 {
|
||||||
|
acct.CodeHash = types.EmptyCodeHash.Bytes()
|
||||||
|
}
|
||||||
|
if acct.Root == (common.Hash{}) {
|
||||||
|
acct.Root = types.EmptyRootHash
|
||||||
|
}
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements Reader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// An error will be returned if the associated snapshot is already stale or
|
||||||
|
// the requested storage slot is not yet covered by the snapshot.
|
||||||
|
//
|
||||||
|
// The returned storage slot might be empty if it's not existent.
|
||||||
|
func (r *stateReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
|
addrHash := crypto.HashData(r.buff, addr.Bytes())
|
||||||
|
slotHash := crypto.HashData(r.buff, key.Bytes())
|
||||||
|
ret, err := r.snap.Storage(addrHash, slotHash)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
if len(ret) == 0 {
|
||||||
|
return common.Hash{}, nil
|
||||||
|
}
|
||||||
|
// Perform the rlp-decode as the slot value is RLP-encoded in the state
|
||||||
|
// snapshot.
|
||||||
|
_, content, _, err := rlp.Split(ret)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
var value common.Hash
|
||||||
|
value.SetBytes(content)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implements Reader, returning a deep-copied snap reader.
|
||||||
|
func (r *stateReader) Copy() Reader {
|
||||||
|
return &stateReader{
|
||||||
|
snap: r.snap,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trieReader implements the Reader interface, providing functions to access
|
||||||
|
// state from the referenced trie.
|
||||||
|
type trieReader struct {
|
||||||
|
root common.Hash // State root which uniquely represent a state
|
||||||
|
db *triedb.Database // Database for loading trie
|
||||||
|
buff crypto.KeccakState // Buffer for keccak256 hashing
|
||||||
|
mainTrie Trie // Main trie, resolved in constructor
|
||||||
|
subRoots map[common.Address]common.Hash // Set of storage roots, cached when the account is resolved
|
||||||
|
subTries map[common.Address]Trie // Group of storage tries, cached when it's resolved
|
||||||
|
}
|
||||||
|
|
||||||
|
// trieReader constructs a trie reader of the specific state. An error will be
|
||||||
|
// returned if the associated trie specified by root is not existent.
|
||||||
|
func newTrieReader(root common.Hash, db *triedb.Database, cache *utils.PointCache) (*trieReader, error) {
|
||||||
|
var (
|
||||||
|
tr Trie
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if !db.IsVerkle() {
|
||||||
|
tr, err = trie.NewStateTrie(trie.StateTrieID(root), db)
|
||||||
|
} else {
|
||||||
|
tr, err = trie.NewVerkleTrie(root, db, cache)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &trieReader{
|
||||||
|
root: root,
|
||||||
|
db: db,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
mainTrie: tr,
|
||||||
|
subRoots: make(map[common.Address]common.Hash),
|
||||||
|
subTries: make(map[common.Address]Trie),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implements Reader, retrieving the account specified by the address.
|
||||||
|
//
|
||||||
|
// An error will be returned if the trie state is corrupted. An nil account
|
||||||
|
// will be returned if it's not existent in the trie.
|
||||||
|
func (r *trieReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
account, err := r.mainTrie.GetAccount(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if account == nil {
|
||||||
|
r.subRoots[addr] = types.EmptyRootHash
|
||||||
|
} else {
|
||||||
|
r.subRoots[addr] = account.Root
|
||||||
|
}
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implements Reader, retrieving the storage slot specified by the
|
||||||
|
// address and slot key.
|
||||||
|
//
|
||||||
|
// An error will be returned if the trie state is corrupted. An empty storage
|
||||||
|
// slot will be returned if it's not existent in the trie.
|
||||||
|
func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
|
||||||
|
var (
|
||||||
|
tr Trie
|
||||||
|
found bool
|
||||||
|
value common.Hash
|
||||||
|
)
|
||||||
|
if r.db.IsVerkle() {
|
||||||
|
tr = r.mainTrie
|
||||||
|
} else {
|
||||||
|
tr, found = r.subTries[addr]
|
||||||
|
if !found {
|
||||||
|
root, ok := r.subRoots[addr]
|
||||||
|
|
||||||
|
// The storage slot is accessed without account caching. It's unexpected
|
||||||
|
// behavior but try to resolve the account first anyway.
|
||||||
|
if !ok {
|
||||||
|
_, err := r.Account(addr)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
root = r.subRoots[addr]
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.HashData(r.buff, addr.Bytes()), root), r.db)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
r.subTries[addr] = tr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret, err := tr.GetStorage(addr, key.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
value.SetBytes(ret)
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implements Reader, returning a deep-copied trie reader.
|
||||||
|
func (r *trieReader) Copy() Reader {
|
||||||
|
tries := make(map[common.Address]Trie)
|
||||||
|
for addr, tr := range r.subTries {
|
||||||
|
tries[addr] = mustCopyTrie(tr)
|
||||||
|
}
|
||||||
|
return &trieReader{
|
||||||
|
root: r.root,
|
||||||
|
db: r.db,
|
||||||
|
buff: crypto.NewKeccakState(),
|
||||||
|
mainTrie: mustCopyTrie(r.mainTrie),
|
||||||
|
subRoots: maps.Clone(r.subRoots),
|
||||||
|
subTries: tries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiReader is the aggregation of a list of Reader interface, providing state
|
||||||
|
// access by leveraging all readers. The checking priority is determined by the
|
||||||
|
// position in the reader list.
|
||||||
|
type multiReader struct {
|
||||||
|
readers []Reader // List of readers, sorted by checking priority
|
||||||
|
}
|
||||||
|
|
||||||
|
// newMultiReader constructs a multiReader instance with the given readers. The
|
||||||
|
// priority among readers is assumed to be sorted. Note, it must contain at least
|
||||||
|
// one reader for constructing a multiReader.
|
||||||
|
func newMultiReader(readers ...Reader) (*multiReader, error) {
|
||||||
|
if len(readers) == 0 {
|
||||||
|
return nil, errors.New("empty reader set")
|
||||||
|
}
|
||||||
|
return &multiReader{
|
||||||
|
readers: readers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account implementing Reader interface, retrieving the account associated with
|
||||||
|
// a particular address.
|
||||||
|
//
|
||||||
|
// - Returns a nil account if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned account is safe to modify after the call
|
||||||
|
func (r *multiReader) Account(addr common.Address) (*types.StateAccount, error) {
|
||||||
|
var errs []error
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
acct, err := reader.Account(addr)
|
||||||
|
if err == nil {
|
||||||
|
return acct, nil
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return nil, errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage implementing Reader interface, retrieving the storage slot associated
|
||||||
|
// with a particular account address and slot key.
|
||||||
|
//
|
||||||
|
// - Returns an empty slot if it does not exist
|
||||||
|
// - Returns an error only if an unexpected issue occurs
|
||||||
|
// - The returned storage slot is safe to modify after the call
|
||||||
|
func (r *multiReader) Storage(addr common.Address, slot common.Hash) (common.Hash, error) {
|
||||||
|
var errs []error
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
slot, err := reader.Storage(addr, slot)
|
||||||
|
if err == nil {
|
||||||
|
return slot, nil
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return common.Hash{}, errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy implementing Reader interface, returning a deep-copied state reader.
|
||||||
|
func (r *multiReader) Copy() Reader {
|
||||||
|
var readers []Reader
|
||||||
|
for _, reader := range r.readers {
|
||||||
|
readers = append(readers, reader.Copy())
|
||||||
|
}
|
||||||
|
return &multiReader{readers: readers}
|
||||||
|
}
|
|
@ -187,52 +187,23 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
||||||
s.originStorage[key] = common.Hash{} // track the empty slot as origin value
|
s.originStorage[key] = common.Hash{} // track the empty slot as origin value
|
||||||
return common.Hash{}
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
// If no live objects are available, attempt to use snapshots
|
s.db.StorageLoaded++
|
||||||
var (
|
|
||||||
enc []byte
|
|
||||||
err error
|
|
||||||
value common.Hash
|
|
||||||
)
|
|
||||||
if s.db.snap != nil {
|
|
||||||
start := time.Now()
|
|
||||||
enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes()))
|
|
||||||
s.db.SnapshotStorageReads += time.Since(start)
|
|
||||||
|
|
||||||
if len(enc) > 0 {
|
start := time.Now()
|
||||||
_, content, _, err := rlp.Split(enc)
|
value, err := s.db.reader.Storage(s.address, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.db.setError(err)
|
s.db.setError(err)
|
||||||
}
|
return common.Hash{}
|
||||||
value.SetBytes(content)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// If the snapshot is unavailable or reading from it fails, load from the database.
|
s.db.StorageReads += time.Since(start)
|
||||||
if s.db.snap == nil || err != nil {
|
|
||||||
start := time.Now()
|
|
||||||
tr, err := s.getTrie()
|
|
||||||
if err != nil {
|
|
||||||
s.db.setError(err)
|
|
||||||
return common.Hash{}
|
|
||||||
}
|
|
||||||
val, err := tr.GetStorage(s.address, key.Bytes())
|
|
||||||
s.db.StorageReads += time.Since(start)
|
|
||||||
|
|
||||||
if err != nil {
|
// Schedule the resolved storage slots for prefetching if it's enabled.
|
||||||
s.db.setError(err)
|
|
||||||
return common.Hash{}
|
|
||||||
}
|
|
||||||
value.SetBytes(val)
|
|
||||||
}
|
|
||||||
// Independent of where we loaded the data from, add it to the prefetcher.
|
|
||||||
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
|
||||||
// want the trie nodes to end up in the prefetcher too, so just push through.
|
|
||||||
if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash {
|
if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash {
|
||||||
if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, [][]byte{key[:]}, true); err != nil {
|
if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, [][]byte{key[:]}, true); err != nil {
|
||||||
log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err)
|
log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.originStorage[key] = value
|
s.originStorage[key] = value
|
||||||
s.db.StorageLoaded++
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +498,7 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
|
||||||
newContract: s.newContract,
|
newContract: s.newContract,
|
||||||
}
|
}
|
||||||
if s.trie != nil {
|
if s.trie != nil {
|
||||||
obj.trie = db.db.CopyTrie(s.trie)
|
obj.trie = mustCopyTrie(s.trie)
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,27 +26,25 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stateEnv struct {
|
type stateEnv struct {
|
||||||
db ethdb.Database
|
|
||||||
state *StateDB
|
state *StateDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStateEnv() *stateEnv {
|
func newStateEnv() *stateEnv {
|
||||||
db := rawdb.NewMemoryDatabase()
|
sdb, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
sdb, _ := New(types.EmptyRootHash, NewDatabase(db), nil)
|
return &stateEnv{state: sdb}
|
||||||
return &stateEnv{db: db, state: sdb}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDump(t *testing.T) {
|
func TestDump(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
|
||||||
sdb, _ := New(types.EmptyRootHash, tdb, nil)
|
tdb := NewDatabase(triedb, nil)
|
||||||
s := &stateEnv{db: db, state: sdb}
|
sdb, _ := New(types.EmptyRootHash, tdb)
|
||||||
|
s := &stateEnv{state: sdb}
|
||||||
|
|
||||||
// generate a few entries
|
// generate a few entries
|
||||||
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
||||||
|
@ -62,7 +60,7 @@ func TestDump(t *testing.T) {
|
||||||
root, _ := s.state.Commit(0, false)
|
root, _ := s.state.Commit(0, false)
|
||||||
|
|
||||||
// check that DumpToCollector contains the state objects that are in trie
|
// check that DumpToCollector contains the state objects that are in trie
|
||||||
s.state, _ = New(root, tdb, nil)
|
s.state, _ = New(root, tdb)
|
||||||
got := string(s.state.Dump(nil))
|
got := string(s.state.Dump(nil))
|
||||||
want := `{
|
want := `{
|
||||||
"root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2",
|
"root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2",
|
||||||
|
@ -101,9 +99,10 @@ func TestDump(t *testing.T) {
|
||||||
|
|
||||||
func TestIterativeDump(t *testing.T) {
|
func TestIterativeDump(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
|
triedb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
|
||||||
sdb, _ := New(types.EmptyRootHash, tdb, nil)
|
tdb := NewDatabase(triedb, nil)
|
||||||
s := &stateEnv{db: db, state: sdb}
|
sdb, _ := New(types.EmptyRootHash, tdb)
|
||||||
|
s := &stateEnv{state: sdb}
|
||||||
|
|
||||||
// generate a few entries
|
// generate a few entries
|
||||||
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
||||||
|
@ -119,7 +118,7 @@ func TestIterativeDump(t *testing.T) {
|
||||||
s.state.updateStateObject(obj1)
|
s.state.updateStateObject(obj1)
|
||||||
s.state.updateStateObject(obj2)
|
s.state.updateStateObject(obj2)
|
||||||
root, _ := s.state.Commit(0, false)
|
root, _ := s.state.Commit(0, false)
|
||||||
s.state, _ = New(root, tdb, nil)
|
s.state, _ = New(root, tdb)
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
s.state.IterativeDump(nil, json.NewEncoder(b))
|
s.state.IterativeDump(nil, json.NewEncoder(b))
|
||||||
|
@ -195,7 +194,7 @@ func TestSnapshotEmpty(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateObjectRevert(t *testing.T) {
|
func TestCreateObjectRevert(t *testing.T) {
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
addr := common.BytesToAddress([]byte("so0"))
|
addr := common.BytesToAddress([]byte("so0"))
|
||||||
snap := state.Snapshot()
|
snap := state.Snapshot()
|
||||||
|
|
||||||
|
|
|
@ -82,10 +82,8 @@ type StateDB struct {
|
||||||
db Database
|
db Database
|
||||||
prefetcher *triePrefetcher
|
prefetcher *triePrefetcher
|
||||||
trie Trie
|
trie Trie
|
||||||
hasher crypto.KeccakState
|
|
||||||
logger *tracing.Hooks
|
logger *tracing.Hooks
|
||||||
snaps *snapshot.Tree // Nil if snapshot is not available
|
reader Reader
|
||||||
snap snapshot.Snapshot // Nil if snapshot is not available
|
|
||||||
|
|
||||||
// originalRoot is the pre-state root, before any changes were made.
|
// originalRoot is the pre-state root, before any changes were made.
|
||||||
// It will be updated when the Commit is called.
|
// It will be updated when the Commit is called.
|
||||||
|
@ -144,17 +142,15 @@ type StateDB struct {
|
||||||
witness *stateless.Witness
|
witness *stateless.Witness
|
||||||
|
|
||||||
// Measurements gathered during execution for debugging purposes
|
// Measurements gathered during execution for debugging purposes
|
||||||
AccountReads time.Duration
|
AccountReads time.Duration
|
||||||
AccountHashes time.Duration
|
AccountHashes time.Duration
|
||||||
AccountUpdates time.Duration
|
AccountUpdates time.Duration
|
||||||
AccountCommits time.Duration
|
AccountCommits time.Duration
|
||||||
StorageReads time.Duration
|
StorageReads time.Duration
|
||||||
StorageUpdates time.Duration
|
StorageUpdates time.Duration
|
||||||
StorageCommits time.Duration
|
StorageCommits time.Duration
|
||||||
SnapshotAccountReads time.Duration
|
SnapshotCommits time.Duration
|
||||||
SnapshotStorageReads time.Duration
|
TrieDBCommits time.Duration
|
||||||
SnapshotCommits time.Duration
|
|
||||||
TrieDBCommits time.Duration
|
|
||||||
|
|
||||||
AccountLoaded int // Number of accounts retrieved from the database during the state transition
|
AccountLoaded int // Number of accounts retrieved from the database during the state transition
|
||||||
AccountUpdated int // Number of accounts updated during the state transition
|
AccountUpdated int // Number of accounts updated during the state transition
|
||||||
|
@ -165,16 +161,20 @@ type StateDB struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new state from a given trie.
|
// New creates a new state from a given trie.
|
||||||
func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) {
|
func New(root common.Hash, db Database) (*StateDB, error) {
|
||||||
tr, err := db.OpenTrie(root)
|
tr, err := db.OpenTrie(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
reader, err := db.Reader(root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
sdb := &StateDB{
|
sdb := &StateDB{
|
||||||
db: db,
|
db: db,
|
||||||
trie: tr,
|
trie: tr,
|
||||||
originalRoot: root,
|
originalRoot: root,
|
||||||
snaps: snaps,
|
reader: reader,
|
||||||
stateObjects: make(map[common.Address]*stateObject),
|
stateObjects: make(map[common.Address]*stateObject),
|
||||||
stateObjectsDestruct: make(map[common.Address]*stateObject),
|
stateObjectsDestruct: make(map[common.Address]*stateObject),
|
||||||
mutations: make(map[common.Address]*mutation),
|
mutations: make(map[common.Address]*mutation),
|
||||||
|
@ -183,13 +183,9 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
||||||
journal: newJournal(),
|
journal: newJournal(),
|
||||||
accessList: newAccessList(),
|
accessList: newAccessList(),
|
||||||
transientStorage: newTransientStorage(),
|
transientStorage: newTransientStorage(),
|
||||||
hasher: crypto.NewKeccakState(),
|
|
||||||
}
|
}
|
||||||
if db.TrieDB().IsVerkle() {
|
if db.TrieDB().IsVerkle() {
|
||||||
sdb.accessEvents = NewAccessEvents(db.(*cachingDB).pointCache)
|
sdb.accessEvents = NewAccessEvents(db.PointCache())
|
||||||
}
|
|
||||||
if sdb.snaps != nil {
|
|
||||||
sdb.snap = sdb.snaps.Snapshot(root)
|
|
||||||
}
|
}
|
||||||
return sdb, nil
|
return sdb, nil
|
||||||
}
|
}
|
||||||
|
@ -204,30 +200,23 @@ func (s *StateDB) SetLogger(l *tracing.Hooks) {
|
||||||
// commit phase, most of the needed data is already hot.
|
// commit phase, most of the needed data is already hot.
|
||||||
func (s *StateDB) StartPrefetcher(namespace string, witness *stateless.Witness) {
|
func (s *StateDB) StartPrefetcher(namespace string, witness *stateless.Witness) {
|
||||||
// Terminate any previously running prefetcher
|
// Terminate any previously running prefetcher
|
||||||
if s.prefetcher != nil {
|
s.StopPrefetcher()
|
||||||
s.prefetcher.terminate(false)
|
|
||||||
s.prefetcher.report()
|
|
||||||
s.prefetcher = nil
|
|
||||||
}
|
|
||||||
// Enable witness collection if requested
|
// Enable witness collection if requested
|
||||||
s.witness = witness
|
s.witness = witness
|
||||||
|
|
||||||
// If snapshots are enabled, start prefethers explicitly
|
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
||||||
if s.snap != nil {
|
// rewards are now handled at the consensus layer. Consequently, a block may
|
||||||
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, witness == nil)
|
// have no state transitions if it contains no transactions and no withdrawals.
|
||||||
|
// In such cases, the account trie won't be scheduled for prefetching, leading
|
||||||
// With the switch to the Proof-of-Stake consensus algorithm, block production
|
// to unnecessary error logs.
|
||||||
// rewards are now handled at the consensus layer. Consequently, a block may
|
//
|
||||||
// have no state transitions if it contains no transactions and no withdrawals.
|
// To prevent this, the account trie is always scheduled for prefetching once
|
||||||
// In such cases, the account trie won't be scheduled for prefetching, leading
|
// the prefetcher is constructed. For more details, see:
|
||||||
// to unnecessary error logs.
|
// https://github.com/ethereum/go-ethereum/issues/29880
|
||||||
//
|
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, witness == nil)
|
||||||
// To prevent this, the account trie is always scheduled for prefetching once
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil, false); err != nil {
|
||||||
// the prefetcher is constructed. For more details, see:
|
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
||||||
// https://github.com/ethereum/go-ethereum/issues/29880
|
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, nil, false); err != nil {
|
|
||||||
log.Error("Failed to prefetch account trie", "root", s.originalRoot, "err", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,57 +572,28 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
||||||
if _, ok := s.stateObjectsDestruct[addr]; ok {
|
if _, ok := s.stateObjectsDestruct[addr]; ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// If no live objects are available, attempt to use snapshots
|
s.AccountLoaded++
|
||||||
var data *types.StateAccount
|
|
||||||
if s.snap != nil {
|
|
||||||
start := time.Now()
|
|
||||||
acc, err := s.snap.Account(crypto.HashData(s.hasher, addr.Bytes()))
|
|
||||||
s.SnapshotAccountReads += time.Since(start)
|
|
||||||
if err == nil {
|
|
||||||
if acc == nil {
|
|
||||||
s.AccountLoaded++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = &types.StateAccount{
|
|
||||||
Nonce: acc.Nonce,
|
|
||||||
Balance: acc.Balance,
|
|
||||||
CodeHash: acc.CodeHash,
|
|
||||||
Root: common.BytesToHash(acc.Root),
|
|
||||||
}
|
|
||||||
if len(data.CodeHash) == 0 {
|
|
||||||
data.CodeHash = types.EmptyCodeHash.Bytes()
|
|
||||||
}
|
|
||||||
if data.Root == (common.Hash{}) {
|
|
||||||
data.Root = types.EmptyRootHash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If snapshot unavailable or reading from it failed, load from the database
|
|
||||||
if data == nil {
|
|
||||||
start := time.Now()
|
|
||||||
var err error
|
|
||||||
data, err = s.trie.GetAccount(addr)
|
|
||||||
s.AccountReads += time.Since(start)
|
|
||||||
|
|
||||||
if err != nil {
|
start := time.Now()
|
||||||
s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %w", addr.Bytes(), err))
|
acct, err := s.reader.Account(addr)
|
||||||
return nil
|
if err != nil {
|
||||||
}
|
s.setError(fmt.Errorf("getStateObject (%x) error: %w", addr.Bytes(), err))
|
||||||
if data == nil {
|
return nil
|
||||||
s.AccountLoaded++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Independent of where we loaded the data from, add it to the prefetcher.
|
s.AccountReads += time.Since(start)
|
||||||
// Whilst this would be a bit weird if snapshots are disabled, but we still
|
|
||||||
// want the trie nodes to end up in the prefetcher too, so just push through.
|
// Short circuit if the account is not found
|
||||||
|
if acct == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Schedule the resolved account for prefetching if it's enabled.
|
||||||
if s.prefetcher != nil {
|
if s.prefetcher != nil {
|
||||||
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, [][]byte{addr[:]}, true); err != nil {
|
if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, [][]byte{addr[:]}, true); err != nil {
|
||||||
log.Error("Failed to prefetch account", "addr", addr, "err", err)
|
log.Error("Failed to prefetch account", "addr", addr, "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Insert into the live set
|
// Insert into the live set
|
||||||
obj := newObject(s, addr, data)
|
obj := newObject(s, addr, acct)
|
||||||
s.setStateObject(obj)
|
s.setStateObject(obj)
|
||||||
s.AccountLoaded++
|
s.AccountLoaded++
|
||||||
return obj
|
return obj
|
||||||
|
@ -688,8 +648,8 @@ func (s *StateDB) Copy() *StateDB {
|
||||||
// Copy all the basic fields, initialize the memory ones
|
// Copy all the basic fields, initialize the memory ones
|
||||||
state := &StateDB{
|
state := &StateDB{
|
||||||
db: s.db,
|
db: s.db,
|
||||||
trie: s.db.CopyTrie(s.trie),
|
trie: mustCopyTrie(s.trie),
|
||||||
hasher: crypto.NewKeccakState(),
|
reader: s.reader.Copy(),
|
||||||
originalRoot: s.originalRoot,
|
originalRoot: s.originalRoot,
|
||||||
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
stateObjects: make(map[common.Address]*stateObject, len(s.stateObjects)),
|
||||||
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
|
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
|
||||||
|
@ -701,14 +661,16 @@ func (s *StateDB) Copy() *StateDB {
|
||||||
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
|
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
|
||||||
logSize: s.logSize,
|
logSize: s.logSize,
|
||||||
preimages: maps.Clone(s.preimages),
|
preimages: maps.Clone(s.preimages),
|
||||||
journal: s.journal.copy(),
|
|
||||||
|
|
||||||
// In order for the block producer to be able to use and make additions
|
// Do we need to copy the access list and transient storage?
|
||||||
// to the snapshot tree, we need to copy that as well. Otherwise, any
|
// In practice: No. At the start of a transaction, these two lists are empty.
|
||||||
// block mined by ourselves will cause gaps in the tree, and force the
|
// In practice, we only ever copy state _between_ transactions/blocks, never
|
||||||
// miner to operate trie-backed only.
|
// in the middle of a transaction. However, it doesn't cost us much to copy
|
||||||
snaps: s.snaps,
|
// empty lists, so we do it anyway to not blow up if we ever decide copy them
|
||||||
snap: s.snap,
|
// in the middle of a transaction.
|
||||||
|
accessList: s.accessList.Copy(),
|
||||||
|
transientStorage: s.transientStorage.Copy(),
|
||||||
|
journal: s.journal.copy(),
|
||||||
}
|
}
|
||||||
if s.witness != nil {
|
if s.witness != nil {
|
||||||
state.witness = s.witness.Copy()
|
state.witness = s.witness.Copy()
|
||||||
|
@ -737,14 +699,6 @@ func (s *StateDB) Copy() *StateDB {
|
||||||
}
|
}
|
||||||
state.logs[hash] = cpy
|
state.logs[hash] = cpy
|
||||||
}
|
}
|
||||||
// Do we need to copy the access list and transient storage?
|
|
||||||
// In practice: No. At the start of a transaction, these two lists are empty.
|
|
||||||
// In practice, we only ever copy state _between_ transactions/blocks, never
|
|
||||||
// in the middle of a transaction. However, it doesn't cost us much to copy
|
|
||||||
// empty lists, so we do it anyway to not blow up if we ever decide copy them
|
|
||||||
// in the middle of a transaction.
|
|
||||||
state.accessList = s.accessList.Copy()
|
|
||||||
state.transientStorage = s.transientStorage.Copy()
|
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,8 +933,8 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||||
// of a specific account. It leverages the associated state snapshot for fast
|
// of a specific account. It leverages the associated state snapshot for fast
|
||||||
// storage iteration and constructs trie node deletion markers by creating
|
// storage iteration and constructs trie node deletion markers by creating
|
||||||
// stack trie with iterated slots.
|
// stack trie with iterated slots.
|
||||||
func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
func (s *StateDB) fastDeleteStorage(snaps *snapshot.Tree, addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
||||||
iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{})
|
iter, err := snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1058,10 +1012,11 @@ func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root
|
||||||
// The fast approach can be failed if the snapshot is not fully
|
// The fast approach can be failed if the snapshot is not fully
|
||||||
// generated, or it's internally corrupted. Fallback to the slow
|
// generated, or it's internally corrupted. Fallback to the slow
|
||||||
// one just in case.
|
// one just in case.
|
||||||
if s.snap != nil {
|
snaps := s.db.Snapshot()
|
||||||
slots, nodes, err = s.fastDeleteStorage(addrHash, root)
|
if snaps != nil {
|
||||||
|
slots, nodes, err = s.fastDeleteStorage(snaps, addrHash, root)
|
||||||
}
|
}
|
||||||
if s.snap == nil || err != nil {
|
if snaps == nil || err != nil {
|
||||||
slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root)
|
slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1299,7 +1254,7 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool) (*stateU
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Commit dirty contract code if any exists
|
// Commit dirty contract code if any exists
|
||||||
if db := s.db.DiskDB(); db != nil && len(ret.codes) > 0 {
|
if db := s.db.TrieDB().Disk(); db != nil && len(ret.codes) > 0 {
|
||||||
batch := db.NewBatch()
|
batch := db.NewBatch()
|
||||||
for _, code := range ret.codes {
|
for _, code := range ret.codes {
|
||||||
rawdb.WriteCode(batch, code.hash, code.blob)
|
rawdb.WriteCode(batch, code.hash, code.blob)
|
||||||
|
@ -1310,18 +1265,16 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool) (*stateU
|
||||||
}
|
}
|
||||||
if !ret.empty() {
|
if !ret.empty() {
|
||||||
// If snapshotting is enabled, update the snapshot tree with this new version
|
// If snapshotting is enabled, update the snapshot tree with this new version
|
||||||
if s.snap != nil {
|
if snap := s.db.Snapshot(); snap != nil {
|
||||||
s.snap = nil
|
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if err := s.snaps.Update(ret.root, ret.originRoot, ret.destructs, ret.accounts, ret.storages); err != nil {
|
if err := snap.Update(ret.root, ret.originRoot, ret.destructs, ret.accounts, ret.storages); err != nil {
|
||||||
log.Warn("Failed to update snapshot tree", "from", ret.originRoot, "to", ret.root, "err", err)
|
log.Warn("Failed to update snapshot tree", "from", ret.originRoot, "to", ret.root, "err", err)
|
||||||
}
|
}
|
||||||
// Keep 128 diff layers in the memory, persistent layer is 129th.
|
// Keep 128 diff layers in the memory, persistent layer is 129th.
|
||||||
// - head layer is paired with HEAD state
|
// - head layer is paired with HEAD state
|
||||||
// - head-1 layer is paired with HEAD-1 state
|
// - head-1 layer is paired with HEAD-1 state
|
||||||
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
|
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
|
||||||
if err := s.snaps.Cap(ret.root, TriesInMemory); err != nil {
|
if err := snap.Cap(ret.root, TriesInMemory); err != nil {
|
||||||
log.Warn("Failed to cap snapshot tree", "root", ret.root, "layers", TriesInMemory, "err", err)
|
log.Warn("Failed to cap snapshot tree", "root", ret.root, "layers", TriesInMemory, "err", err)
|
||||||
}
|
}
|
||||||
s.SnapshotCommits += time.Since(start)
|
s.SnapshotCommits += time.Since(start)
|
||||||
|
@ -1336,6 +1289,7 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool) (*stateU
|
||||||
s.TrieDBCommits += time.Since(start)
|
s.TrieDBCommits += time.Since(start)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.reader, _ = s.db.Reader(s.originalRoot)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,6 +1405,7 @@ func (s *StateDB) markUpdate(addr common.Address) {
|
||||||
s.mutations[addr].typ = update
|
s.mutations[addr].typ = update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PointCache returns the point cache used by verkle tree.
|
||||||
func (s *StateDB) PointCache() *utils.PointCache {
|
func (s *StateDB) PointCache() *utils.PointCache {
|
||||||
return s.db.PointCache()
|
return s.db.PointCache()
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,6 @@ func (test *stateTest) run() bool {
|
||||||
}
|
}
|
||||||
disk = rawdb.NewMemoryDatabase()
|
disk = rawdb.NewMemoryDatabase()
|
||||||
tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults})
|
tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults})
|
||||||
sdb = NewDatabaseWithNodeDB(disk, tdb)
|
|
||||||
byzantium = rand.Intn(2) == 0
|
byzantium = rand.Intn(2) == 0
|
||||||
)
|
)
|
||||||
defer disk.Close()
|
defer disk.Close()
|
||||||
|
@ -217,7 +216,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, sdb, snaps)
|
state, err := New(root, NewDatabase(tdb, snaps))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ package state
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"math"
|
"math"
|
||||||
|
@ -53,8 +52,9 @@ func TestUpdateLeaks(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
tdb = triedb.NewDatabase(db, nil)
|
tdb = triedb.NewDatabase(db, nil)
|
||||||
|
sdb = NewDatabase(tdb, nil)
|
||||||
)
|
)
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil)
|
state, _ := New(types.EmptyRootHash, sdb)
|
||||||
|
|
||||||
// Update it with some accounts
|
// Update it with some accounts
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
|
@ -90,8 +90,8 @@ func TestIntermediateLeaks(t *testing.T) {
|
||||||
finalDb := rawdb.NewMemoryDatabase()
|
finalDb := rawdb.NewMemoryDatabase()
|
||||||
transNdb := triedb.NewDatabase(transDb, nil)
|
transNdb := triedb.NewDatabase(transDb, nil)
|
||||||
finalNdb := triedb.NewDatabase(finalDb, nil)
|
finalNdb := triedb.NewDatabase(finalDb, nil)
|
||||||
transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil)
|
transState, _ := New(types.EmptyRootHash, NewDatabase(transNdb, nil))
|
||||||
finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil)
|
finalState, _ := New(types.EmptyRootHash, NewDatabase(finalNdb, nil))
|
||||||
|
|
||||||
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
|
modify := func(state *StateDB, addr common.Address, i, tweak byte) {
|
||||||
state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified)
|
state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak)), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -166,7 +166,7 @@ func TestIntermediateLeaks(t *testing.T) {
|
||||||
// https://github.com/ethereum/go-ethereum/pull/15549.
|
// https://github.com/ethereum/go-ethereum/pull/15549.
|
||||||
func TestCopy(t *testing.T) {
|
func TestCopy(t *testing.T) {
|
||||||
// Create a random state test to copy and modify "independently"
|
// Create a random state test to copy and modify "independently"
|
||||||
orig, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
orig, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
|
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
|
@ -230,8 +230,8 @@ func TestCopy(t *testing.T) {
|
||||||
// TestCopyWithDirtyJournal tests if Copy can correct create a equal copied
|
// TestCopyWithDirtyJournal tests if Copy can correct create a equal copied
|
||||||
// stateDB with dirty journal present.
|
// stateDB with dirty journal present.
|
||||||
func TestCopyWithDirtyJournal(t *testing.T) {
|
func TestCopyWithDirtyJournal(t *testing.T) {
|
||||||
db := NewDatabase(rawdb.NewMemoryDatabase())
|
db := NewDatabaseForTesting()
|
||||||
orig, _ := New(types.EmptyRootHash, db, nil)
|
orig, _ := New(types.EmptyRootHash, db)
|
||||||
|
|
||||||
// Fill up the initial states
|
// Fill up the initial states
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
|
@ -241,7 +241,7 @@ func TestCopyWithDirtyJournal(t *testing.T) {
|
||||||
orig.updateStateObject(obj)
|
orig.updateStateObject(obj)
|
||||||
}
|
}
|
||||||
root, _ := orig.Commit(0, true)
|
root, _ := orig.Commit(0, true)
|
||||||
orig, _ = New(root, db, nil)
|
orig, _ = New(root, db)
|
||||||
|
|
||||||
// modify all in memory without finalizing
|
// modify all in memory without finalizing
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
|
@ -274,8 +274,8 @@ func TestCopyWithDirtyJournal(t *testing.T) {
|
||||||
// It then proceeds to make changes to S1. Those changes are _not_ supposed
|
// It then proceeds to make changes to S1. Those changes are _not_ supposed
|
||||||
// to affect S2. This test checks that the copy properly deep-copies the objectstate
|
// to affect S2. This test checks that the copy properly deep-copies the objectstate
|
||||||
func TestCopyObjectState(t *testing.T) {
|
func TestCopyObjectState(t *testing.T) {
|
||||||
db := NewDatabase(rawdb.NewMemoryDatabase())
|
db := NewDatabaseForTesting()
|
||||||
orig, _ := New(types.EmptyRootHash, db, nil)
|
orig, _ := New(types.EmptyRootHash, db)
|
||||||
|
|
||||||
// Fill up the initial states
|
// Fill up the initial states
|
||||||
for i := byte(0); i < 5; i++ {
|
for i := byte(0); i < 5; i++ {
|
||||||
|
@ -527,7 +527,7 @@ func (test *snapshotTest) String() string {
|
||||||
func (test *snapshotTest) run() bool {
|
func (test *snapshotTest) run() bool {
|
||||||
// Run all actions and create snapshots.
|
// Run all actions and create snapshots.
|
||||||
var (
|
var (
|
||||||
state, _ = New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ = New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
snapshotRevs = make([]int, len(test.snapshots))
|
snapshotRevs = make([]int, len(test.snapshots))
|
||||||
sindex = 0
|
sindex = 0
|
||||||
checkstates = make([]*StateDB, len(test.snapshots))
|
checkstates = make([]*StateDB, len(test.snapshots))
|
||||||
|
@ -699,7 +699,7 @@ func TestTouchDelete(t *testing.T) {
|
||||||
s := newStateEnv()
|
s := newStateEnv()
|
||||||
s.state.getOrNewStateObject(common.Address{})
|
s.state.getOrNewStateObject(common.Address{})
|
||||||
root, _ := s.state.Commit(0, false)
|
root, _ := s.state.Commit(0, false)
|
||||||
s.state, _ = New(root, s.state.db, s.state.snaps)
|
s.state, _ = New(root, s.state.db)
|
||||||
|
|
||||||
snapshot := s.state.Snapshot()
|
snapshot := s.state.Snapshot()
|
||||||
s.state.AddBalance(common.Address{}, new(uint256.Int), tracing.BalanceChangeUnspecified)
|
s.state.AddBalance(common.Address{}, new(uint256.Int), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -716,7 +716,7 @@ func TestTouchDelete(t *testing.T) {
|
||||||
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
|
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
|
||||||
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
|
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
|
||||||
func TestCopyOfCopy(t *testing.T) {
|
func TestCopyOfCopy(t *testing.T) {
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
addr := common.HexToAddress("aaaa")
|
addr := common.HexToAddress("aaaa")
|
||||||
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified)
|
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified)
|
||||||
|
|
||||||
|
@ -733,8 +733,8 @@ func TestCopyOfCopy(t *testing.T) {
|
||||||
//
|
//
|
||||||
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
||||||
func TestCopyCommitCopy(t *testing.T) {
|
func TestCopyCommitCopy(t *testing.T) {
|
||||||
tdb := NewDatabase(rawdb.NewMemoryDatabase())
|
tdb := NewDatabaseForTesting()
|
||||||
state, _ := New(types.EmptyRootHash, tdb, nil)
|
state, _ := New(types.EmptyRootHash, tdb)
|
||||||
|
|
||||||
// Create an account and check if the retrieved balance is correct
|
// Create an account and check if the retrieved balance is correct
|
||||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||||
|
@ -787,7 +787,7 @@ func TestCopyCommitCopy(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Commit state, ensure states can be loaded from disk
|
// Commit state, ensure states can be loaded from disk
|
||||||
root, _ := state.Commit(0, false)
|
root, _ := state.Commit(0, false)
|
||||||
state, _ = New(root, tdb, nil)
|
state, _ = New(root, tdb)
|
||||||
if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
|
if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
|
||||||
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
|
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
|
||||||
}
|
}
|
||||||
|
@ -807,7 +807,7 @@ func TestCopyCommitCopy(t *testing.T) {
|
||||||
//
|
//
|
||||||
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
// See https://github.com/ethereum/go-ethereum/issues/20106.
|
||||||
func TestCopyCopyCommitCopy(t *testing.T) {
|
func TestCopyCopyCommitCopy(t *testing.T) {
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
|
||||||
// Create an account and check if the retrieved balance is correct
|
// Create an account and check if the retrieved balance is correct
|
||||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||||
|
@ -876,8 +876,8 @@ func TestCopyCopyCommitCopy(t *testing.T) {
|
||||||
|
|
||||||
// TestCommitCopy tests the copy from a committed state is not fully functional.
|
// TestCommitCopy tests the copy from a committed state is not fully functional.
|
||||||
func TestCommitCopy(t *testing.T) {
|
func TestCommitCopy(t *testing.T) {
|
||||||
db := NewDatabase(rawdb.NewMemoryDatabase())
|
db := NewDatabaseForTesting()
|
||||||
state, _ := New(types.EmptyRootHash, db, nil)
|
state, _ := New(types.EmptyRootHash, db)
|
||||||
|
|
||||||
// Create an account and check if the retrieved balance is correct
|
// Create an account and check if the retrieved balance is correct
|
||||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||||
|
@ -902,7 +902,7 @@ func TestCommitCopy(t *testing.T) {
|
||||||
}
|
}
|
||||||
root, _ := state.Commit(0, true)
|
root, _ := state.Commit(0, true)
|
||||||
|
|
||||||
state, _ = New(root, db, nil)
|
state, _ = New(root, db)
|
||||||
state.SetState(addr, skey2, sval2)
|
state.SetState(addr, skey2, sval2)
|
||||||
state.Commit(1, true)
|
state.Commit(1, true)
|
||||||
|
|
||||||
|
@ -915,10 +915,10 @@ func TestCommitCopy(t *testing.T) {
|
||||||
t.Fatalf("unexpected code: have %x", code)
|
t.Fatalf("unexpected code: have %x", code)
|
||||||
}
|
}
|
||||||
// Miss slots because of non-functional trie after commit
|
// Miss slots because of non-functional trie after commit
|
||||||
if val := copied.GetState(addr, skey1); val != (common.Hash{}) {
|
if val := copied.GetState(addr, skey1); val != sval1 {
|
||||||
t.Fatalf("unexpected storage slot: have %x", sval1)
|
t.Fatalf("unexpected storage slot: have %x", val)
|
||||||
}
|
}
|
||||||
if val := copied.GetCommittedState(addr, skey1); val != (common.Hash{}) {
|
if val := copied.GetCommittedState(addr, skey1); val != sval1 {
|
||||||
t.Fatalf("unexpected storage slot: have %x", val)
|
t.Fatalf("unexpected storage slot: have %x", val)
|
||||||
}
|
}
|
||||||
// Slots cached in the stateDB, available after commit
|
// Slots cached in the stateDB, available after commit
|
||||||
|
@ -928,9 +928,6 @@ func TestCommitCopy(t *testing.T) {
|
||||||
if val := copied.GetCommittedState(addr, skey2); val != sval2 {
|
if val := copied.GetCommittedState(addr, skey2); val != sval2 {
|
||||||
t.Fatalf("unexpected storage slot: have %x", val)
|
t.Fatalf("unexpected storage slot: have %x", val)
|
||||||
}
|
}
|
||||||
if !errors.Is(copied.Error(), trie.ErrCommitted) {
|
|
||||||
t.Fatalf("unexpected state error, %v", copied.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestDeleteCreateRevert tests a weird state transition corner case that we hit
|
// TestDeleteCreateRevert tests a weird state transition corner case that we hit
|
||||||
|
@ -943,13 +940,13 @@ func TestCommitCopy(t *testing.T) {
|
||||||
// first, but the journal wiped the entire state object on create-revert.
|
// first, but the journal wiped the entire state object on create-revert.
|
||||||
func TestDeleteCreateRevert(t *testing.T) {
|
func TestDeleteCreateRevert(t *testing.T) {
|
||||||
// Create an initial state with a single contract
|
// Create an initial state with a single contract
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
|
||||||
addr := common.BytesToAddress([]byte("so"))
|
addr := common.BytesToAddress([]byte("so"))
|
||||||
state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified)
|
state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified)
|
||||||
|
|
||||||
root, _ := state.Commit(0, false)
|
root, _ := state.Commit(0, false)
|
||||||
state, _ = New(root, state.db, state.snaps)
|
state, _ = New(root, state.db)
|
||||||
|
|
||||||
// Simulate self-destructing in one transaction, then create-reverting in another
|
// Simulate self-destructing in one transaction, then create-reverting in another
|
||||||
state.SelfDestruct(addr)
|
state.SelfDestruct(addr)
|
||||||
|
@ -961,7 +958,7 @@ func TestDeleteCreateRevert(t *testing.T) {
|
||||||
|
|
||||||
// Commit the entire state and make sure we don't crash and have the correct state
|
// Commit the entire state and make sure we don't crash and have the correct state
|
||||||
root, _ = state.Commit(0, true)
|
root, _ = state.Commit(0, true)
|
||||||
state, _ = New(root, state.db, state.snaps)
|
state, _ = New(root, state.db)
|
||||||
|
|
||||||
if state.getStateObject(addr) != nil {
|
if state.getStateObject(addr) != nil {
|
||||||
t.Fatalf("self-destructed contract came alive")
|
t.Fatalf("self-destructed contract came alive")
|
||||||
|
@ -992,10 +989,10 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
|
||||||
CleanCacheSize: 0,
|
CleanCacheSize: 0,
|
||||||
}}) // disable caching
|
}}) // disable caching
|
||||||
}
|
}
|
||||||
db := NewDatabaseWithNodeDB(memDb, tdb)
|
db := NewDatabase(tdb, nil)
|
||||||
|
|
||||||
var root common.Hash
|
var root common.Hash
|
||||||
state, _ := New(types.EmptyRootHash, db, nil)
|
state, _ := New(types.EmptyRootHash, db)
|
||||||
addr := common.BytesToAddress([]byte("so"))
|
addr := common.BytesToAddress([]byte("so"))
|
||||||
{
|
{
|
||||||
state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified)
|
state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -1009,7 +1006,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
|
||||||
tdb.Commit(root, false)
|
tdb.Commit(root, false)
|
||||||
}
|
}
|
||||||
// Create a new state on the old root
|
// Create a new state on the old root
|
||||||
state, _ = New(root, db, nil)
|
state, _ = New(root, db)
|
||||||
// Now we clear out the memdb
|
// Now we clear out the memdb
|
||||||
it := memDb.NewIterator(nil, nil)
|
it := memDb.NewIterator(nil, nil)
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
|
@ -1042,9 +1039,8 @@ func TestStateDBAccessList(t *testing.T) {
|
||||||
return common.HexToHash(a)
|
return common.HexToHash(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
memDb := rawdb.NewMemoryDatabase()
|
db := NewDatabaseForTesting()
|
||||||
db := NewDatabase(memDb)
|
state, _ := New(types.EmptyRootHash, db)
|
||||||
state, _ := New(types.EmptyRootHash, db, nil)
|
|
||||||
state.accessList = newAccessList()
|
state.accessList = newAccessList()
|
||||||
|
|
||||||
verifyAddrs := func(astrings ...string) {
|
verifyAddrs := func(astrings ...string) {
|
||||||
|
@ -1213,9 +1209,9 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
||||||
// Create a state trie with many accounts and slots
|
// Create a state trie with many accounts and slots
|
||||||
var (
|
var (
|
||||||
memdb = rawdb.NewMemoryDatabase()
|
memdb = rawdb.NewMemoryDatabase()
|
||||||
triedb = triedb.NewDatabase(memdb, nil)
|
tdb = triedb.NewDatabase(memdb, triedb.HashDefaults)
|
||||||
statedb = NewDatabaseWithNodeDB(memdb, triedb)
|
statedb = NewDatabase(tdb, nil)
|
||||||
state, _ = New(types.EmptyRootHash, statedb, nil)
|
state, _ = New(types.EmptyRootHash, statedb)
|
||||||
)
|
)
|
||||||
for a := byte(0); a < 10; a++ {
|
for a := byte(0); a < 10; a++ {
|
||||||
state.CreateAccount(common.Address{a})
|
state.CreateAccount(common.Address{a})
|
||||||
|
@ -1227,15 +1223,15 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to commit state trie: %v", err)
|
t.Fatalf("failed to commit state trie: %v", err)
|
||||||
}
|
}
|
||||||
triedb.Reference(root, common.Hash{})
|
tdb.Reference(root, common.Hash{})
|
||||||
if err := triedb.Cap(1024); err != nil {
|
if err := tdb.Cap(1024); err != nil {
|
||||||
t.Fatalf("failed to cap trie dirty cache: %v", err)
|
t.Fatalf("failed to cap trie dirty cache: %v", err)
|
||||||
}
|
}
|
||||||
if err := triedb.Commit(root, false); err != nil {
|
if err := tdb.Commit(root, false); err != nil {
|
||||||
t.Fatalf("failed to commit state trie: %v", err)
|
t.Fatalf("failed to commit state trie: %v", err)
|
||||||
}
|
}
|
||||||
// Reopen the state trie from flushed disk and verify it
|
// Reopen the state trie from flushed disk and verify it
|
||||||
state, err = New(root, NewDatabase(memdb), nil)
|
state, err = New(root, NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to reopen state trie: %v", err)
|
t.Fatalf("failed to reopen state trie: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1249,9 +1245,8 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateDBTransientStorage(t *testing.T) {
|
func TestStateDBTransientStorage(t *testing.T) {
|
||||||
memDb := rawdb.NewMemoryDatabase()
|
db := NewDatabaseForTesting()
|
||||||
db := NewDatabase(memDb)
|
state, _ := New(types.EmptyRootHash, db)
|
||||||
state, _ := New(types.EmptyRootHash, db, nil)
|
|
||||||
|
|
||||||
key := common.Hash{0x01}
|
key := common.Hash{0x01}
|
||||||
value := common.Hash{0x02}
|
value := common.Hash{0x02}
|
||||||
|
@ -1286,9 +1281,9 @@ func TestDeleteStorage(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
disk = rawdb.NewMemoryDatabase()
|
disk = rawdb.NewMemoryDatabase()
|
||||||
tdb = triedb.NewDatabase(disk, nil)
|
tdb = triedb.NewDatabase(disk, nil)
|
||||||
db = NewDatabaseWithNodeDB(disk, tdb)
|
|
||||||
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
|
snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash)
|
||||||
state, _ = New(types.EmptyRootHash, db, snaps)
|
db = NewDatabase(tdb, snaps)
|
||||||
|
state, _ = New(types.EmptyRootHash, db)
|
||||||
addr = common.HexToAddress("0x1")
|
addr = common.HexToAddress("0x1")
|
||||||
)
|
)
|
||||||
// Initialize account and populate storage
|
// Initialize account and populate storage
|
||||||
|
@ -1300,9 +1295,10 @@ func TestDeleteStorage(t *testing.T) {
|
||||||
state.SetState(addr, slot, value)
|
state.SetState(addr, slot, value)
|
||||||
}
|
}
|
||||||
root, _ := state.Commit(0, true)
|
root, _ := state.Commit(0, true)
|
||||||
|
|
||||||
// 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, db, snaps)
|
fastState, _ := New(root, NewDatabase(tdb, snaps))
|
||||||
slowState, _ := New(root, db, nil)
|
slowState, _ := New(root, NewDatabase(tdb, nil))
|
||||||
|
|
||||||
obj := fastState.getOrNewStateObject(addr)
|
obj := fastState.getOrNewStateObject(addr)
|
||||||
storageRoot := obj.data.Root
|
storageRoot := obj.data.Root
|
||||||
|
@ -1340,8 +1336,8 @@ func TestStorageDirtiness(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
disk = rawdb.NewMemoryDatabase()
|
disk = rawdb.NewMemoryDatabase()
|
||||||
tdb = triedb.NewDatabase(disk, nil)
|
tdb = triedb.NewDatabase(disk, nil)
|
||||||
db = NewDatabaseWithNodeDB(disk, tdb)
|
db = NewDatabase(tdb, nil)
|
||||||
state, _ = New(types.EmptyRootHash, db, nil)
|
state, _ = New(types.EmptyRootHash, db)
|
||||||
addr = common.HexToAddress("0x1")
|
addr = common.HexToAddress("0x1")
|
||||||
checkDirty = func(key common.Hash, value common.Hash, dirty bool) {
|
checkDirty = func(key common.Hash, value common.Hash, dirty bool) {
|
||||||
obj := state.getStateObject(addr)
|
obj := state.getStateObject(addr)
|
||||||
|
|
|
@ -53,8 +53,8 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c
|
||||||
}
|
}
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
nodeDb := triedb.NewDatabase(db, config)
|
nodeDb := triedb.NewDatabase(db, config)
|
||||||
sdb := NewDatabaseWithNodeDB(db, nodeDb)
|
sdb := NewDatabase(nodeDb, nil)
|
||||||
state, _ := New(types.EmptyRootHash, sdb, nil)
|
state, _ := New(types.EmptyRootHash, sdb)
|
||||||
|
|
||||||
// Fill it with some arbitrary data
|
// Fill it with some arbitrary data
|
||||||
var accounts []*testAccount
|
var accounts []*testAccount
|
||||||
|
@ -94,7 +94,7 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root com
|
||||||
config.PathDB = pathdb.Defaults
|
config.PathDB = pathdb.Defaults
|
||||||
}
|
}
|
||||||
// Check root availability and state contents
|
// Check root availability and state contents
|
||||||
state, err := New(root, NewDatabaseWithConfig(db, &config), nil)
|
state, err := New(root, NewDatabase(triedb.NewDatabase(db, &config), nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
t.Fatalf("failed to create state trie at %x: %v", root, err)
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) e
|
||||||
if scheme == rawdb.PathScheme {
|
if scheme == rawdb.PathScheme {
|
||||||
config.PathDB = pathdb.Defaults
|
config.PathDB = pathdb.Defaults
|
||||||
}
|
}
|
||||||
state, err := New(root, NewDatabaseWithConfig(db, config), nil)
|
state, err := New(root, NewDatabase(triedb.NewDatabase(db, config), nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func filledStateDB() *StateDB {
|
func filledStateDB() *StateDB {
|
||||||
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
|
||||||
// Create an account and check if the retrieved balance is correct
|
// Create an account and check if the retrieved balance is correct
|
||||||
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||||
|
@ -67,8 +67,11 @@ func TestUseAfterTerminate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerklePrefetcher(t *testing.T) {
|
func TestVerklePrefetcher(t *testing.T) {
|
||||||
db := NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), triedb.VerkleDefaults)
|
disk := rawdb.NewMemoryDatabase()
|
||||||
state, err := New(types.EmptyRootHash, db, nil)
|
db := triedb.NewDatabase(disk, triedb.VerkleDefaults)
|
||||||
|
sdb := NewDatabase(db, nil)
|
||||||
|
|
||||||
|
state, err := New(types.EmptyRootHash, sdb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to initialize state: %v", err)
|
t.Fatalf("failed to initialize state: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -82,9 +85,9 @@ func TestVerklePrefetcher(t *testing.T) {
|
||||||
state.SetState(addr, skey, sval) // Change the storage trie
|
state.SetState(addr, skey, sval) // Change the storage trie
|
||||||
root, _ := state.Commit(0, true)
|
root, _ := state.Commit(0, true)
|
||||||
|
|
||||||
state, _ = New(root, db, nil)
|
state, _ = New(root, sdb)
|
||||||
sRoot := state.GetStorageRoot(addr)
|
sRoot := state.GetStorageRoot(addr)
|
||||||
fetcher := newTriePrefetcher(db, root, "", false)
|
fetcher := newTriePrefetcher(sdb, root, "", false)
|
||||||
|
|
||||||
// Read account
|
// Read account
|
||||||
fetcher.prefetch(common.Hash{}, root, common.Address{}, [][]byte{
|
fetcher.prefetch(common.Hash{}, root, common.Address{}, [][]byte{
|
||||||
|
|
|
@ -34,7 +34,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
@ -602,7 +601,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Run("MPT", func(t *testing.T) {
|
t.Run("MPT", func(t *testing.T) {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
test(statedb)
|
test(statedb)
|
||||||
})
|
})
|
||||||
t.Run("Verkle", func(t *testing.T) {
|
t.Run("Verkle", func(t *testing.T) {
|
||||||
|
@ -610,7 +609,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
cacheConfig := DefaultCacheConfigWithScheme(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.NewDatabaseWithNodeDB(db, triedb), nil)
|
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
||||||
test(statedb)
|
test(statedb)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,7 @@ import (
|
||||||
func ExecuteStateless(config *params.ChainConfig, witness *stateless.Witness) (common.Hash, common.Hash, error) {
|
func ExecuteStateless(config *params.ChainConfig, witness *stateless.Witness) (common.Hash, common.Hash, error) {
|
||||||
// Create and populate the state database to serve as the stateless backend
|
// Create and populate the state database to serve as the stateless backend
|
||||||
memdb := witness.MakeHashDB()
|
memdb := witness.MakeHashDB()
|
||||||
|
db, err := state.New(witness.Root(), state.NewDatabase(triedb.NewDatabase(memdb, triedb.HashDefaults), nil))
|
||||||
db, err := state.New(witness.Root(), state.NewDatabaseWithConfig(memdb, triedb.HashDefaults), nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, common.Hash{}, err
|
return common.Hash{}, common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
@ -545,7 +543,7 @@ func TestOpenDrops(t *testing.T) {
|
||||||
store.Close()
|
store.Close()
|
||||||
|
|
||||||
// Create a blob pool out of the pre-seeded data
|
// Create a blob pool out of the pre-seeded data
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -676,7 +674,7 @@ func TestOpenIndex(t *testing.T) {
|
||||||
store.Close()
|
store.Close()
|
||||||
|
|
||||||
// Create a blob pool out of the pre-seeded data
|
// Create a blob pool out of the pre-seeded data
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.Commit(0, true)
|
statedb.Commit(0, true)
|
||||||
|
|
||||||
|
@ -776,7 +774,7 @@ func TestOpenHeap(t *testing.T) {
|
||||||
store.Close()
|
store.Close()
|
||||||
|
|
||||||
// Create a blob pool out of the pre-seeded data
|
// Create a blob pool out of the pre-seeded data
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -856,7 +854,7 @@ func TestOpenCap(t *testing.T) {
|
||||||
// with a high cap to ensure everything was persisted previously
|
// with a high cap to ensure everything was persisted previously
|
||||||
for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} {
|
for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} {
|
||||||
// Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction
|
// Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -1266,7 +1264,7 @@ func TestAdd(t *testing.T) {
|
||||||
keys = make(map[string]*ecdsa.PrivateKey)
|
keys = make(map[string]*ecdsa.PrivateKey)
|
||||||
addrs = make(map[string]common.Address)
|
addrs = make(map[string]common.Address)
|
||||||
)
|
)
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
for acc, seed := range tt.seeds {
|
for acc, seed := range tt.seeds {
|
||||||
// Generate a new random key/address for the seed account
|
// Generate a new random key/address for the seed account
|
||||||
keys[acc], _ = crypto.GenerateKey()
|
keys[acc], _ = crypto.GenerateKey()
|
||||||
|
@ -1328,7 +1326,7 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) {
|
||||||
basefee = uint64(1050)
|
basefee = uint64(1050)
|
||||||
blobfee = uint64(105)
|
blobfee = uint64(105)
|
||||||
signer = types.LatestSigner(testChainConfig)
|
signer = types.LatestSigner(testChainConfig)
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
chain = &testBlockChain{
|
chain = &testBlockChain{
|
||||||
config: testChainConfig,
|
config: testChainConfig,
|
||||||
basefee: uint256.NewInt(basefee),
|
basefee: uint256.NewInt(basefee),
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
@ -80,7 +79,7 @@ func TestTransactionFutureAttack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
config.GlobalQueue = 100
|
config.GlobalQueue = 100
|
||||||
|
@ -117,7 +116,7 @@ func TestTransactionFutureAttack(t *testing.T) {
|
||||||
func TestTransactionFuture1559(t *testing.T) {
|
func TestTransactionFuture1559(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||||
|
@ -150,7 +149,7 @@ func TestTransactionFuture1559(t *testing.T) {
|
||||||
func TestTransactionZAttack(t *testing.T) {
|
func TestTransactionZAttack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||||
|
@ -218,7 +217,7 @@ func TestTransactionZAttack(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkFutureAttack(b *testing.B) {
|
func BenchmarkFutureAttack(b *testing.B) {
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
config.GlobalQueue = 100
|
config.GlobalQueue = 100
|
||||||
|
|
|
@ -31,7 +31,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool"
|
"github.com/ethereum/go-ethereum/core/txpool"
|
||||||
|
@ -160,7 +159,7 @@ func setupPool() (*LegacyPool, *ecdsa.PrivateKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) {
|
func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
|
@ -251,7 +250,7 @@ func (c *testChain) State() (*state.StateDB, error) {
|
||||||
// a state change between those fetches.
|
// a state change between those fetches.
|
||||||
stdb := c.statedb
|
stdb := c.statedb
|
||||||
if *c.trigger {
|
if *c.trigger {
|
||||||
c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
// simulate that the new head block included tx0 and tx1
|
// simulate that the new head block included tx0 and tx1
|
||||||
c.statedb.SetNonce(c.address, 2)
|
c.statedb.SetNonce(c.address, 2)
|
||||||
c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether), tracing.BalanceChangeUnspecified)
|
c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether), tracing.BalanceChangeUnspecified)
|
||||||
|
@ -269,7 +268,7 @@ func TestStateChangeDuringReset(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
key, _ = crypto.GenerateKey()
|
key, _ = crypto.GenerateKey()
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
trigger = false
|
trigger = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -468,7 +467,7 @@ func TestChainFork(t *testing.T) {
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
resetState := func() {
|
resetState := func() {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified)
|
||||||
|
|
||||||
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
|
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
|
||||||
|
@ -497,7 +496,7 @@ func TestDoubleNonce(t *testing.T) {
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
resetState := func() {
|
resetState := func() {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified)
|
statedb.AddBalance(addr, uint256.NewInt(100000000000000), tracing.BalanceChangeUnspecified)
|
||||||
|
|
||||||
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
|
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
|
||||||
|
@ -697,7 +696,7 @@ func TestPostponing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the postponing with
|
// Create the pool to test the postponing with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
@ -910,7 +909,7 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1003,7 +1002,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
evictionInterval = time.Millisecond * 100
|
evictionInterval = time.Millisecond * 100
|
||||||
|
|
||||||
// Create the pool to test the non-expiration enforcement
|
// Create the pool to test the non-expiration enforcement
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1189,7 +1188,7 @@ func TestPendingGlobalLimiting(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1291,7 +1290,7 @@ func TestCapClearsFromAll(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1326,7 +1325,7 @@ func TestPendingMinimumAllowance(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1375,7 +1374,7 @@ func TestRepricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
@ -1495,7 +1494,7 @@ func TestMinGasPriceEnforced(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
txPoolConfig := DefaultConfig
|
txPoolConfig := DefaultConfig
|
||||||
|
@ -1668,7 +1667,7 @@ func TestRepricingKeepsLocals(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
@ -1742,7 +1741,7 @@ func TestUnderpricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -1857,7 +1856,7 @@ func TestStableUnderpricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -2090,7 +2089,7 @@ func TestDeduplication(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
@ -2157,7 +2156,7 @@ func TestReplacement(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
@ -2363,7 +2362,7 @@ func testJournaling(t *testing.T, nolocals bool) {
|
||||||
os.Remove(journal)
|
os.Remove(journal)
|
||||||
|
|
||||||
// Create the original pool to inject transaction into the journal
|
// Create the original pool to inject transaction into the journal
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
|
@ -2464,7 +2463,7 @@ func TestStatusCheck(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the status retrievals with
|
// Create the pool to test the status retrievals with
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
pool := New(testTxPoolConfig, blockchain)
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
@ -86,7 +85,7 @@ func TestEIP2200(t *testing.T) {
|
||||||
for i, tt := range eip2200Tests {
|
for i, tt := range eip2200Tests {
|
||||||
address := common.BytesToAddress([]byte("contract"))
|
address := common.BytesToAddress([]byte("contract"))
|
||||||
|
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.CreateAccount(address)
|
statedb.CreateAccount(address)
|
||||||
statedb.SetCode(address, hexutil.MustDecode(tt.input))
|
statedb.SetCode(address, hexutil.MustDecode(tt.input))
|
||||||
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
||||||
|
@ -138,7 +137,7 @@ func TestCreateGas(t *testing.T) {
|
||||||
var gasUsed = uint64(0)
|
var gasUsed = uint64(0)
|
||||||
doCheck := func(testGas int) bool {
|
doCheck := func(testGas int) bool {
|
||||||
address := common.BytesToAddress([]byte("contract"))
|
address := common.BytesToAddress([]byte("contract"))
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.CreateAccount(address)
|
statedb.CreateAccount(address)
|
||||||
statedb.SetCode(address, hexutil.MustDecode(tt.code))
|
statedb.SetCode(address, hexutil.MustDecode(tt.code))
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
|
|
@ -27,7 +27,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"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/crypto"
|
||||||
|
@ -582,7 +581,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||||
|
|
||||||
func TestOpTstore(t *testing.T) {
|
func TestOpTstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
@ -43,7 +42,7 @@ func TestLoopInterrupt(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range loopInterruptTests {
|
for i, tt := range loopInterruptTests {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.CreateAccount(address)
|
statedb.CreateAccount(address)
|
||||||
statedb.SetCode(address, common.Hex2Bytes(tt))
|
statedb.SetCode(address, common.Hex2Bytes(tt))
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
@ -128,7 +127,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
||||||
setDefaults(cfg)
|
setDefaults(cfg)
|
||||||
|
|
||||||
if cfg.State == nil {
|
if cfg.State == nil {
|
||||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
address = common.BytesToAddress([]byte("contract"))
|
address = common.BytesToAddress([]byte("contract"))
|
||||||
|
@ -165,7 +164,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
||||||
setDefaults(cfg)
|
setDefaults(cfg)
|
||||||
|
|
||||||
if cfg.State == nil {
|
if cfg.State == nil {
|
||||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
vmenv = NewEnv(cfg)
|
vmenv = NewEnv(cfg)
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/asm"
|
"github.com/ethereum/go-ethereum/core/asm"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
@ -105,7 +104,7 @@ func TestExecute(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCall(t *testing.T) {
|
func TestCall(t *testing.T) {
|
||||||
state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
address := common.HexToAddress("0xaa")
|
address := common.HexToAddress("0xaa")
|
||||||
state.SetCode(address, []byte{
|
state.SetCode(address, []byte{
|
||||||
byte(vm.PUSH1), 10,
|
byte(vm.PUSH1), 10,
|
||||||
|
@ -161,7 +160,7 @@ func BenchmarkCall(b *testing.B) {
|
||||||
}
|
}
|
||||||
func benchmarkEVM_Create(bench *testing.B, code string) {
|
func benchmarkEVM_Create(bench *testing.B, code string) {
|
||||||
var (
|
var (
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
sender = common.BytesToAddress([]byte("sender"))
|
sender = common.BytesToAddress([]byte("sender"))
|
||||||
receiver = common.BytesToAddress([]byte("receiver"))
|
receiver = common.BytesToAddress([]byte("receiver"))
|
||||||
)
|
)
|
||||||
|
@ -227,7 +226,7 @@ func BenchmarkEVM_SWAP1(b *testing.B) {
|
||||||
return contract
|
return contract
|
||||||
}
|
}
|
||||||
|
|
||||||
state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
contractAddr := common.BytesToAddress([]byte("contract"))
|
contractAddr := common.BytesToAddress([]byte("contract"))
|
||||||
|
|
||||||
b.Run("10k", func(b *testing.B) {
|
b.Run("10k", func(b *testing.B) {
|
||||||
|
@ -255,7 +254,7 @@ func BenchmarkEVM_RETURN(b *testing.B) {
|
||||||
return contract
|
return contract
|
||||||
}
|
}
|
||||||
|
|
||||||
state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
state, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
contractAddr := common.BytesToAddress([]byte("contract"))
|
contractAddr := common.BytesToAddress([]byte("contract"))
|
||||||
|
|
||||||
for _, n := range []uint64{1_000, 10_000, 100_000, 1_000_000} {
|
for _, n := range []uint64{1_000, 10_000, 100_000, 1_000_000} {
|
||||||
|
@ -393,7 +392,7 @@ func TestBlockhash(t *testing.T) {
|
||||||
func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) {
|
func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) {
|
||||||
cfg := new(Config)
|
cfg := new(Config)
|
||||||
setDefaults(cfg)
|
setDefaults(cfg)
|
||||||
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
cfg.GasLimit = gas
|
cfg.GasLimit = gas
|
||||||
if len(tracerCode) > 0 {
|
if len(tracerCode) > 0 {
|
||||||
tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil)
|
tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil)
|
||||||
|
@ -880,7 +879,7 @@ func TestRuntimeJSTracer(t *testing.T) {
|
||||||
main := common.HexToAddress("0xaa")
|
main := common.HexToAddress("0xaa")
|
||||||
for i, jsTracer := range jsTracers {
|
for i, jsTracer := range jsTracers {
|
||||||
for j, tc := range tests {
|
for j, tc := range tests {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
statedb.SetCode(main, tc.code)
|
statedb.SetCode(main, tc.code)
|
||||||
statedb.SetCode(common.HexToAddress("0xbb"), calleeCode)
|
statedb.SetCode(common.HexToAddress("0xbb"), calleeCode)
|
||||||
statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
|
statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
|
||||||
|
@ -922,7 +921,7 @@ func TestJSTracerCreateTx(t *testing.T) {
|
||||||
exit: function(res) { this.exits++ }}`
|
exit: function(res) { this.exits++ }}`
|
||||||
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
|
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
|
||||||
|
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
|
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -64,8 +64,9 @@ func TestAccountRange(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
|
mdb = rawdb.NewMemoryDatabase()
|
||||||
sdb, _ = state.New(types.EmptyRootHash, statedb, nil)
|
statedb = state.NewDatabase(triedb.NewDatabase(mdb, &triedb.Config{Preimages: true}), nil)
|
||||||
|
sdb, _ = state.New(types.EmptyRootHash, statedb)
|
||||||
addrs = [AccountRangeMaxResults * 2]common.Address{}
|
addrs = [AccountRangeMaxResults * 2]common.Address{}
|
||||||
m = map[common.Address]bool{}
|
m = map[common.Address]bool{}
|
||||||
)
|
)
|
||||||
|
@ -82,7 +83,7 @@ func TestAccountRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root, _ := sdb.Commit(0, true)
|
root, _ := sdb.Commit(0, true)
|
||||||
sdb, _ = state.New(root, statedb, nil)
|
sdb, _ = state.New(root, statedb)
|
||||||
|
|
||||||
trie, err := statedb.OpenTrie(root)
|
trie, err := statedb.OpenTrie(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -135,12 +136,12 @@ func TestEmptyAccountRange(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
statedb = state.NewDatabase(rawdb.NewMemoryDatabase())
|
statedb = state.NewDatabaseForTesting()
|
||||||
st, _ = state.New(types.EmptyRootHash, statedb, nil)
|
st, _ = state.New(types.EmptyRootHash, statedb)
|
||||||
)
|
)
|
||||||
// Commit(although nothing to flush) and re-init the statedb
|
// Commit(although nothing to flush) and re-init the statedb
|
||||||
st.Commit(0, true)
|
st.Commit(0, true)
|
||||||
st, _ = state.New(types.EmptyRootHash, statedb, nil)
|
st, _ = state.New(types.EmptyRootHash, statedb)
|
||||||
|
|
||||||
results := st.RawDump(&state.DumpConfig{
|
results := st.RawDump(&state.DumpConfig{
|
||||||
SkipCode: true,
|
SkipCode: true,
|
||||||
|
@ -161,8 +162,10 @@ func TestStorageRangeAt(t *testing.T) {
|
||||||
|
|
||||||
// Create a state where account 0x010000... has a few storage entries.
|
// Create a state where account 0x010000... has a few storage entries.
|
||||||
var (
|
var (
|
||||||
db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
|
mdb = rawdb.NewMemoryDatabase()
|
||||||
sdb, _ = state.New(types.EmptyRootHash, db, nil)
|
tdb = triedb.NewDatabase(mdb, &triedb.Config{Preimages: true})
|
||||||
|
db = state.NewDatabase(tdb, nil)
|
||||||
|
sdb, _ = state.New(types.EmptyRootHash, db)
|
||||||
addr = common.Address{0x01}
|
addr = common.Address{0x01}
|
||||||
keys = []common.Hash{ // hashes of Keys of storage
|
keys = []common.Hash{ // hashes of Keys of storage
|
||||||
common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"),
|
common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"),
|
||||||
|
@ -181,7 +184,7 @@ func TestStorageRangeAt(t *testing.T) {
|
||||||
sdb.SetState(addr, *entry.Key, entry.Value)
|
sdb.SetState(addr, *entry.Key, entry.Value)
|
||||||
}
|
}
|
||||||
root, _ := sdb.Commit(0, false)
|
root, _ := sdb.Commit(0, false)
|
||||||
sdb, _ = state.New(root, db, nil)
|
sdb, _ = state.New(root, db)
|
||||||
|
|
||||||
// Check a few combinations of limit and start/end.
|
// Check a few combinations of limit and start/end.
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
|
@ -68,8 +68,9 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
||||||
// the internal junks created by tracing will be persisted into the disk.
|
// the internal junks created by tracing will be persisted into the disk.
|
||||||
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
||||||
// please re-enable it for better performance.
|
// please re-enable it for better performance.
|
||||||
database = state.NewDatabaseWithConfig(eth.chainDb, triedb.HashDefaults)
|
tdb := triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
|
||||||
if statedb, err = state.New(block.Root(), database, nil); err == nil {
|
database = state.NewDatabase(tdb, nil)
|
||||||
|
if statedb, err = state.New(block.Root(), database); err == nil {
|
||||||
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
|
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
|
||||||
return statedb, noopReleaser, nil
|
return statedb, noopReleaser, nil
|
||||||
}
|
}
|
||||||
|
@ -86,13 +87,13 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
||||||
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
|
||||||
// please re-enable it for better performance.
|
// please re-enable it for better performance.
|
||||||
tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
|
tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
|
||||||
database = state.NewDatabaseWithNodeDB(eth.chainDb, tdb)
|
database = state.NewDatabase(tdb, nil)
|
||||||
|
|
||||||
// If we didn't check the live database, do check state over ephemeral database,
|
// If we didn't check the live database, do check state over ephemeral database,
|
||||||
// otherwise we would rewind past a persisted block (specific corner case is
|
// otherwise we would rewind past a persisted block (specific corner case is
|
||||||
// chain tracing from the genesis).
|
// chain tracing from the genesis).
|
||||||
if !readOnly {
|
if !readOnly {
|
||||||
statedb, err = state.New(current.Root(), database, nil)
|
statedb, err = state.New(current.Root(), database)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return statedb, noopReleaser, nil
|
return statedb, noopReleaser, nil
|
||||||
}
|
}
|
||||||
|
@ -111,7 +112,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
||||||
}
|
}
|
||||||
current = parent
|
current = parent
|
||||||
|
|
||||||
statedb, err = state.New(current.Root(), database, nil)
|
statedb, err = state.New(current.Root(), database)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -156,7 +157,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
||||||
return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
|
return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
|
||||||
current.NumberU64(), current.Root().Hex(), err)
|
current.NumberU64(), current.Root().Hex(), err)
|
||||||
}
|
}
|
||||||
statedb, err = state.New(root, database, nil)
|
statedb, err = state.New(root, database)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err)
|
return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ func createMiner(t *testing.T) *Miner {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create new chain %v", err)
|
t.Fatalf("can't create new chain %v", err)
|
||||||
}
|
}
|
||||||
statedb, _ := state.New(bc.Genesis().Root(), bc.StateCache(), nil)
|
statedb, _ := state.New(bc.Genesis().Root(), bc.StateCache())
|
||||||
blockchain := &testBlockChain{bc.Genesis().Root(), chainConfig, statedb, 10000000, new(event.Feed)}
|
blockchain := &testBlockChain{bc.Genesis().Root(), chainConfig, statedb, 10000000, new(event.Feed)}
|
||||||
|
|
||||||
pool := legacypool.New(testTxPoolConfig, blockchain)
|
pool := legacypool.New(testTxPoolConfig, blockchain)
|
||||||
|
|
|
@ -222,7 +222,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
|
||||||
if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
|
if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
|
||||||
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
|
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
|
||||||
}
|
}
|
||||||
st.StateDB, _ = state.New(root, st.StateDB.Database(), st.Snapshots)
|
st.StateDB, _ = state.New(root, st.StateDB.Database())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,8 +462,8 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
|
||||||
tconf.PathDB = pathdb.Defaults
|
tconf.PathDB = pathdb.Defaults
|
||||||
}
|
}
|
||||||
triedb := triedb.NewDatabase(db, tconf)
|
triedb := triedb.NewDatabase(db, tconf)
|
||||||
sdb := state.NewDatabaseWithNodeDB(db, triedb)
|
sdb := state.NewDatabase(triedb, nil)
|
||||||
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
|
statedb, _ := state.New(types.EmptyRootHash, sdb)
|
||||||
for addr, a := range accounts {
|
for addr, a := range accounts {
|
||||||
statedb.SetCode(addr, a.Code)
|
statedb.SetCode(addr, a.Code)
|
||||||
statedb.SetNonce(addr, a.Nonce)
|
statedb.SetNonce(addr, a.Nonce)
|
||||||
|
@ -486,7 +486,8 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
|
||||||
}
|
}
|
||||||
snaps, _ = snapshot.New(snapconfig, db, triedb, root)
|
snaps, _ = snapshot.New(snapconfig, db, triedb, root)
|
||||||
}
|
}
|
||||||
statedb, _ = state.New(root, sdb, snaps)
|
sdb = state.NewDatabase(triedb, snaps)
|
||||||
|
statedb, _ = state.New(root, sdb)
|
||||||
return StateTestState{statedb, triedb, snaps}
|
return StateTestState{statedb, triedb, snaps}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ type backend interface {
|
||||||
// types of node backend as an entrypoint. It's responsible for all interactions
|
// types of node backend as an entrypoint. It's responsible for all interactions
|
||||||
// relevant with trie nodes and node preimages.
|
// relevant with trie nodes and node preimages.
|
||||||
type Database struct {
|
type Database struct {
|
||||||
|
disk ethdb.Database
|
||||||
config *Config // Configuration for trie database
|
config *Config // Configuration for trie database
|
||||||
preimages *preimageStore // The store for caching preimages
|
preimages *preimageStore // The store for caching preimages
|
||||||
backend backend // The backend for managing trie nodes
|
backend backend // The backend for managing trie nodes
|
||||||
|
@ -109,6 +110,7 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
|
||||||
preimages = newPreimageStore(diskdb)
|
preimages = newPreimageStore(diskdb)
|
||||||
}
|
}
|
||||||
db := &Database{
|
db := &Database{
|
||||||
|
disk: diskdb,
|
||||||
config: config,
|
config: config,
|
||||||
preimages: preimages,
|
preimages: preimages,
|
||||||
}
|
}
|
||||||
|
@ -327,3 +329,8 @@ func (db *Database) SetBufferSize(size int) error {
|
||||||
func (db *Database) IsVerkle() bool {
|
func (db *Database) IsVerkle() bool {
|
||||||
return db.config.IsVerkle
|
return db.config.IsVerkle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disk returns the underlying disk database.
|
||||||
|
func (db *Database) Disk() ethdb.Database {
|
||||||
|
return db.disk
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue