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 a7842c9cae
commit e104cbc902
38 changed files with 359 additions and 274 deletions

View file

@ -148,7 +148,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

@ -336,7 +336,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

@ -149,7 +149,7 @@ func runCmd(ctx *cli.Context) error {
}) })
defer triedb.Close() defer triedb.Close()
genesis := gen.MustCommit(db, triedb) genesis := gen.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 = gen.Config chainConfig = gen.Config
} else { } else {
@ -159,7 +159,7 @@ func runCmd(ctx *cli.Context) error {
HashDB: hashdb.Defaults, HashDB: hashdb.Defaults,
}) })
defer triedb.Close() defer triedb.Close()
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)
genesisConfig = new(core.Genesis) genesisConfig = new(core.Genesis)
} }

View file

@ -476,7 +476,7 @@ func dump(ctx *cli.Context) error {
triedb := utils.MakeTrieDatabase(ctx, db, true, false) // always enable preimage lookup triedb := utils.MakeTrieDatabase(ctx, db, 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)
@ -1781,11 +1781,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
@ -1795,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, 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

@ -343,8 +343,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

@ -124,7 +124,8 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { func (ga *GenesisAlloc) deriveHash() (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.NewDatabase(rawdb.NewMemoryDatabase()) memorydb := rawdb.NewMemoryDatabase()
db := state.NewDatabase(state.NewCodeDB(memorydb), trie.NewDatabase(memorydb, trie.HashDefaults))
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
@ -139,14 +140,14 @@ func (ga *GenesisAlloc) deriveHash() (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 deriveHash, but the main difference is // flush is very similar with deriveHash, but the main difference is
// all the generated states will be persisted into the given database. // all the generated states will be persisted into the given database.
// Also, the genesis state specification will be flushed as well. // Also, the genesis state 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
} }

111
core/state/codestore.go Normal file
View file

@ -0,0 +1,111 @@
// 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)
return len(code), err
}
// 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,12 +17,9 @@
package state package state
import ( import (
"errors"
"fmt" "fmt"
"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"
@ -30,16 +27,34 @@ import (
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
) )
const ( // CodeReader wraps the ReadCode and ReadCodeSize methods of a backing contract
// Number of codehash->size associations to keep. // code store, providing an interface for retrieving contract code and its size.
codeSizeCacheSize = 100000 type CodeReader interface {
// ReadCode retrieves a particular contract's code.
ReadCode(addr common.Address, codeHash common.Hash) ([]byte, error)
// Cache size granted for caching clean code. // ReadCodeSize retrieves a particular contracts code's size.
codeCacheSize = 64 * 1024 * 1024 ReadCodeSize(addr common.Address, codeHash common.Hash) (int, error)
) }
// Database wraps access to tries and contract code. // 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(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)
@ -49,20 +64,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.
@ -70,11 +77,6 @@ type Trie interface {
// TODO(fjl): remove this when StateTrie is removed // TODO(fjl): remove this when StateTrie is removed
GetKey([]byte) []byte GetKey([]byte) []byte
// GetStorage returns the value for key stored in the trie. The value bytes
// must not be modified by the caller. If a node was not found in the database,
// a trie.MissingNodeError is returned.
GetStorage(addr common.Address, key []byte) ([]byte, error)
// GetAccount abstracts an account read from the trie. It retrieves the // GetAccount abstracts an account read from the trie. It retrieves the
// account blob from the trie with provided account address and decodes it // account blob from the trie with provided account address and decodes it
// with associated decoding algorithm. If the specified account is not in // with associated decoding algorithm. If the specified account is not in
@ -83,27 +85,32 @@ type Trie interface {
// be returned. // be returned.
GetAccount(address common.Address) (*types.StateAccount, error) GetAccount(address common.Address) (*types.StateAccount, error)
// UpdateStorage associates key with value in the trie. If value has length zero, // GetStorage returns the value for key stored in the trie. The value bytes
// any existing value is deleted from the trie. The value bytes must not be modified // must not be modified by the caller. If a node was not found in the database,
// by the caller while they are stored in the trie. If a node was not found in the // a trie.MissingNodeError is returned.
// database, a trie.MissingNodeError is returned. GetStorage(addr common.Address, key []byte) ([]byte, error)
UpdateStorage(addr common.Address, key, value []byte) error
// UpdateAccount abstracts an account write to the trie. It encodes the // UpdateAccount abstracts an account write to the trie. It encodes the
// provided account object with associated algorithm and then updates it // provided account object with associated algorithm and then updates it
// in the trie with provided address. // in the trie with provided address.
UpdateAccount(address common.Address, account *types.StateAccount) error UpdateAccount(address common.Address, account *types.StateAccount) error
// UpdateContractCode abstracts code write to the trie. It is expected // UpdateStorage associates key with value in the trie. If value has length zero,
// to be moved to the stateWriter interface when the latter is ready. // any existing value is deleted from the trie. The value bytes must not be modified
UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error // by the caller while they are stored in the trie. If a node was not found in the
// database, a trie.MissingNodeError is returned.
UpdateStorage(addr common.Address, key, value []byte) error
// DeleteAccount abstracts an account deletion from the trie.
DeleteAccount(address common.Address) error
// DeleteStorage removes any existing value for key from the trie. If a node // DeleteStorage removes any existing value for key from the trie. If a node
// was not found in the database, a trie.MissingNodeError is returned. // was not found in the database, a trie.MissingNodeError is returned.
DeleteStorage(addr common.Address, key []byte) error DeleteStorage(addr common.Address, key []byte) error
// DeleteAccount abstracts an account deletion from the trie. // UpdateContractCode abstracts code write to the trie. It is expected
DeleteAccount(address common.Address) error // to be moved to the stateWriter interface when the latter is ready.
UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error
// Hash returns the root hash of the trie. It does not write to the database and // Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one. // can be used even if the trie doesn't have one.
@ -132,58 +139,37 @@ 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.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
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.
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) { func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) {
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.
@ -196,50 +182,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

@ -472,7 +472,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))
} }
@ -490,7 +490,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",
@ -97,8 +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, &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
@ -115,7 +119,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))
@ -191,7 +195,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

@ -1174,12 +1174,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)
@ -1194,8 +1201,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()
@ -1214,10 +1225,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
) )
@ -552,7 +552,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))
@ -569,7 +569,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
@ -643,7 +643,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")
@ -712,7 +712,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")
@ -765,7 +765,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))
@ -814,7 +814,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)
@ -865,7 +865,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()
@ -1036,7 +1036,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++ {
@ -1057,7 +1057,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)
} }
@ -1072,7 +1072,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}
@ -1108,7 +1108,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")
@ -1142,7 +1142,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)
@ -1625,7 +1625,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)
@ -1699,7 +1699,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
@ -1814,7 +1814,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
@ -2047,7 +2047,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)
@ -2114,7 +2114,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)
@ -2320,7 +2320,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
@ -2421,7 +2421,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

@ -109,7 +109,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"))
@ -143,7 +143,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

@ -35,7 +35,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.IteratorDump { func accountRangeTest(t *testing.T, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump {
result := statedb.IteratorDump(&state.DumpConfig{ result := statedb.IteratorDump(&state.DumpConfig{
SkipCode: true, SkipCode: true,
SkipStorage: true, SkipStorage: true,
@ -62,11 +62,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))
@ -80,16 +82,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 := range firstResult.Accounts { for addr1 := range firstResult.Accounts {
@ -107,7 +105,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 {
@ -133,7 +131,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
@ -159,8 +157,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"),
@ -175,11 +174,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

@ -535,7 +535,7 @@ func testGetNodeData(t *testing.T, protocol uint, drop bool) {
accounts := []common.Address{testAddr, acc1Addr, acc2Addr} accounts := []common.Address{testAddr, acc1Addr, acc2Addr}
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
root := backend.chain.GetBlockByNumber(i).Root() root := backend.chain.GetBlockByNumber(i).Root()
reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil) reconstructed, _ := state.New(root, state.NewDatabaseForTesting(reconstructDB), nil)
for j, acc := range accounts { for j, acc := range accounts {
state, _ := backend.chain.StateAt(root) state, _ := backend.chain.StateAt(root)
bw := state.GetBalance(acc) bw := state.GetBalance(acc)

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

@ -22,9 +22,9 @@ 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/state"
"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/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -310,7 +310,7 @@ func handleGetCode(msg Decoder) (serveRequestFn, uint64, uint64, error) {
p.bumpInvalid() p.bumpInvalid()
continue continue
} }
code, err := bc.StateCache().ContractCode(address, common.BytesToHash(account.CodeHash)) code, err := bc.CodeDB().ReadCode(address, common.BytesToHash(account.CodeHash))
if err != nil { if err != nil {
p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", address, "codehash", common.BytesToHash(account.CodeHash), "err", err) p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", address, "codehash", common.BytesToHash(account.CodeHash), "err", err)
continue continue
@ -409,14 +409,12 @@ func handleGetProofs(msg Decoder) (serveRequestFn, uint64, uint64, error) {
continue continue
} }
// Open the account or storage trie for the request // Open the account or storage trie for the request
statedb := bc.StateCache() var tr *trie.StateTrie
var trie state.Trie
switch len(request.AccountAddress) { switch len(request.AccountAddress) {
case 0: case 0:
// No account key specified, open an account trie // No account key specified, open an account trie
trie, err = statedb.OpenTrie(root) tr, err = trie.NewStateTrie(trie.StateTrieID(root), bc.TrieDB())
if trie == nil || err != nil { if err != nil {
p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err) p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err)
continue continue
} }
@ -429,14 +427,14 @@ func handleGetProofs(msg Decoder) (serveRequestFn, uint64, uint64, error) {
p.bumpInvalid() p.bumpInvalid()
continue continue
} }
trie, err = statedb.OpenStorageTrie(root, address, account.Root) tr, err = trie.NewStateTrie(trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), account.Root), bc.TrieDB())
if trie == nil || err != nil { if err != nil {
p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", address, "root", account.Root, "err", err) p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", address, "root", account.Root, "err", err)
continue continue
} }
} }
// Prove the user's request from the account or storage trie // Prove the user's request from the account or storage trie
if err := trie.Prove(request.Key, nodes); err != nil { if err := tr.Prove(request.Key, nodes); err != nil {
p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err) p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err)
continue continue
} }

View file

@ -57,7 +57,7 @@ type testOdr struct {
OdrBackend OdrBackend
indexerConfig *IndexerConfig indexerConfig *IndexerConfig
sdb, ldb ethdb.Database sdb, ldb ethdb.Database
serverState state.Database triedb *trie.Database
disable bool disable bool
} }
@ -88,9 +88,9 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
t state.Trie t state.Trie
) )
if len(req.Id.AccountAddress) > 0 { if len(req.Id.AccountAddress) > 0 {
t, err = odr.serverState.OpenStorageTrie(req.Id.StateRoot, common.BytesToAddress(req.Id.AccountAddress), req.Id.Root) t, err = trie.NewStateTrie(trie.StorageTrieID(req.Id.StateRoot, crypto.Keccak256Hash(req.Id.AccountAddress), req.Id.Root), odr.triedb)
} else { } else {
t, err = odr.serverState.OpenTrie(req.Id.Root) t, err = trie.NewStateTrie(trie.StateTrieID(req.Id.StateRoot), odr.triedb)
} }
if err != nil { if err != nil {
panic(err) panic(err)
@ -162,7 +162,7 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc
st = NewState(ctx, header, lc.Odr()) st = NewState(ctx, header, lc.Odr())
} else { } else {
header := bc.GetHeaderByHash(bhash) header := bc.GetHeaderByHash(bhash)
st, _ = state.New(header.Root, bc.StateCache(), nil) st, _ = state.New(header.Root, state.NewDatabase(bc.CodeDB(), bc.TrieDB()), nil)
} }
var res []byte var res []byte
@ -196,7 +196,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
} else { } else {
chain = bc chain = bc
header = bc.GetHeaderByHash(bhash) header = bc.GetHeaderByHash(bhash)
st, _ = state.New(header.Root, bc.StateCache(), nil) st, _ = state.New(header.Root, state.NewDatabase(bc.CodeDB(), bc.TrieDB()), nil)
} }
// Perform read-only call. // Perform read-only call.
@ -284,7 +284,7 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
} }
gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults)) gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults))
odr := &testOdr{sdb: sdb, ldb: ldb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} odr := &testOdr{sdb: sdb, ldb: ldb, triedb: blockchain.TrieDB(), indexerConfig: TestClientIndexerConfig}
lightchain, err := NewLightChain(odr, gspec.Config, ethash.NewFullFaker()) lightchain, err := NewLightChain(odr, gspec.Config, ethash.NewFullFaker())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -72,7 +72,7 @@ func (db *odrDatabase) CopyTrie(t state.Trie) state.Trie {
} }
} }
func (db *odrDatabase) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) { func (db *odrDatabase) ReadCode(addr common.Address, codeHash common.Hash) ([]byte, error) {
if codeHash == sha3Nil { if codeHash == sha3Nil {
return nil, nil return nil, nil
} }
@ -87,19 +87,19 @@ func (db *odrDatabase) ContractCode(addr common.Address, codeHash common.Hash) (
return req.Data, err return req.Data, err
} }
func (db *odrDatabase) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) { func (db *odrDatabase) ReadCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
code, err := db.ContractCode(addr, codeHash) code, err := db.ReadCode(addr, codeHash)
return len(code), err return len(code), err
} }
func (db *odrDatabase) WriteCodes(addresses []common.Address, hashes []common.Hash, codes [][]byte) error {
panic("not implemented")
}
func (db *odrDatabase) TrieDB() *trie.Database { func (db *odrDatabase) TrieDB() *trie.Database {
return nil return nil
} }
func (db *odrDatabase) DiskDB() ethdb.KeyValueStore {
panic("not implemented")
}
type odrTrie struct { type odrTrie struct {
db *odrDatabase db *odrDatabase
id *TrieID id *TrieID

View file

@ -52,10 +52,10 @@ func TestNodeIterator(t *testing.T) {
gspec.MustCommit(lightdb, trie.NewDatabase(lightdb, trie.HashDefaults)) gspec.MustCommit(lightdb, trie.NewDatabase(lightdb, trie.HashDefaults))
ctx := context.Background() ctx := context.Background()
odr := &testOdr{sdb: fulldb, ldb: lightdb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} odr := &testOdr{sdb: fulldb, ldb: lightdb, triedb: blockchain.TrieDB(), indexerConfig: TestClientIndexerConfig}
head := blockchain.CurrentHeader() head := blockchain.CurrentHeader()
lightTrie, _ := NewStateDatabase(ctx, head, odr).OpenTrie(head.Root) lightTrie, _ := NewStateDatabase(ctx, head, odr).OpenTrie(head.Root)
fullTrie, _ := blockchain.StateCache().OpenTrie(head.Root) fullTrie, _ := trie.NewStateTrie(trie.StateTrieID(head.Root), blockchain.TrieDB())
if err := diffTries(fullTrie, lightTrie); err != nil { if err := diffTries(fullTrie, lightTrie); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -98,7 +98,7 @@ func TestTxPool(t *testing.T) {
} }
gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults)) gspec.MustCommit(ldb, trie.NewDatabase(ldb, trie.HashDefaults))
odr := &testOdr{sdb: sdb, ldb: ldb, serverState: blockchain.StateCache(), indexerConfig: TestClientIndexerConfig} odr := &testOdr{sdb: sdb, ldb: ldb, triedb: blockchain.TrieDB(), indexerConfig: TestClientIndexerConfig}
relay := &testTxRelay{ relay := &testTxRelay{
send: make(chan int, 1), send: make(chan int, 1),
discard: make(chan int, 1), discard: make(chan int, 1),

View file

@ -301,7 +301,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{chainConfig, statedb, 10000000, new(event.Feed)} blockchain := &testBlockChain{chainConfig, statedb, 10000000, new(event.Feed)}
pool := legacypool.New(testTxPoolConfig, blockchain) pool := legacypool.New(testTxPoolConfig, blockchain)

View file

@ -314,7 +314,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)