diff --git a/core/blockchain.go b/core/blockchain.go index d49bd5f937..5349ea8866 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -230,6 +230,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par if cacheConfig == nil { cacheConfig = DefaultCacheConfig } + if cacheConfig.TriesInMemory <= 0 { + cacheConfig.TriesInMemory = 128 + } bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) @@ -830,7 +833,7 @@ func (bc *BlockChain) Stop() { if !bc.cacheConfig.TrieDirtyDisabled { triedb := bc.stateCache.TrieDB() - for _, offset := range []uint64{0, 1, DefaultCacheConfig.TriesInMemory - 1} { + for _, offset := range []uint64{0, 1, bc.cacheConfig.TriesInMemory - 1} { if number := bc.CurrentBlock().NumberU64(); number > offset { recent := bc.GetBlockByNumber(number - offset) @@ -1298,7 +1301,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive bc.triegc.Push(root, -int64(block.NumberU64())) - if current := block.NumberU64(); current > DefaultCacheConfig.TriesInMemory { + if current := block.NumberU64(); current > bc.cacheConfig.TriesInMemory { // If we exceeded our memory allowance, flush matured singleton nodes to disk var ( nodes, imgs = triedb.Size() @@ -1308,7 +1311,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. triedb.Cap(limit - ethdb.IdealBatchSize) } // Find the next state trie we need to commit - chosen := current - DefaultCacheConfig.TriesInMemory + chosen := current - bc.cacheConfig.TriesInMemory // If we exceeded out time allowance, flush an entire trie to disk if bc.gcproc > bc.cacheConfig.TrieTimeLimit { @@ -1320,8 +1323,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. } else { // If we're exceeding limits but haven't reached a large enough memory gap, // warn the user that the system is becoming unstable. - if chosen < lastWrite+DefaultCacheConfig.TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit { - log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", DefaultCacheConfig.TriesInMemory, "optimum", float64(chosen-lastWrite)/float64((DefaultCacheConfig.TriesInMemory))) + if chosen < lastWrite+bc.cacheConfig.TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit { + log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TriesInMemory, "optimum", float64(chosen-lastWrite)/float64((bc.cacheConfig.TriesInMemory))) } // Flush an entire trie and restart the counters triedb.Commit(header.Root, true, nil) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index d44d563b20..fa6b61225e 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -1681,7 +1681,7 @@ func TestTrieForkGC(t *testing.T) { } } // Dereference all the recent tries and ensure no past trie is left in - for i := 0; i < int(DefaultCacheConfig.TriesInMemory); i++ { + for i := 0; i < int(chain.cacheConfig.TriesInMemory); i++ { chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) } @@ -1737,7 +1737,7 @@ func TestLargeReorgTrieGC(t *testing.T) { t.Fatalf("failed to finalize competitor chain: %v", err) } - for i, block := range competitor[:len(competitor)-int(DefaultCacheConfig.TriesInMemory)] { + for i, block := range competitor[:len(competitor)-int(chain.cacheConfig.TriesInMemory)] { if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { t.Fatalf("competitor %d: competing chain state missing", i) } @@ -1993,9 +1993,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon t.Fatalf("block %d: failed to insert into chain: %v", n, err) } - lastPrunedIndex := len(blocks) - int(DefaultCacheConfig.TriesInMemory) - 1 + lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1 lastPrunedBlock := blocks[lastPrunedIndex] - firstNonPrunedBlock := blocks[len(blocks)-int(DefaultCacheConfig.TriesInMemory)] + firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)] // Verify pruning of lastPrunedBlock if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { @@ -2866,7 +2866,7 @@ func TestSideImportPrunedBlocks(t *testing.T) { t.Fatalf("block %d: failed to insert into chain: %v", n, err) } - lastPrunedIndex := len(blocks) - int(DefaultCacheConfig.TriesInMemory) - 1 + lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1 lastPrunedBlock := blocks[lastPrunedIndex] // Verify pruning of lastPrunedBlock @@ -2874,7 +2874,7 @@ func TestSideImportPrunedBlocks(t *testing.T) { t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) } - firstNonPrunedBlock := blocks[len(blocks)-int(DefaultCacheConfig.TriesInMemory)] + firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)] // Verify firstNonPrunedBlock is not pruned if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) diff --git a/core/tests/blockchain_sethead_test.go b/core/tests/blockchain_sethead_test.go index ad6e78697d..6160dfb48f 100644 --- a/core/tests/blockchain_sethead_test.go +++ b/core/tests/blockchain_sethead_test.go @@ -2082,6 +2082,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { // verifyNoGaps checks that there are no gaps after the initial set of blocks in // the database and errors if found. +// //nolint:gocognit func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) { t.Helper() @@ -2135,6 +2136,7 @@ func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted // verifyCutoff checks that there are no chain data available in the chain after // the specified limit, but that it is available before. +// //nolint:gocognit func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) { t.Helper() diff --git a/eth/backend.go b/eth/backend.go index cc65d9837f..824fec8914 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -218,6 +218,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { TrieTimeLimit: config.TrieTimeout, SnapshotLimit: config.SnapshotCache, Preimages: config.Preimages, + TriesInMemory: config.TriesInMemory, } ) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index adb36ffadd..c9272758ab 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -176,6 +176,7 @@ type Config struct { TrieTimeout time.Duration SnapshotCache int Preimages bool + TriesInMemory uint64 // Mining options Miner miner.Config