core, cmd, accounts, eth, light, trie: seperate out CodeStore interface

This commit is contained in:
Gary Rong 2023-09-01 10:51:23 +08:00
parent 577be37e0e
commit b5007068d1
32 changed files with 328 additions and 233 deletions

View file

@ -149,7 +149,7 @@ func (b *SimulatedBackend) rollback(parent *types.Block) {
blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {}) blocks, _ := core.GenerateChain(b.config, parent, ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
b.pendingBlock = blocks[0] b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.blockchain.StateCache(), nil) b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.blockchain.CodeDB(), b.blockchain.TrieDB()), nil)
} }
// Fork creates a side-chain that can be used to simulate reorgs. // Fork creates a side-chain that can be used to simulate reorgs.

View file

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

View file

@ -154,7 +154,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(state.NewCodeDB(db), triedb)
statedb, _ = state.New(genesis.Root(), sdb, nil) statedb, _ = state.New(genesis.Root(), sdb, nil)
chainConfig = genesisConfig.Config chainConfig = genesisConfig.Config

View file

@ -466,7 +466,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(state.NewCodeDB(db), triedb), nil)
if err != nil { if err != nil {
return err return err
} }

View file

@ -209,8 +209,8 @@ type BlockChain struct {
gcproc time.Duration // Accumulates canonical block processing for trie dumping gcproc time.Duration // Accumulates canonical block processing for trie dumping
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
codedb *state.CodeDB // The database handler for maintaining contract codes.
triedb *trie.Database // The database handler for maintaining trie nodes. triedb *trie.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
// txLookupLimit is the maximum number of blocks from head whose tx indices // txLookupLimit is the maximum number of blocks from head whose tx indices
// are reserved: // are reserved:
@ -289,6 +289,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
chainConfig: chainConfig, chainConfig: chainConfig,
cacheConfig: cacheConfig, cacheConfig: cacheConfig,
db: db, db: db,
codedb: state.NewCodeDB(db),
triedb: triedb, triedb: triedb,
triegc: prque.New[int64, common.Hash](nil), triegc: prque.New[int64, common.Hash](nil),
quit: make(chan struct{}), quit: make(chan struct{}),
@ -304,7 +305,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
} }
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
bc.forker = NewForkChoice(bc, shouldPreserve) bc.forker = NewForkChoice(bc, shouldPreserve)
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
bc.validator = NewBlockValidator(chainConfig, bc, engine) bc.validator = NewBlockValidator(chainConfig, bc, engine)
bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine)
bc.processor = NewStateProcessor(chainConfig, bc, engine) bc.processor = NewStateProcessor(chainConfig, bc, engine)
@ -1778,11 +1778,10 @@ 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, state.NewDatabase(bc.codedb, bc.triedb), bc.snaps)
if err != nil { if err != nil {
return it.index, err return it.index, err
} }
// Enable prefetching to pull in trie node paths while processing transactions // Enable prefetching to pull in trie node paths while processing transactions
statedb.StartPrefetcher("chain") statedb.StartPrefetcher("chain")
activeState = statedb activeState = statedb
@ -1792,7 +1791,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, state.NewDatabase(bc.codedb, bc.triedb), bc.snaps)
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) { go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)

View file

@ -278,7 +278,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.StateAt(hash)
return err == nil return err == nil
} }
@ -311,12 +311,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.codedb.ReadCodeWithPrefix(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.
@ -326,7 +323,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, state.NewDatabase(bc.codedb, bc.triedb), bc.snaps)
} }
// Config retrieves the chain's fork configuration. // Config retrieves the chain's fork configuration.
@ -350,11 +347,6 @@ func (bc *BlockChain) Processor() Processor {
return bc.processor return bc.processor
} }
// StateCache returns the caching database underpinning the blockchain instance.
func (bc *BlockChain) StateCache() state.Database {
return bc.stateCache
}
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
func (bc *BlockChain) GasLimit() uint64 { func (bc *BlockChain) GasLimit() uint64 {
return bc.CurrentBlock().GasLimit return bc.CurrentBlock().GasLimit
@ -387,6 +379,11 @@ func (bc *BlockChain) TrieDB() *trie.Database {
return bc.triedb return bc.triedb
} }
// CodeDB retrieves the low level code database used for contract code storage.
func (bc *BlockChain) CodeDB() *state.CodeDB {
return bc.codedb
}
// SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent.
func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription { func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription {
return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch)) return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch))

View file

@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"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"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -2040,7 +2039,6 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
dbconfig.HashDB = hashdb.Defaults dbconfig.HashDB = hashdb.Defaults
} }
chain.triedb = trie.NewDatabase(chain.db, dbconfig) chain.triedb = trie.NewDatabase(chain.db, dbconfig)
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
// Force run a freeze cycle // Force run a freeze cycle
type freezer interface { type freezer interface {

View file

@ -158,7 +158,8 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
} }
return err return err
} }
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) sdb := state.NewDatabase(blockchain.CodeDB(), blockchain.TrieDB())
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), sdb, nil)
if err != nil { if err != nil {
return err return err
} }

View file

@ -364,8 +364,10 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
triedb := trie.NewDatabase(db, trie.HashDefaults) triedb := trie.NewDatabase(db, trie.HashDefaults)
defer triedb.Close() defer triedb.Close()
codedb := state.NewCodeDB(db)
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(codedb, triedb), nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -135,7 +135,8 @@ func (ga *GenesisAlloc) hash(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) memorydb := rawdb.NewMemoryDatabase()
db := state.NewDatabase(state.NewCodeDB(memorydb), trie.NewDatabase(memorydb, config))
statedb, err := state.New(types.EmptyRootHash, db, nil) statedb, err := state.New(types.EmptyRootHash, db, nil)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
@ -150,14 +151,14 @@ func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
statedb.SetState(addr, key, value) statedb.SetState(addr, key, value)
} }
} }
return statedb.Commit(0, false) return statedb.IntermediateRoot(false), nil
} }
// flush is very similar with hash, but the main difference is all the generated // flush is very similar with hash, but the main difference is all the generated
// states will be persisted into the given database. Also, the genesis state // states will be persisted into the given database. Also, the genesis state
// specification will be flushed as well. // specification will be flushed as well.
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil) statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(state.NewCodeDB(db), triedb), nil)
if err != nil { if err != nil {
return err return err
} }

114
core/state/codedb.go Normal file
View file

@ -0,0 +1,114 @@
// Copyright 2023 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"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
)
const (
// Number of codehash->size associations to keep.
codeSizeCacheSize = 100000
// Cache size granted for caching clean code.
codeCacheSize = 64 * 1024 * 1024
)
var errMismatchedLength = errors.New("provided lists have different lengths")
// CodeDB is an implementation of the CodeStore interface, designed for providing
// efficient read and write functionalities for contract code.
type CodeDB struct {
db ethdb.KeyValueStore
size *lru.Cache[common.Hash, int]
cache *lru.SizeConstrainedCache[common.Hash, []byte]
}
// NewCodeDB returns a codeDB instance with given database.
func NewCodeDB(db ethdb.KeyValueStore) *CodeDB {
return &CodeDB{
db: db,
size: lru.NewCache[common.Hash, int](codeSizeCacheSize),
cache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
}
}
// ReadCode implements CodeReader, retrieving a particular contract's code
// with given contract address and code hash.
func (db *CodeDB) ReadCode(address common.Address, codeHash common.Hash) ([]byte, error) {
code, _ := db.cache.Get(codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadCode(db.db, codeHash)
if len(code) > 0 {
db.cache.Add(codeHash, code)
db.size.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
}
// ReadCodeSize implements CodeReader, retrieving a particular contracts code's size
// with given contract address and code hash.
func (db *CodeDB) ReadCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
if cached, ok := db.size.Get(codeHash); ok {
return cached, nil
}
code, err := db.ReadCode(addr, codeHash)
if err != nil {
return 0, err
}
return len(code), nil
}
// WriteCodes implements CodeWriter, writing the provided a list of contract codes
// into database.
func (db *CodeDB) WriteCodes(addresses []common.Address, hashes []common.Hash, codes [][]byte) error {
if len(addresses) != len(hashes) {
return errMismatchedLength
}
if len(addresses) != len(codes) {
return errMismatchedLength
}
batch := db.db.NewBatch()
for i := 0; i < len(addresses); i++ {
rawdb.WriteCode(batch, hashes[i], codes[i])
}
return batch.Write()
}
// ReadCodeWithPrefix retrieves a particular contract's code. If the code can't
// be found in the cache, then check the existence with **new** db scheme.
func (db *CodeDB) ReadCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
code, _ := db.cache.Get(codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadCodeWithPrefix(db.db, codeHash)
if len(code) > 0 {
db.cache.Add(codeHash, code)
db.size.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
}

View file

@ -17,13 +17,10 @@
package state package state
import ( import (
"errors"
"fmt" "fmt"
"github.com/crate-crypto/go-ipa/banderwagon" "github.com/crate-crypto/go-ipa/banderwagon"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/rawdb"
"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"
@ -32,13 +29,7 @@ import (
"github.com/ethereum/go-ethereum/trie/utils" "github.com/ethereum/go-ethereum/trie/utils"
) )
const ( var (
// Number of codehash->size associations to keep.
codeSizeCacheSize = 100000
// Cache size granted for caching clean code.
codeCacheSize = 64 * 1024 * 1024
// commitmentSize is the size of commitment stored in cache. // commitmentSize is the size of commitment stored in cache.
commitmentSize = banderwagon.UncompressedSize commitmentSize = banderwagon.UncompressedSize
@ -46,8 +37,35 @@ const (
commitmentCacheItems = 64 * 1024 * 1024 / (commitmentSize + common.AddressLength) commitmentCacheItems = 64 * 1024 * 1024 / (commitmentSize + common.AddressLength)
) )
// Database wraps access to tries and contract code. // CodeReader wraps the ReadCode and ReadCodeSize methods of a backing contract
// code store, providing an interface for retrieving contract code and its size.
type CodeReader interface {
// ReadCode retrieves a particular contract's code.
ReadCode(addr common.Address, codeHash common.Hash) ([]byte, error)
// ReadCodeSize retrieves a particular contracts code's size.
ReadCodeSize(addr common.Address, codeHash common.Hash) (int, error)
}
// CodeWriter wraps the WriteCodes method of a backing contract code store,
// providing an interface for writing contract codes back to database.
type CodeWriter interface {
// WriteCodes persists the provided a batch of contract codes.
WriteCodes(addresses []common.Address, codeHashes []common.Hash, codes [][]byte) error
}
// CodeStore defines the essential methods for reading and writing contract codes,
// providing a comprehensive interface for code management.
type CodeStore interface {
CodeReader
CodeWriter
}
// Database defines the essential methods for reading and writing ethereum states,
// providing a comprehensive interface for ethereum state management.
type Database interface { type Database interface {
CodeStore
// OpenTrie opens the main account trie. // OpenTrie opens the main account trie.
OpenTrie(root common.Hash) (Trie, error) OpenTrie(root common.Hash) (Trie, error)
@ -57,20 +75,12 @@ type Database interface {
// CopyTrie returns an independent copy of the given trie. // CopyTrie returns an independent copy of the given trie.
CopyTrie(Trie) Trie CopyTrie(Trie) Trie
// ContractCode retrieves a particular contract's code.
ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error)
// ContractCodeSize retrieves a particular contracts code's size.
ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error)
// DiskDB returns the underlying key-value disk database.
DiskDB() ethdb.KeyValueStore
// TrieDB returns the underlying trie database for managing trie nodes. // TrieDB returns the underlying trie database for managing trie nodes.
TrieDB() *trie.Database TrieDB() *trie.Database
} }
// Trie is a Ethereum Merkle Patricia trie. // Trie is a Ethereum state trie interface, defining the essential methods
// to read and write states via trie.
type Trie interface { type Trie interface {
// GetKey returns the sha3 preimage of a hashed key that was previously used // GetKey returns the sha3 preimage of a hashed key that was previously used
// to store a value. // to store a value.
@ -140,40 +150,27 @@ type Trie interface {
Prove(key []byte, proofDb ethdb.KeyValueWriter) error Prove(key []byte, proofDb ethdb.KeyValueWriter) error
} }
// NewDatabase creates a backing store for state. The returned database is safe for // NewDatabase creates a state database with the provided contract code store
// concurrent use, but does not retain any recent trie nodes in memory. To keep some // and trie node database.
// historical state in memory, use the NewDatabaseWithConfig constructor. func NewDatabase(codedb *CodeDB, triedb *trie.Database) Database {
func NewDatabase(db ethdb.Database) Database {
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 *trie.Config) Database {
return &cachingDB{ return &cachingDB{
disk: db, codedb: codedb,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), triedb: triedb,
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
triedb: trie.NewDatabase(db, config),
} }
} }
// NewDatabaseWithNodeDB creates a state database with an already initialized node database. // NewDatabaseForTesting is similar to NewDatabase, but it sets up a local code
func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.Database) Database { // store and trie database with default config by using the provided database,
return &cachingDB{ // specifically intended for testing.
disk: db, func NewDatabaseForTesting(db ethdb.Database) Database {
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), return NewDatabase(NewCodeDB(db), trie.NewDatabase(db, nil))
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
triedb: triedb,
}
} }
// cachingDB is the implementation of Database interface, designed for providing
// functionalities to read and write states.
type cachingDB struct { type cachingDB struct {
disk ethdb.KeyValueStore codedb *CodeDB
codeSizeCache *lru.Cache[common.Hash, int] triedb *trie.Database
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
triedb *trie.Database
} }
// OpenTrie opens the main account trie at a specific root hash. // OpenTrie opens the main account trie at a specific root hash.
@ -181,11 +178,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.triedb.IsVerkle() { if db.triedb.IsVerkle() {
return trie.NewVerkleTrie(root, db.triedb, utils.NewPointCache(commitmentCacheItems)) return trie.NewVerkleTrie(root, db.triedb, utils.NewPointCache(commitmentCacheItems))
} }
tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) return trie.NewStateTrie(trie.StateTrieID(root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
} }
// OpenStorageTrie opens the storage trie of an account. // OpenStorageTrie opens the storage trie of an account.
@ -196,11 +189,7 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
if db.triedb.IsVerkle() { if db.triedb.IsVerkle() {
return self, nil return self, nil
} }
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) return trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
if err != nil {
return nil, err
}
return tr, nil
} }
// CopyTrie returns an independent copy of the given trie. // CopyTrie returns an independent copy of the given trie.
@ -213,50 +202,21 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
} }
} }
// ContractCode retrieves a particular contract's code. // ReadCode implements CodeReader, retrieving a particular contract's code.
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) { func (db *cachingDB) ReadCode(address common.Address, codeHash common.Hash) ([]byte, error) {
code, _ := db.codeCache.Get(codeHash) return db.codedb.ReadCode(address, codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadCode(db.disk, codeHash)
if len(code) > 0 {
db.codeCache.Add(codeHash, code)
db.codeSizeCache.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
} }
// ContractCodeWithPrefix retrieves a particular contract's code. If the // ReadCodeSize implements CodeReader, retrieving a particular contracts
// code can't be found in the cache, then check the existence with **new** // code's size.
// db scheme. func (db *cachingDB) ReadCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) { return db.codedb.ReadCodeSize(addr, codeHash)
code, _ := db.codeCache.Get(codeHash)
if len(code) > 0 {
return code, nil
}
code = rawdb.ReadCodeWithPrefix(db.disk, codeHash)
if len(code) > 0 {
db.codeCache.Add(codeHash, code)
db.codeSizeCache.Add(codeHash, len(code))
return code, nil
}
return nil, errors.New("not found")
} }
// ContractCodeSize retrieves a particular contracts code's size. // WriteCodes implements CodeWriter, writing the provided a list of contract
func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) { // codes into database.
if cached, ok := db.codeSizeCache.Get(codeHash); ok { func (db *cachingDB) WriteCodes(addresses []common.Address, hashes []common.Hash, codes [][]byte) error {
return cached, nil return db.codedb.WriteCodes(addresses, hashes, codes)
}
code, err := db.ContractCode(addr, codeHash)
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.

View file

@ -136,7 +136,7 @@ func (it *nodeIterator) step() error {
} }
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
it.codeHash = common.BytesToHash(account.CodeHash) it.codeHash = common.BytesToHash(account.CodeHash)
it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.CodeHash)) it.code, err = it.state.db.ReadCode(address, common.BytesToHash(account.CodeHash))
if err != nil { if err != nil {
return fmt.Errorf("code %x: %v", account.CodeHash, err) return fmt.Errorf("code %x: %v", account.CodeHash, err)
} }

View file

@ -476,7 +476,7 @@ func (s *stateObject) Code() []byte {
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return nil return nil
} }
code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.CodeHash())) code, err := s.db.db.ReadCode(s.address, common.BytesToHash(s.CodeHash()))
if err != nil { if err != nil {
s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
} }
@ -494,7 +494,7 @@ func (s *stateObject) CodeSize() int {
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return 0 return 0
} }
size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.CodeHash())) size, err := s.db.db.ReadCodeSize(s.address, common.BytesToHash(s.CodeHash()))
if err != nil { if err != nil {
s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
} }

View file

@ -37,14 +37,16 @@ type stateEnv struct {
func newStateEnv() *stateEnv { func newStateEnv() *stateEnv {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
sdb, _ := New(types.EmptyRootHash, NewDatabase(db), nil) sdb, _ := New(types.EmptyRootHash, NewDatabaseForTesting(db), nil)
return &stateEnv{db: db, 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, &trie.Config{Preimages: true}) tdb := trie.NewDatabase(db, &trie.Config{Preimages: true})
sdb, _ := New(types.EmptyRootHash, tdb, nil) defer tdb.Close()
sdb, _ := New(types.EmptyRootHash, NewDatabase(NewCodeDB(db), tdb), nil)
s := &stateEnv{db: db, state: sdb} s := &stateEnv{db: db, state: sdb}
// generate a few entries // generate a few entries
@ -61,7 +63,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, NewDatabase(NewCodeDB(db), tdb), nil)
got := string(s.state.Dump(nil)) got := string(s.state.Dump(nil))
want := `{ want := `{
"root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", "root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2",
@ -100,8 +102,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, &trie.Config{Preimages: true}) tdb := trie.NewDatabase(db, &trie.Config{Preimages: true})
sdb, _ := New(types.EmptyRootHash, tdb, nil) defer tdb.Close()
sdb, _ := New(types.EmptyRootHash, NewDatabase(NewCodeDB(db), tdb), nil)
s := &stateEnv{db: db, state: sdb} s := &stateEnv{db: db, state: sdb}
// generate a few entries // generate a few entries
@ -118,7 +122,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, NewDatabase(NewCodeDB(db), tdb), nil)
b := &bytes.Buffer{} b := &bytes.Buffer{}
s.state.IterativeDump(nil, json.NewEncoder(b)) s.state.IterativeDump(nil, json.NewEncoder(b))
@ -194,7 +198,7 @@ func TestSnapshotEmpty(t *testing.T) {
} }
func TestSnapshot2(t *testing.T) { func TestSnapshot2(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) state, _ := New(types.EmptyRootHash, NewDatabaseForTesting(rawdb.NewMemoryDatabase()), nil)
stateobjaddr0 := common.BytesToAddress([]byte("so0")) stateobjaddr0 := common.BytesToAddress([]byte("so0"))
stateobjaddr1 := common.BytesToAddress([]byte("so1")) stateobjaddr1 := common.BytesToAddress([]byte("so1"))

View file

@ -1171,12 +1171,19 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
// Commit objects to the trie, measuring the elapsed time // Commit objects to the trie, measuring the elapsed time
var ( var (
// Metrics
accountTrieNodesUpdated int accountTrieNodesUpdated int
accountTrieNodesDeleted int accountTrieNodesDeleted int
storageTrieNodesUpdated int storageTrieNodesUpdated int
storageTrieNodesDeleted int storageTrieNodesDeleted int
nodes = trienode.NewMergedNodeSet()
codeWriter = s.db.DiskDB().NewBatch() // Un-flushed contract codes
addresses []common.Address
codeHashes []common.Hash
codes [][]byte
// Un-flushed trie nodes
nodes = trienode.NewMergedNodeSet()
) )
// Handle all state deletions first // Handle all state deletions first
incomplete, err := s.handleDestruction(nodes) incomplete, err := s.handleDestruction(nodes)
@ -1191,8 +1198,12 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
} }
// Write any contract code associated with the state object // Write any contract code associated with the state object
if obj.code != nil && obj.dirtyCode { if obj.code != nil && obj.dirtyCode {
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
obj.dirtyCode = false obj.dirtyCode = false
// Collect dirty contract codes for later write in a single batch.
addresses = append(addresses, addr)
codeHashes = append(codeHashes, common.BytesToHash(obj.CodeHash()))
codes = append(codes, obj.code)
} }
// Write any storage changes in the state object to its storage trie // Write any storage changes in the state object to its storage trie
set, err := obj.commit() set, err := obj.commit()
@ -1211,10 +1222,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
storageTrieNodesDeleted += deleted storageTrieNodesDeleted += deleted
} }
} }
if codeWriter.ValueSize() > 0 { if err := s.db.WriteCodes(addresses, codeHashes, codes); err != nil {
if err := codeWriter.Write(); err != nil { return common.Hash{}, err
log.Crit("Failed to commit dirty codes", "error", err)
}
} }
// Write the account trie changes, measuring the amount of wasted time // Write the account trie changes, measuring the amount of wasted time
var start time.Time var start time.Time

View file

@ -182,7 +182,7 @@ func (test *stateTest) run() bool {
} }
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = trie.NewDatabase(disk, &trie.Config{PathDB: pathdb.Defaults}) tdb = trie.NewDatabase(disk, &trie.Config{PathDB: pathdb.Defaults})
sdb = NewDatabaseWithNodeDB(disk, tdb) sdb = NewDatabase(NewCodeDB(disk), tdb)
byzantium = rand.Intn(2) == 0 byzantium = rand.Intn(2) == 0
) )
defer disk.Close() defer disk.Close()

View file

@ -51,7 +51,7 @@ func TestUpdateLeaks(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
tdb = trie.NewDatabase(db, nil) tdb = trie.NewDatabase(db, nil)
) )
state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil) state, _ := New(types.EmptyRootHash, NewDatabase(NewCodeDB(db), tdb), nil)
// Update it with some accounts // Update it with some accounts
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
@ -87,8 +87,8 @@ func TestIntermediateLeaks(t *testing.T) {
finalDb := rawdb.NewMemoryDatabase() finalDb := rawdb.NewMemoryDatabase()
transNdb := trie.NewDatabase(transDb, nil) transNdb := trie.NewDatabase(transDb, nil)
finalNdb := trie.NewDatabase(finalDb, nil) finalNdb := trie.NewDatabase(finalDb, nil)
transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil) transState, _ := New(types.EmptyRootHash, NewDatabase(NewCodeDB(transDb), transNdb), nil)
finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil) finalState, _ := New(types.EmptyRootHash, NewDatabase(NewCodeDB(finalDb), 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, big.NewInt(int64(11*i)+int64(tweak))) state.SetBalance(addr, big.NewInt(int64(11*i)+int64(tweak)))
@ -163,7 +163,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(rawdb.NewMemoryDatabase()), nil)
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}))
@ -423,7 +423,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(rawdb.NewMemoryDatabase()), nil)
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))
@ -550,7 +550,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(rawdb.NewMemoryDatabase()), nil)
addr := common.HexToAddress("aaaa") addr := common.HexToAddress("aaaa")
state.SetBalance(addr, big.NewInt(42)) state.SetBalance(addr, big.NewInt(42))
@ -567,7 +567,7 @@ 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(rawdb.NewMemoryDatabase())
state, _ := New(types.EmptyRootHash, tdb, nil) state, _ := New(types.EmptyRootHash, tdb, nil)
// Create an account and check if the retrieved balance is correct // Create an account and check if the retrieved balance is correct
@ -641,7 +641,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(rawdb.NewMemoryDatabase()), nil)
// 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")
@ -710,7 +710,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
// TestCommitCopy tests the copy from a committed state is not functional. // TestCommitCopy tests the copy from a committed state is not functional.
func TestCommitCopy(t *testing.T) { func TestCommitCopy(t *testing.T) {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) state, _ := New(types.EmptyRootHash, NewDatabaseForTesting(rawdb.NewMemoryDatabase()), nil)
// 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")
@ -763,7 +763,7 @@ 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(rawdb.NewMemoryDatabase()), nil)
addr := common.BytesToAddress([]byte("so")) addr := common.BytesToAddress([]byte("so"))
state.SetBalance(addr, big.NewInt(1)) state.SetBalance(addr, big.NewInt(1))
@ -812,7 +812,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
CleanCacheSize: 0, CleanCacheSize: 0,
}}) // disable caching }}) // disable caching
} }
db := NewDatabaseWithNodeDB(memDb, triedb) db := NewDatabase(NewCodeDB(memDb), triedb)
var root common.Hash var root common.Hash
state, _ := New(types.EmptyRootHash, db, nil) state, _ := New(types.EmptyRootHash, db, nil)
@ -863,7 +863,7 @@ func TestStateDBAccessList(t *testing.T) {
} }
memDb := rawdb.NewMemoryDatabase() memDb := rawdb.NewMemoryDatabase()
db := NewDatabase(memDb) db := NewDatabaseForTesting(memDb)
state, _ := New(types.EmptyRootHash, db, nil) state, _ := New(types.EmptyRootHash, db, nil)
state.accessList = newAccessList() state.accessList = newAccessList()
@ -1034,7 +1034,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
var ( var (
memdb = rawdb.NewMemoryDatabase() memdb = rawdb.NewMemoryDatabase()
triedb = trie.NewDatabase(memdb, nil) triedb = trie.NewDatabase(memdb, nil)
statedb = NewDatabaseWithNodeDB(memdb, triedb) statedb = NewDatabase(NewCodeDB(memdb), triedb)
state, _ = New(types.EmptyRootHash, statedb, nil) state, _ = New(types.EmptyRootHash, statedb, nil)
) )
for a := byte(0); a < 10; a++ { for a := byte(0); a < 10; a++ {
@ -1055,7 +1055,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
t.Fatalf("failed to commit state trie: %v", err) t.Fatalf("failed to commit state trie: %v", err)
} }
// Reopen the state trie from flushed disk and verify it // Reopen the state trie from flushed disk and verify it
state, err = New(root, NewDatabase(memdb), nil) state, err = New(root, NewDatabaseForTesting(memdb), 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)
} }
@ -1070,7 +1070,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
func TestStateDBTransientStorage(t *testing.T) { func TestStateDBTransientStorage(t *testing.T) {
memDb := rawdb.NewMemoryDatabase() memDb := rawdb.NewMemoryDatabase()
db := NewDatabase(memDb) db := NewDatabaseForTesting(memDb)
state, _ := New(types.EmptyRootHash, db, nil) state, _ := New(types.EmptyRootHash, db, nil)
key := common.Hash{0x01} key := common.Hash{0x01}
@ -1106,7 +1106,7 @@ func TestResetObject(t *testing.T) {
var ( var (
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = trie.NewDatabase(disk, nil) tdb = trie.NewDatabase(disk, nil)
db = NewDatabaseWithNodeDB(disk, tdb) db = NewDatabase(NewCodeDB(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) state, _ = New(types.EmptyRootHash, db, snaps)
addr = common.HexToAddress("0x1") addr = common.HexToAddress("0x1")
@ -1140,7 +1140,7 @@ func TestDeleteStorage(t *testing.T) {
var ( var (
disk = rawdb.NewMemoryDatabase() disk = rawdb.NewMemoryDatabase()
tdb = trie.NewDatabase(disk, nil) tdb = trie.NewDatabase(disk, nil)
db = NewDatabaseWithNodeDB(disk, tdb) db = NewDatabase(NewCodeDB(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) state, _ = New(types.EmptyRootHash, db, snaps)
addr = common.HexToAddress("0x1") addr = common.HexToAddress("0x1")

View file

@ -51,7 +51,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
nodeDb := trie.NewDatabase(db, config) nodeDb := trie.NewDatabase(db, config)
sdb := NewDatabaseWithNodeDB(db, nodeDb) sdb := NewDatabase(NewCodeDB(db), nodeDb)
state, _ := New(types.EmptyRootHash, sdb, nil) state, _ := New(types.EmptyRootHash, sdb, nil)
// Fill it with some arbitrary data // Fill it with some arbitrary data
@ -92,7 +92,10 @@ 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) tdb := trie.NewDatabase(db, &config)
defer tdb.Close()
state, err := New(root, NewDatabase(NewCodeDB(db), tdb), 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)
} }
@ -118,7 +121,10 @@ 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) tdb := trie.NewDatabase(db, config)
defer tdb.Close()
state, err := New(root, NewDatabase(NewCodeDB(db), tdb), nil)
if err != nil { if err != nil {
return err return err
} }
@ -215,7 +221,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s
codeResults = make([]trie.CodeSyncResult, len(codeElements)) codeResults = make([]trie.CodeSyncResult, len(codeElements))
) )
for i, element := range codeElements { for i, element := range codeElements {
data, err := srcDb.ContractCode(common.Address{}, element.code) data, err := srcDb.ReadCode(common.Address{}, element.code)
if err != nil { if err != nil {
t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code) t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code)
} }
@ -335,7 +341,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) {
if len(codeElements) > 0 { if len(codeElements) > 0 {
codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1) codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
for i, element := range codeElements[:len(codeResults)] { for i, element := range codeElements[:len(codeResults)] {
data, err := srcDb.ContractCode(common.Address{}, element.code) data, err := srcDb.ReadCode(common.Address{}, element.code)
if err != nil { if err != nil {
t.Fatalf("failed to retrieve contract bytecode for %x", element.code) t.Fatalf("failed to retrieve contract bytecode for %x", element.code)
} }
@ -437,7 +443,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) {
if len(codeQueue) > 0 { if len(codeQueue) > 0 {
results := make([]trie.CodeSyncResult, 0, len(codeQueue)) results := make([]trie.CodeSyncResult, 0, len(codeQueue))
for hash := range codeQueue { for hash := range codeQueue {
data, err := srcDb.ContractCode(common.Address{}, hash) data, err := srcDb.ReadCode(common.Address{}, hash)
if err != nil { if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash) t.Fatalf("failed to retrieve node data for %x", hash)
} }
@ -532,7 +538,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) {
for hash := range codeQueue { for hash := range codeQueue {
delete(codeQueue, hash) delete(codeQueue, hash)
data, err := srcDb.ContractCode(common.Address{}, hash) data, err := srcDb.ReadCode(common.Address{}, hash)
if err != nil { if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash) t.Fatalf("failed to retrieve node data for %x", hash)
} }
@ -648,7 +654,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) {
if len(codeQueue) > 0 { if len(codeQueue) > 0 {
results := make([]trie.CodeSyncResult, 0, len(codeQueue)) results := make([]trie.CodeSyncResult, 0, len(codeQueue))
for hash := range codeQueue { for hash := range codeQueue {
data, err := srcDb.ContractCode(common.Address{}, hash) data, err := srcDb.ReadCode(common.Address{}, hash)
if err != nil { if err != nil {
t.Fatalf("failed to retrieve node data for %x", hash) t.Fatalf("failed to retrieve node data for %x", hash)
} }

View file

@ -27,7 +27,7 @@ import (
) )
func filledStateDB() *StateDB { func filledStateDB() *StateDB {
state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) state, _ := New(types.EmptyRootHash, NewDatabaseForTesting(rawdb.NewMemoryDatabase()), nil)
// 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")

View file

@ -511,7 +511,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(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), big.NewInt(1000000)) statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), big.NewInt(1000000))
statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), big.NewInt(1000000)) statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), big.NewInt(1000000))
statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), big.NewInt(1000000)) statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), big.NewInt(1000000))
@ -636,7 +636,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(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr, big.NewInt(1_000_000_000)) statedb.AddBalance(addr, big.NewInt(1_000_000_000))
statedb.Commit(0, true) statedb.Commit(0, true)
@ -736,7 +736,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(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr1, big.NewInt(1_000_000_000)) statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
statedb.AddBalance(addr2, big.NewInt(1_000_000_000)) statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
statedb.AddBalance(addr3, big.NewInt(1_000_000_000)) statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
@ -816,7 +816,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(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr1, big.NewInt(1_000_000_000)) statedb.AddBalance(addr1, big.NewInt(1_000_000_000))
statedb.AddBalance(addr2, big.NewInt(1_000_000_000)) statedb.AddBalance(addr2, big.NewInt(1_000_000_000))
statedb.AddBalance(addr3, big.NewInt(1_000_000_000)) statedb.AddBalance(addr3, big.NewInt(1_000_000_000))
@ -1203,7 +1203,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(rawdb.NewDatabase(memorydb.New())), nil)
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()

View file

@ -78,7 +78,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(rawdb.NewMemoryDatabase()), nil)
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
@ -115,7 +115,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(rawdb.NewMemoryDatabase()), nil)
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(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()) pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
@ -148,7 +148,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(rawdb.NewMemoryDatabase()), nil)
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(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()) pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
@ -216,7 +216,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(rawdb.NewMemoryDatabase()), nil)
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

View file

@ -158,7 +158,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed))
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
@ -252,7 +252,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(rawdb.NewMemoryDatabase()), nil)
// 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(big.Int).SetUint64(params.Ether)) c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
@ -270,7 +270,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(rawdb.NewMemoryDatabase()), nil)
trigger = false trigger = false
) )
@ -469,7 +469,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(rawdb.NewMemoryDatabase()), nil)
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
@ -498,7 +498,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(rawdb.NewMemoryDatabase()), nil)
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
@ -698,7 +698,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -911,7 +911,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1004,7 +1004,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1190,7 +1190,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1292,7 +1292,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1327,7 +1327,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1376,7 +1376,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -1496,7 +1496,8 @@ 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) memorydb := rawdb.NewMemoryDatabase()
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(state.NewCodeDB(memorydb), trie.NewDatabase(memorydb, nil)), nil)
blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed))
txPoolConfig := DefaultConfig txPoolConfig := DefaultConfig
@ -1669,7 +1670,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
pool := New(testTxPoolConfig, blockchain) pool := New(testTxPoolConfig, blockchain)
@ -1743,7 +1744,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -1858,7 +1859,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -2091,7 +2092,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -2158,7 +2159,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -2364,7 +2365,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(rawdb.NewMemoryDatabase()), nil)
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
config := testTxPoolConfig config := testTxPoolConfig
@ -2465,7 +2466,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(rawdb.NewMemoryDatabase()), nil)
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)

View file

@ -84,7 +84,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(rawdb.NewMemoryDatabase()), nil)
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}))
@ -136,7 +136,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(rawdb.NewMemoryDatabase()), nil)
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)

View file

@ -582,7 +582,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(rawdb.NewMemoryDatabase()), nil)
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{}) env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
stack = newstack() stack = newstack()
mem = NewMemory() mem = NewMemory()

View file

@ -43,7 +43,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(rawdb.NewMemoryDatabase()), nil)
statedb.CreateAccount(address) statedb.CreateAccount(address)
statedb.SetCode(address, common.Hex2Bytes(tt)) statedb.SetCode(address, common.Hex2Bytes(tt))
statedb.Finalise(true) statedb.Finalise(true)

View file

@ -114,7 +114,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(rawdb.NewMemoryDatabase()), nil)
} }
var ( var (
address = common.BytesToAddress([]byte("contract")) address = common.BytesToAddress([]byte("contract"))
@ -148,7 +148,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(rawdb.NewMemoryDatabase()), nil)
} }
var ( var (
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)

View file

@ -103,7 +103,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(rawdb.NewMemoryDatabase()), nil)
address := common.HexToAddress("0x0a") address := common.HexToAddress("0x0a")
state.SetCode(address, []byte{ state.SetCode(address, []byte{
byte(vm.PUSH1), 10, byte(vm.PUSH1), 10,
@ -159,7 +159,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(rawdb.NewMemoryDatabase()), nil)
sender = common.BytesToAddress([]byte("sender")) sender = common.BytesToAddress([]byte("sender"))
receiver = common.BytesToAddress([]byte("receiver")) receiver = common.BytesToAddress([]byte("receiver"))
) )
@ -327,7 +327,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -818,7 +818,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(rawdb.NewMemoryDatabase()), nil)
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)
@ -860,7 +860,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(rawdb.NewMemoryDatabase()), nil)
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)

View file

@ -36,7 +36,7 @@ import (
var dumper = spew.ConfigState{Indent: " "} var dumper = spew.ConfigState{Indent: " "}
func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump { func accountRangeTest(t *testing.T, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump {
result := statedb.RawDump(&state.DumpConfig{ result := statedb.RawDump(&state.DumpConfig{
SkipCode: true, SkipCode: true,
SkipStorage: true, SkipStorage: true,
@ -63,11 +63,13 @@ func TestAccountRange(t *testing.T) {
t.Parallel() t.Parallel()
var ( var (
statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true}) disk = rawdb.NewMemoryDatabase()
sdb, _ = state.New(types.EmptyRootHash, statedb, nil) tdb = trie.NewDatabase(disk, &trie.Config{Preimages: true})
addrs = [AccountRangeMaxResults * 2]common.Address{} sdb, _ = state.New(types.EmptyRootHash, state.NewDatabase(state.NewCodeDB(disk), tdb), nil)
m = map[common.Address]bool{} addrs = [AccountRangeMaxResults * 2]common.Address{}
m = map[common.Address]bool{}
) )
defer tdb.Close()
for i := range addrs { for i := range addrs {
hash := common.HexToHash(fmt.Sprintf("%x", i)) hash := common.HexToHash(fmt.Sprintf("%x", i))
@ -81,16 +83,12 @@ 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, state.NewDatabase(state.NewCodeDB(disk), tdb), nil)
trie, err := statedb.OpenTrie(root) accountRangeTest(t, sdb, common.Hash{}, AccountRangeMaxResults/2, AccountRangeMaxResults/2)
if err != nil {
t.Fatal(err)
}
accountRangeTest(t, &trie, sdb, common.Hash{}, AccountRangeMaxResults/2, AccountRangeMaxResults/2)
// test pagination // test pagination
firstResult := accountRangeTest(t, &trie, sdb, common.Hash{}, AccountRangeMaxResults, AccountRangeMaxResults) firstResult := accountRangeTest(t, sdb, common.Hash{}, AccountRangeMaxResults, AccountRangeMaxResults)
secondResult := accountRangeTest(t, &trie, sdb, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults) secondResult := accountRangeTest(t, sdb, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults)
hList := make([]common.Hash, 0) hList := make([]common.Hash, 0)
for addr1, acc := range firstResult.Accounts { for addr1, acc := range firstResult.Accounts {
@ -108,7 +106,7 @@ func TestAccountRange(t *testing.T) {
// set and get an even split between the first and second sets. // set and get an even split between the first and second sets.
slices.SortFunc(hList, common.Hash.Cmp) slices.SortFunc(hList, common.Hash.Cmp)
middleH := hList[AccountRangeMaxResults/2] middleH := hList[AccountRangeMaxResults/2]
middleResult := accountRangeTest(t, &trie, sdb, middleH, AccountRangeMaxResults, AccountRangeMaxResults) middleResult := accountRangeTest(t, sdb, middleH, AccountRangeMaxResults, AccountRangeMaxResults)
missing, infirst, insecond := 0, 0, 0 missing, infirst, insecond := 0, 0, 0
for h := range middleResult.Accounts { for h := range middleResult.Accounts {
if _, ok := firstResult.Accounts[h]; ok { if _, ok := firstResult.Accounts[h]; ok {
@ -134,7 +132,7 @@ func TestEmptyAccountRange(t *testing.T) {
t.Parallel() t.Parallel()
var ( var (
statedb = state.NewDatabase(rawdb.NewMemoryDatabase()) statedb = state.NewDatabaseForTesting(rawdb.NewMemoryDatabase())
st, _ = state.New(types.EmptyRootHash, statedb, nil) st, _ = state.New(types.EmptyRootHash, statedb, nil)
) )
// Commit(although nothing to flush) and re-init the statedb // Commit(although nothing to flush) and re-init the statedb
@ -160,8 +158,9 @@ 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(), &trie.Config{Preimages: true}) disk = rawdb.NewMemoryDatabase()
sdb, _ = state.New(types.EmptyRootHash, db, nil) tdb = trie.NewDatabase(disk, &trie.Config{Preimages: true})
sdb, _ = state.New(types.EmptyRootHash, state.NewDatabase(state.NewCodeDB(disk), tdb), nil)
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"),
@ -176,11 +175,13 @@ func TestStorageRangeAt(t *testing.T) {
keys[3]: {Key: &common.Hash{0x03}, Value: common.Hash{0x04}}, keys[3]: {Key: &common.Hash{0x03}, Value: common.Hash{0x04}},
} }
) )
defer tdb.Close()
for _, entry := range storage { for _, entry := range storage {
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, state.NewDatabase(state.NewCodeDB(disk), tdb), nil)
// Check a few combinations of limit and start/end. // Check a few combinations of limit and start/end.
tests := []struct { tests := []struct {

View file

@ -67,8 +67,8 @@ 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, trie.HashDefaults) tdb := trie.NewDatabase(eth.chainDb, trie.HashDefaults)
if statedb, err = state.New(block.Root(), database, nil); err == nil { if statedb, err = state.New(block.Root(), state.NewDatabase(state.NewCodeDB(eth.chainDb), tdb), nil); 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
} }
@ -85,7 +85,7 @@ 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.
triedb = trie.NewDatabase(eth.chainDb, trie.HashDefaults) triedb = trie.NewDatabase(eth.chainDb, trie.HashDefaults)
database = state.NewDatabaseWithNodeDB(eth.chainDb, triedb) database = state.NewDatabase(state.NewCodeDB(eth.chainDb), triedb)
// If we didn't check the live database, do check state over ephemeral database, // If we didn't check the live database, do check state over ephemeral database,
// otherwise we would rewind past a persisted block (specific corner case is // otherwise we would rewind past a persisted block (specific corner case is

View file

@ -313,7 +313,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) {
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(), state.NewDatabase(bc.CodeDB(), bc.TrieDB()), nil)
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)

View file

@ -317,7 +317,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
tconf.PathDB = pathdb.Defaults tconf.PathDB = pathdb.Defaults
} }
triedb := trie.NewDatabase(db, tconf) triedb := trie.NewDatabase(db, tconf)
sdb := state.NewDatabaseWithNodeDB(db, triedb) sdb := state.NewDatabase(state.NewCodeDB(db), triedb)
statedb, _ := state.New(types.EmptyRootHash, sdb, nil) statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) statedb.SetCode(addr, a.Code)