Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,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.
statedb *state.CachingDB // State database to reuse between imports (contains state cache)
stateDB *stateDatabase // 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 @@ -338,19 +338,18 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
if cfg == nil {
cfg = DefaultConfig()
}

// Open trie database with provided config
// Open state database with provided config
enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
if err != nil {
return nil, err
}
triedb := triedb.NewDatabase(db, cfg.triedbConfig(enableVerkle))
stateDB := newStateDatabase(db, cfg)

// Write the supplied genesis to the database if it has not been initialized
// yet. The corresponding chain config will be returned, either from the
// provided genesis or from the locally stored configuration if the genesis
// has already been initialized.
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, cfg.Overrides)
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, stateDB.triedb(enableVerkle), genesis, cfg.Overrides)
if err != nil {
return nil, err
}
Expand All @@ -366,7 +365,8 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
chainConfig: chainConfig,
cfg: cfg,
db: db,
triedb: triedb,
stateDB: stateDB,
triedb: stateDB.triedb(false), // TODO(rjl493456442) support verkle
triegc: prque.New[int64, common.Hash](nil),
chainmu: syncx.NewClosableMutex(),
bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit),
Expand All @@ -382,7 +382,6 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
return nil, err
}
bc.flushInterval.Store(int64(cfg.TrieTimeLimit))
bc.statedb = state.NewDatabase(bc.triedb, nil)
bc.validator = NewBlockValidator(chainConfig, bc)
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
bc.processor = NewStateProcessor(chainConfig, bc.hc)
Expand Down Expand Up @@ -548,9 +547,7 @@ func (bc *BlockChain) setupSnapshot() {
AsyncBuild: !bc.cfg.SnapshotWait,
}
bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root)

// Re-initialize the state database with snapshot
bc.statedb = state.NewDatabase(bc.triedb, bc.snaps)
bc.stateDB.setSnapshot(bc.snaps)
}
}

Expand Down Expand Up @@ -941,7 +938,7 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*typ
// then block number zero is returned, indicating that snapshot recovery is disabled
// and the whole snapshot should be auto-generated in case of head mismatch.
func (bc *BlockChain) rewindHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
if bc.triedb.Scheme() == rawdb.PathScheme {
if bc.cfg.StateScheme == rawdb.PathScheme {
return bc.rewindPathHead(head, root)
}
return bc.rewindHashHead(head, root)
Expand Down Expand Up @@ -1097,7 +1094,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
}
// Reset the trie database with the fresh snap synced state.
root := block.Root()
if bc.triedb.Scheme() == rawdb.PathScheme {
if bc.cfg.StateScheme == rawdb.PathScheme {
if err := bc.triedb.Enable(root); err != nil {
return err
}
Expand Down Expand Up @@ -1269,7 +1266,7 @@ func (bc *BlockChain) Stop() {
}
bc.snaps.Release()
}
if bc.triedb.Scheme() == rawdb.PathScheme {
if bc.cfg.StateScheme == rawdb.PathScheme {
// Ensure that the in-memory trie nodes are journaled to disk properly.
if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil {
log.Info("Failed to journal in-memory trie nodes", "err", err)
Expand Down Expand Up @@ -1312,8 +1309,8 @@ func (bc *BlockChain) Stop() {
bc.logger.OnClose()
}
// Close the trie database, release all the held resources as the last step.
if err := bc.triedb.Close(); err != nil {
log.Error("Failed to close trie database", "err", err)
if err := bc.stateDB.close(); err != nil {
log.Error("Failed to close state database", "err", err)
}
log.Info("Blockchain stopped")
}
Expand Down Expand Up @@ -1586,7 +1583,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
}
// If node is running in path mode, skip explicit gc operation
// which is unnecessary in this mode.
if bc.triedb.Scheme() == rawdb.PathScheme {
if bc.cfg.StateScheme == rawdb.PathScheme {
return nil
}
// If we're running an archive node, always flush
Expand Down Expand Up @@ -1956,7 +1953,8 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
defer interrupt.Store(true) // terminate the prefetch at the end

if bc.cfg.NoPrefetch {
statedb, err = state.New(parentRoot, bc.statedb)
sdb := bc.stateDB.stateDB(bc.chainConfig.IsVerkle(block.Number(), block.Time()))
statedb, err = state.New(parentRoot, sdb)
if err != nil {
return nil, err
}
Expand All @@ -1966,15 +1964,16 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
//
// Note: the main processor and prefetcher share the same reader with a local
// cache for mitigating the overhead of state access.
prefetch, process, err := bc.statedb.ReadersWithCacheStats(parentRoot)
sdb := bc.stateDB.stateDB(bc.chainConfig.IsVerkle(block.Number(), block.Time()))
prefetch, process, err := sdb.ReadersWithCacheStats(parentRoot)
if err != nil {
return nil, err
}
throwaway, err := state.NewWithReader(parentRoot, bc.statedb, prefetch)
throwaway, err := state.NewWithReader(parentRoot, sdb, prefetch)
if err != nil {
return nil, err
}
statedb, err = state.NewWithReader(parentRoot, bc.statedb, process)
statedb, err = state.NewWithReader(parentRoot, sdb, process)
if err != nil {
return nil, err
}
Expand Down
13 changes: 7 additions & 6 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,7 @@ func (bc *BlockChain) TxIndexDone() bool {

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

// HasBlockAndState checks if a block and associated state trie is fully present
Expand All @@ -345,7 +344,7 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
// state is not treated as recoverable if it's available, thus
// false will be returned in this case.
func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
if bc.triedb.Scheme() == rawdb.HashScheme {
if bc.cfg.StateScheme == rawdb.HashScheme {
return false
}
result, _ := bc.triedb.Recoverable(root)
Expand All @@ -357,7 +356,7 @@ func (bc *BlockChain) stateRecoverable(root common.Hash) bool {
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) []byte {
// TODO(rjl493456442) The associated account address is also required
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
return bc.statedb.ContractCodeWithPrefix(common.Address{}, hash)
return bc.stateDB.contractCode(common.Address{}, hash)
}

// State returns a new mutable state based on the current HEAD block.
Expand All @@ -367,7 +366,8 @@ 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.statedb)
// TODO(rjl493456442) support verkle state accessing
return state.New(root, bc.stateDB.stateDB(false))
}

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

// StateCache returns the caching database underpinning the blockchain instance.
func (bc *BlockChain) StateCache() state.Database {
return bc.statedb
// TODO(rjl493456442) support verkle database
return bc.stateDB.stateDB(false)
}

// GasLimit returns the gas limit of the current HEAD block.
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_repair_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1845,7 +1845,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
rawdb.WriteLastPivotNumber(db, *tt.pivotBlock)
}
// Pull the plug on the database, simulating a hard crash
chain.triedb.Close()
chain.stateDB.close()
db.Close()
chain.stopWithoutSaving()

Expand Down Expand Up @@ -1971,7 +1971,7 @@ func testIssue23496(t *testing.T, scheme string) {
}

// Pull the plug on the database, simulating a hard crash
chain.triedb.Close()
chain.stateDB.close()
db.Close()
chain.stopWithoutSaving()

Expand Down
6 changes: 2 additions & 4 deletions core/blockchain_sethead_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"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/ethdb/pebble"
"github.com/ethereum/go-ethereum/params"
Expand Down Expand Up @@ -2033,15 +2032,14 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
t.Fatalf("Failed to import canonical chain tail: %v", err)
}
// Reopen the trie database without persisting in-memory dirty nodes.
chain.triedb.Close()
chain.stateDB.close()
dbconfig := &triedb.Config{}
if scheme == rawdb.PathScheme {
dbconfig.PathDB = pathdb.Defaults
} else {
dbconfig.HashDB = hashdb.Defaults
}
chain.triedb = triedb.NewDatabase(chain.db, dbconfig)
chain.statedb = state.NewDatabase(chain.triedb, chain.snaps)
chain.stateDB = newStateDatabase(chain.db, chain.cfg)

// Force run a freeze cycle
type freezer interface {
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
db := chain.db
db.Close()
chain.stopWithoutSaving()
chain.triedb.Close()
chain.stateDB.close()

// Start a new blockchain back up and see where the repair leads us
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false)
Expand Down Expand Up @@ -416,7 +416,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
}

// Simulate the blockchain crash.
tmp.triedb.Close()
tmp.stateDB.close()
tmp.stopWithoutSaving()

newchain, err = NewBlockChain(snaptest.db, snaptest.gspec, snaptest.engine, DefaultConfig().WithStateScheme(snaptest.scheme))
Expand Down
3 changes: 2 additions & 1 deletion core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
}
return err
}
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.statedb)
sdb := blockchain.stateDB.stateDB(false)
statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), sdb)
if err != nil {
return err
}
Expand Down
47 changes: 22 additions & 25 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ import (
)

const (
// Number of codehash->size associations to keep.
codeSizeCacheSize = 1_000_000 // 4 megabytes in total
// CodeSizeCacheSize is the number of codehash->size associations to keep.
CodeSizeCacheSize = 1_000_000 // 4 megabytes in total

// Cache size granted for caching clean code.
codeCacheSize = 256 * 1024 * 1024
// CodeCacheSize is the cache size granted for caching clean code.
CodeCacheSize = 256 * 1024 * 1024

// Number of address->curve point associations to keep.
pointCacheSize = 4096
// PointCacheSize is the number of address->curve point associations to keep.
PointCacheSize = 4096
)

// Database wraps access to tries and contract code.
Expand Down Expand Up @@ -159,9 +159,22 @@ func NewDatabase(triedb *triedb.Database, snap *snapshot.Tree) *CachingDB {
disk: triedb.Disk(),
triedb: triedb,
snap: snap,
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
pointCache: utils.NewPointCache(pointCacheSize),
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](CodeCacheSize),
codeSizeCache: lru.NewCache[common.Hash, int](CodeSizeCacheSize),
pointCache: utils.NewPointCache(PointCacheSize),
}
}

// NewDatabaseWithCache creates a state database with the provided database
// and relative caches.
func NewDatabaseWithCache(disk ethdb.KeyValueStore, triedb *triedb.Database, snap *snapshot.Tree, codeCache *lru.SizeConstrainedCache[common.Hash, []byte], codeSizeCache *lru.Cache[common.Hash, int], pointCache *utils.PointCache) *CachingDB {
return &CachingDB{
disk: disk,
snap: snap,
triedb: triedb,
codeCache: codeCache,
codeSizeCache: codeSizeCache,
pointCache: pointCache,
}
}

Expand Down Expand Up @@ -248,22 +261,6 @@ func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
return tr, nil
}

// ContractCodeWithPrefix 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 *CachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) []byte {
code, _ := db.codeCache.Get(codeHash)
if len(code) > 0 {
return code
}
code = rawdb.ReadCodeWithPrefix(db.disk, codeHash)
if len(code) > 0 {
db.codeCache.Add(codeHash, code)
db.codeSizeCache.Add(codeHash, len(code))
}
return code
}

// TrieDB retrieves any intermediate trie-node caching layer.
func (db *CachingDB) TrieDB() *triedb.Database {
return db.triedb
Expand Down
Loading