Skip to content
Merged
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
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ var (
utils.CacheGCFlag,
utils.CacheSnapshotFlag,
// utils.CacheNoPrefetchFlag,
utils.CacheEnableSharedStorageFlag,
utils.CachePreimagesFlag,
utils.MultiDataBaseFlag,
utils.PruneAncientDataFlag, // deprecated
Expand Down
12 changes: 12 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,12 @@ var (
Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
Category: flags.PerfCategory,
}
CacheEnableSharedStorageFlag = &cli.BoolFlag{
Name: "cache.enablesharedpool",
Usage: "Enable shared storage pool cache in statedb, default is false",
Value: false,
Category: flags.PerfCategory,
}
CachePreimagesFlag = &cli.BoolFlag{
Name: "cache.preimages",
Usage: "Enable recording the SHA3/keccak preimages of trie keys",
Expand Down Expand Up @@ -2130,6 +2136,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
}
if ctx.IsSet(CacheEnableSharedStorageFlag.Name) {
cfg.EnableSharedStorage = true
log.Info("Enabled shared storage pool cache")
} else {
log.Info("Disabled shared storage pool cache")
}
if ctx.IsSet(CacheLogSizeFlag.Name) {
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
}
Expand Down
3 changes: 3 additions & 0 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ const (
// CacheConfig contains the configuration values for the trie database
// and state snapshot these are resident in a blockchain.
type CacheConfig struct {
EnableSharedStorage bool // Whether to enable shared storage in statedb, improve execute stage performance ~6%.
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
Expand Down Expand Up @@ -2185,6 +2186,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
if err != nil {
return nil, it.index, err
}
statedb.EnableSharedStorage(bc.cacheConfig.EnableSharedStorage)
statedb.SetNeedBadSharedStorage(bc.chainConfig.NeedBadSharedStorage(block.Number()))
bc.updateHighestVerifiedHeader(block.Header())

// If we are past Byzantium, enable prefetching to pull in trie node paths
Expand Down
3 changes: 2 additions & 1 deletion core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,11 @@ 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) {
stateDb, err := state.New(root, bc.statedb)
stateDb, err := state.NewWithSharedPool(root, bc.statedb)
if err != nil {
return nil, err
}
stateDb.EnableSharedStorage(bc.cacheConfig.EnableSharedStorage)

// If there's no trie and the specified snapshot is not available, getting
// any state will by default return nil.
Expand Down
23 changes: 17 additions & 6 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,14 @@ func (s *stateObject) getPrefetchedTrie() Trie {
return s.db.prefetcher.trie(s.addrHash, s.data.Root)
}

func (s *stateObject) getOriginStorage(key common.Hash) (common.Hash, bool) {
if value, cached := s.originStorage[key]; cached {
return value, true
}
func (s *stateObject) tryGetFromSharedPool(key common.Hash) (common.Hash, bool) {
// if L1 cache miss, try to get it from shared pool
if s.sharedOriginStorage != nil {
val, ok := s.sharedOriginStorage.Load(key)
if !ok {
return common.Hash{}, false
}
storage := val.(common.Hash)
s.originStorage[key] = storage
return storage, true
}
return common.Hash{}, false
Expand Down Expand Up @@ -211,9 +207,18 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
return value
}

if value, cached := s.getOriginStorage(key); cached {
if value, cached := s.originStorage[key]; cached {
return value
}

if s.db.needBadSharedStorage {
// keep compatible with old erroneous data(https://forum.bnbchain.org/t/about-the-hertzfix/2400).
if value, cached := s.tryGetFromSharedPool(key); cached {
s.originStorage[key] = value
return value
}
}

// If the object was destructed in *this* block (and potentially resurrected),
// the storage has been cleared out, and we should *not* consult the previous
// database about any storage values. The only possible alternatives are:
Expand All @@ -224,6 +229,12 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
s.originStorage[key] = common.Hash{} // track the empty slot as origin value
return common.Hash{}
}

if value, cached := s.tryGetFromSharedPool(key); cached {
s.originStorage[key] = value
return value
}

s.db.StorageLoaded++

var start time.Time
Expand Down
32 changes: 22 additions & 10 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ type StateDB struct {
// perspective. This map is populated at the transaction boundaries.
mutations map[common.Address]*mutation

storagePool *StoragePool // sharedPool to store L1 originStorage of stateObjects
// if needBadSharedStorage = true, try read from sharedPool firstly, compatible with old erroneous data(https://forum.bnbchain.org/t/about-the-hertzfix/2400).
// else read from sharedPool which is not in stateObjectsDestruct.
needBadSharedStorage bool
writeOnSharedStorage bool // Write to the shared origin storage of a stateObject while reading from the underlying storage layer.
storagePool *StoragePool // sharedPool to store L1 originStorage of stateObjects

// DB error.
// State objects are used by the consensus core and VM which are
// unable to deal with database-level errors. Any error that occurs
Expand Down Expand Up @@ -212,8 +216,15 @@ func New(root common.Hash, db Database) (*StateDB, error) {
return sdb, nil
}

func (s *StateDB) EnableWriteOnSharedStorage() {
s.writeOnSharedStorage = true
func (s *StateDB) EnableSharedStorage(enableSharedStorage bool) {
s.writeOnSharedStorage = enableSharedStorage
}

func (s *StateDB) SetNeedBadSharedStorage(needBadSharedStorage bool) {
s.needBadSharedStorage = needBadSharedStorage
if needBadSharedStorage {
s.writeOnSharedStorage = true
}
}

// In mining mode, we will try multi-fillTransactions to get the most profitable one.
Expand Down Expand Up @@ -792,14 +803,15 @@ func (s *StateDB) copyInternal(doPrefetch bool) *StateDB {
stateObjectsDestruct: make(map[common.Address]*stateObject, len(s.stateObjectsDestruct)),
mutations: make(map[common.Address]*mutation, len(s.mutations)),
dbErr: s.dbErr,
needBadSharedStorage: s.needBadSharedStorage,
writeOnSharedStorage: s.writeOnSharedStorage,
storagePool: s.storagePool,
// writeOnSharedStorage: s.writeOnSharedStorage,
refund: s.refund,
thash: s.thash,
txIndex: s.txIndex,
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
logSize: s.logSize,
preimages: maps.Clone(s.preimages),
refund: s.refund,
thash: s.thash,
txIndex: s.txIndex,
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
logSize: s.logSize,
preimages: maps.Clone(s.preimages),

transientStorage: s.transientStorage.Copy(),
journal: s.journal.copy(),
Expand Down
4 changes: 0 additions & 4 deletions core/state_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ func (p *statePrefetcher) Prefetch(transactions types.Transactions, header *type
for i := 0; i < prefetchThread; i++ {
go func() {
newStatedb := statedb.CopyDoPrefetch()
if p.config.NeedBadSharedStorage(header.Number) {
newStatedb.EnableWriteOnSharedStorage()
}

gaspool := new(GasPool).AddGas(gasLimit)
evm := vm.NewEVM(NewEVMBlockContext(header, p.chain, nil), newStatedb, p.config, *cfg)
// Iterate over and process the individual transactions
Expand Down
1 change: 1 addition & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
EnablePreimageRecording: config.EnablePreimageRecording,
}
cacheConfig = &core.CacheConfig{
EnableSharedStorage: config.EnableSharedStorage,
TrieCleanLimit: config.TrieCleanCache,
TrieCleanNoPrefetch: config.NoPrefetch,
TrieDirtyLimit: config.TrieDirtyCache,
Expand Down
60 changes: 31 additions & 29 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,29 @@ var FullNodeGPO = gasprice.Config{

// Defaults contains default settings for use on the BSC main net.
var Defaults = Config{
SyncMode: SnapSync,
NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
BlockHistory: 0,
StateHistory: params.FullImmutabilityThreshold,
DatabaseCache: 512,
TrieCleanCache: 154,
TrieDirtyCache: 256,
TrieTimeout: 10 * time.Minute,
TriesInMemory: 128,
TriesVerifyMode: core.LocalVerify,
SnapshotCache: 102,
FilterLogCacheSize: 32,
Miner: minerconfig.DefaultConfig,
TxPool: legacypool.DefaultConfig,
BlobPool: blobpool.DefaultConfig,
RPCGasCap: 50000000,
RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO,
RPCTxFeeCap: 1, // 1 ether
BlobExtraReserve: params.DefaultExtraReserveForBlobRequests, // Extra reserve threshold for blob, blob never expires when -1 is set, default 28800
SyncMode: SnapSync,
NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
BlockHistory: 0,
StateHistory: params.FullImmutabilityThreshold,
DatabaseCache: 512,
EnableSharedStorage: false,
TrieCleanCache: 154,
TrieDirtyCache: 256,
TrieTimeout: 10 * time.Minute,
TriesInMemory: 128,
TriesVerifyMode: core.LocalVerify,
SnapshotCache: 102,
FilterLogCacheSize: 32,
Miner: minerconfig.DefaultConfig,
TxPool: legacypool.DefaultConfig,
BlobPool: blobpool.DefaultConfig,
RPCGasCap: 50000000,
RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO,
RPCTxFeeCap: 1, // 1 ether
BlobExtraReserve: params.DefaultExtraReserveForBlobRequests, // Extra reserve threshold for blob, blob never expires when -1 is set, default 28800
}

//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
Expand Down Expand Up @@ -145,13 +146,14 @@ type Config struct {
// !!Deprecated: use 'BlockHistory' instead.
PruneAncientData bool

TrieCleanCache int
TrieDirtyCache int
TrieTimeout time.Duration
SnapshotCache int
TriesInMemory uint64
TriesVerifyMode core.VerifyMode
Preimages bool
EnableSharedStorage bool
TrieCleanCache int
TrieDirtyCache int
TrieTimeout time.Duration
SnapshotCache int
TriesInMemory uint64
TriesVerifyMode core.VerifyMode
Preimages bool

// This is the number of blocks for which logs will be cached in the filter system.
FilterLogCacheSize int
Expand Down
2 changes: 1 addition & 1 deletion params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ func (c *ChainConfig) IsHertzfix(num *big.Int) bool {
}

func (c *ChainConfig) NeedBadSharedStorage(num *big.Int) bool {
if c.IsHertzfix(num) {
if c.IsHertzfix(num) || c.ChainID == nil {
return false
}

Expand Down