Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FILL_COST on top of Gary's new state reader #12

Open
wants to merge 10 commits into
base: state-reader-3
Choose a base branch
from
9 changes: 5 additions & 4 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}
// Re-create statedb instance with new root upon the updated database
// for accessing latest states.
statedb, err = state.New(root, statedb.Database(), nil)
statedb, err = state.New(root, statedb.Database())
if err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
}
Expand All @@ -381,8 +381,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}

func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true})
statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
sdb := state.NewDatabase(db, tdb, nil)
statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
Expand All @@ -393,7 +394,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
}
// Commit and re-open to start with a clean state.
root, _ := statedb.Commit(0, false)
statedb, _ = state.New(root, sdb, nil)
statedb, _ = state.New(root, sdb)
return statedb
}

Expand Down
6 changes: 3 additions & 3 deletions cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ func runCmd(ctx *cli.Context) error {
})
defer triedb.Close()
genesis := genesisConfig.MustCommit(db, triedb)
sdb := state.NewDatabaseWithNodeDB(db, triedb)
statedb, _ = state.New(genesis.Root(), sdb, nil)
sdb := state.NewDatabase(db, triedb, nil)
statedb, _ = state.New(genesis.Root(), sdb)
chainConfig = genesisConfig.Config

if ctx.String(SenderFlag.Name) != "" {
Expand Down Expand Up @@ -277,7 +277,7 @@ func runCmd(ctx *cli.Context) error {
fmt.Printf("Failed to commit changes %v\n", err)
return err
}
dumpdb, err := state.New(root, sdb, nil)
dumpdb, err := state.New(root, sdb)
if err != nil {
fmt.Printf("Failed to open statedb %v\n", err)
return err
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/staterunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func runStateTest(fname string, cfg vm.Config, dump bool) error {
result.Root = &root
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
if dump { // Dump any state to aid debugging
cpy, _ := state.New(root, tstate.StateDB.Database(), nil)
cpy, _ := state.New(root, tstate.StateDB.Database())
dump := cpy.RawDump(nil)
result.State = &dump
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func dump(ctx *cli.Context) error {
triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
defer triedb.Close()

state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil)
state, err := state.New(root, state.NewDatabase(db, triedb, nil))
if err != nil {
return err
}
Expand Down
46 changes: 22 additions & 24 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,8 @@ var (
storageUpdateTimer = metrics.NewRegisteredResettingTimer("chain/storage/updates", nil)
storageCommitTimer = metrics.NewRegisteredResettingTimer("chain/storage/commits", nil)

snapshotAccountReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/account/reads", nil)
snapshotStorageReadTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/storage/reads", nil)
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)

triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)

blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
Expand Down Expand Up @@ -217,7 +214,7 @@ type BlockChain struct {
lastWrite uint64 // Last block when the state was flushed
flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state
triedb *triedb.Database // The database handler for maintaining trie nodes.
stateCache state.Database // State database to reuse between imports (contains state cache)
stateDb *state.CachingDB // State database to reuse between imports (contains state cache)
txIndexer *txIndexer // Transaction indexer, might be nil if not enabled

hc *HeaderChain
Expand Down Expand Up @@ -310,7 +307,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
bc.forker = NewForkChoice(bc, shouldPreserve)
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
bc.stateDb = state.NewDatabase(bc.db, bc.triedb, nil)
bc.validator = NewBlockValidator(chainConfig, bc)
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
bc.processor = NewStateProcessor(chainConfig, bc.hc)
Expand Down Expand Up @@ -448,7 +445,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
AsyncBuild: !bc.cacheConfig.SnapshotWait,
}
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)

// Re-initialize the state database with snapshot
bc.stateDb = state.NewDatabase(bc.db, bc.triedb, bc.snaps)
}

// Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
Expand Down Expand Up @@ -1800,7 +1801,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
if parent == nil {
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
}
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
statedb, err := state.New(parent.Root, bc.stateDb)
if err != nil {
return it.index, err
}
Expand All @@ -1826,7 +1827,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
var followupInterrupt atomic.Bool
if !bc.cacheConfig.TrieCleanNoPrefetch {
if followup, err := it.peek(); followup != nil && err == nil {
throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps)
throwaway, _ := state.New(parent.Root, bc.stateDb)

go func(start time.Time, followup *types.Block, throwaway *state.StateDB) {
// Disable tracing for prefetcher executions.
Expand Down Expand Up @@ -1946,21 +1947,6 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
}
proctime := time.Since(start) // processing + validation

// Update the metrics touched during block processing and validation
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing)
snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing)
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
triehash := statedb.AccountHashes // The time spent on tries hashing
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
trieRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read
trieRead += statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read
blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation

// Write the block to the chain and get the status.
var (
wstart = time.Now()
Expand All @@ -1975,6 +1961,18 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
if err != nil {
return nil, err
}
// Update the metrics touched during block processing and validation
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
triehash := statedb.AccountHashes // The time spent on account trie hashing
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on account trie update + storage tries update and hashing
trieRead := statedb.AccountReads + statedb.StorageReads // The time spent on account read and storage read
blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation

// Update the metrics touched during block commit
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
Expand Down
11 changes: 4 additions & 7 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {

// HasState checks if state trie is fully present in the database or not.
func (bc *BlockChain) HasState(hash common.Hash) bool {
_, err := bc.stateCache.OpenTrie(hash)
_, err := bc.stateDb.OpenTrie(hash)
return err == nil
}

Expand Down Expand Up @@ -341,12 +341,9 @@ func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
// If the code doesn't exist in the in-memory cache, check the storage with
// new code scheme.
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
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash)
return bc.stateDb.ContractCodeWithPrefix(common.Address{}, hash)
}

// State returns a new mutable state based on the current HEAD block.
Expand All @@ -356,7 +353,7 @@ func (bc *BlockChain) State() (*state.StateDB, error) {

// StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
return state.New(root, bc.stateCache, bc.snaps)
return state.New(root, bc.stateDb)
}

// Config retrieves the chain's fork configuration.
Expand All @@ -382,7 +379,7 @@ func (bc *BlockChain) Processor() Processor {

// StateCache returns the caching database underpinning the blockchain instance.
func (bc *BlockChain) StateCache() state.Database {
return bc.stateCache
return bc.stateDb
}

// GasLimit returns the gas limit of the current HEAD block.
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_sethead_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
dbconfig.HashDB = hashdb.Defaults
}
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb)
chain.stateDb = state.NewDatabase(chain.db, chain.triedb, chain.snaps)

// Force run a freeze cycle
type freezer interface {
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
}
return err
}
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil)
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateDb)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
defer triedb.Close()

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(db, triedb, nil))
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -475,7 +475,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
}

for i := 0; i < n; i++ {
statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, trdb), nil)
statedb, err := state.New(parent.Root(), state.NewDatabase(db, trdb, nil))
if err != nil {
panic(err)
}
Expand Down
6 changes: 3 additions & 3 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
}
// Create an ephemeral in-memory database for computing hash,
// all the derived states will be discarded to not pollute disk.
db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config)
statedb, err := state.New(types.EmptyRootHash, db, nil)
db := rawdb.NewMemoryDatabase()
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(db, triedb.NewDatabase(db, config), nil))
if err != nil {
return common.Hash{}, err
}
Expand All @@ -149,7 +149,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) {
// states will be persisted into the given database. Also, the genesis state
// specification will be flushed as well.
func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Database, blockhash common.Hash) error {
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil)
statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(db, triedb, nil))
if err != nil {
return err
}
Expand Down
7 changes: 7 additions & 0 deletions core/rawdb/accessors_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash commo
return data
}

// HasStorageSnapshot returns a flag indicating whether the requested storage
// slot exists.
func HasStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) bool {
exists, _ := db.Has(storageSnapshotKey(accountHash, storageHash))
return exists
}

// WriteStorageSnapshot stores the snapshot entry of a storage trie leaf.
func WriteStorageSnapshot(db ethdb.KeyValueWriter, accountHash, storageHash common.Hash, entry []byte) {
if err := db.Put(storageSnapshotKey(accountHash, storageHash), entry); err != nil {
Expand Down
Loading