From 0fb0afe8a38daf13880e8d3c0fc43b4edc74c80e Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Thu, 22 Dec 2022 23:04:18 +0300 Subject: [PATCH] add coinbase config cache (#416) * add coinbase config cache * revert formatting --- core/blockchain.go | 63 +++++++++++++++++++++++---------------- core/blockchain_reader.go | 12 ++++++++ 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 8f20865fc1..226e32a96e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -95,13 +95,14 @@ var ( ) const ( - bodyCacheLimit = 256 - blockCacheLimit = 256 - receiptsCacheLimit = 32 - txLookupCacheLimit = 1024 - feeConfigCacheLimit = 256 - badBlockLimit = 10 - TriesInMemory = 128 + bodyCacheLimit = 256 + blockCacheLimit = 256 + receiptsCacheLimit = 32 + txLookupCacheLimit = 1024 + feeConfigCacheLimit = 256 + coinbaseConfigCacheLimit = 256 + badBlockLimit = 10 + TriesInMemory = 128 // BlockChainVersion ensures that an incompatible database forces a resync from scratch. // @@ -144,6 +145,13 @@ type cacheableFeeConfig struct { lastChangedAt *big.Int } +// cacheableCoinbaseConfig encapsulates coinbase address itself and allowFeeRecipient flag, +// in order to cache them together. +type cacheableCoinbaseConfig struct { + coinbaseAddress common.Address + allowFeeRecipients bool +} + // CacheConfig contains the configuration values for the trie caching/pruning // that's resident in a blockchain. type CacheConfig struct { @@ -219,13 +227,14 @@ type BlockChain struct { currentBlock atomic.Value // Current head of the block chain - stateCache state.Database // State database to reuse between imports (contains state cache) - stateManager TrieWriter - bodyCache *lru.Cache // Cache for the most recent block bodies - receiptsCache *lru.Cache // Cache for the most recent receipts per block - blockCache *lru.Cache // Cache for the most recent entire blocks - txLookupCache *lru.Cache // Cache for the most recent transaction lookup data. - feeConfigCache *lru.Cache // Cache for the most recent feeConfig lookup data. + stateCache state.Database // State database to reuse between imports (contains state cache) + stateManager TrieWriter + bodyCache *lru.Cache // Cache for the most recent block bodies + receiptsCache *lru.Cache // Cache for the most recent receipts per block + blockCache *lru.Cache // Cache for the most recent entire blocks + txLookupCache *lru.Cache // Cache for the most recent transaction lookup data. + feeConfigCache *lru.Cache // Cache for the most recent feeConfig lookup data. + coinbaseConfigCache *lru.Cache // Cache for the most recent coinbaseConfig lookup data. running int32 // 0 if chain is running, 1 when stopped @@ -298,6 +307,7 @@ func NewBlockChain( blockCache, _ := lru.New(blockCacheLimit) txLookupCache, _ := lru.New(txLookupCacheLimit) feeConfigCache, _ := lru.New(feeConfigCacheLimit) + coinbaseConfigCache, _ := lru.New(coinbaseConfigCacheLimit) badBlocks, _ := lru.New(badBlockLimit) bc := &BlockChain{ @@ -310,18 +320,19 @@ func NewBlockChain( Preimages: cacheConfig.Preimages, StatsPrefix: trieCleanCacheStatsNamespace, }), - bodyCache: bodyCache, - receiptsCache: receiptsCache, - blockCache: blockCache, - txLookupCache: txLookupCache, - feeConfigCache: feeConfigCache, - engine: engine, - vmConfig: vmConfig, - badBlocks: badBlocks, - senderCacher: newTxSenderCacher(runtime.NumCPU()), - acceptorQueue: make(chan *types.Block, cacheConfig.AcceptorQueueLimit), - quit: make(chan struct{}), - acceptedLogsCache: NewFIFOCache[common.Hash, [][]*types.Log](cacheConfig.AcceptedCacheSize), + bodyCache: bodyCache, + receiptsCache: receiptsCache, + blockCache: blockCache, + txLookupCache: txLookupCache, + feeConfigCache: feeConfigCache, + coinbaseConfigCache: coinbaseConfigCache, + engine: engine, + vmConfig: vmConfig, + badBlocks: badBlocks, + senderCacher: newTxSenderCacher(runtime.NumCPU()), + acceptorQueue: make(chan *types.Block, cacheConfig.AcceptorQueueLimit), + quit: make(chan struct{}), + acceptedLogsCache: NewFIFOCache[common.Hash, [][]*types.Log](cacheConfig.AcceptedCacheSize), } bc.validator = NewBlockValidator(chainConfig, bc, engine) bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index fd090e776f..f30a7fe553 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -400,11 +400,23 @@ func (bc *BlockChain) GetCoinbaseAt(parent *types.Header) (common.Address, bool, } } + // try to return it from the cache + if cached, hit := bc.coinbaseConfigCache.Get(parent.Root); hit { + cachedCoinbaseConfig, ok := cached.(*cacheableCoinbaseConfig) + if !ok { + return common.Address{}, false, fmt.Errorf("expected type cachedCoinbaseConfig, got %T", cached) + } + return cachedCoinbaseConfig.coinbaseAddress, cachedCoinbaseConfig.allowFeeRecipients, nil + } + stateDB, err := bc.StateAt(parent.Root) if err != nil { return common.Address{}, false, err } rewardAddress, feeRecipients := precompile.GetStoredRewardAddress(stateDB) + + cacheable := &cacheableCoinbaseConfig{coinbaseAddress: rewardAddress, allowFeeRecipients: feeRecipients} + bc.coinbaseConfigCache.Add(parent.Root, cacheable) return rewardAddress, feeRecipients, nil }