diff --git a/cmd/XDC/main.go b/cmd/XDC/main.go index f710549a4949..c540970e936a 100644 --- a/cmd/XDC/main.go +++ b/cmd/XDC/main.go @@ -98,6 +98,7 @@ var ( utils.CacheDatabaseFlag, utils.CacheTrieFlag, utils.CacheGCFlag, + utils.CacheNoPrefetchFlag, //utils.TrieCacheGenFlag, utils.CacheLogSizeFlag, utils.FDLimitFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e294a7761873..3e57fac331f8 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -302,6 +302,11 @@ var ( Value: 25, Category: flags.PerfCategory, } + CacheNoPrefetchFlag = &cli.BoolFlag{ + Name: "cache.noprefetch", + Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", + Category: flags.PerfCategory, + } CacheLogSizeFlag = &cli.IntFlag{ Name: "cache-blocklogs", Aliases: []string{"cache.blocklogs"}, @@ -1474,6 +1479,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" + cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 @@ -1736,10 +1742,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (chain *core.B Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } cache := &core.CacheConfig{ - Disabled: ctx.String(GCModeFlag.Name) == "archive", - TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, - TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, - TrieTimeLimit: ethconfig.Defaults.TrieTimeout, + TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, + TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), + TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, + TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", + TrieTimeLimit: ethconfig.Defaults.TrieTimeout, } if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 diff --git a/core/blockchain.go b/core/blockchain.go index 24505670ddd8..f74b6c151354 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -81,6 +81,9 @@ var ( blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) + blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) + blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) + errInsertionInterrupted = errors.New("insertion is interrupted") errChainStopped = errors.New("blockchain is stopped") errInvalidOldChain = errors.New("invalid old chain") @@ -127,10 +130,11 @@ const ( // CacheConfig contains the configuration values for the trie caching/pruning // that's resident in a blockchain. type CacheConfig struct { - Disabled bool // Whether to disable trie write caching (archive node) - TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory - TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk - TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk + 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 + TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) + TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk } type ResultProcessBlock struct { @@ -179,8 +183,6 @@ type BlockChain struct { // Readers don't need to take it, they can just read the database. chainmu *syncx.ClosableMutex - procmu sync.RWMutex // block processor lock - currentBlock atomic.Value // Current head of the block chain currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) @@ -200,13 +202,14 @@ type BlockChain struct { wg sync.WaitGroup quit chan struct{} // shutdown signal, closed in Stop. - running int32 // 0 if chain is running, 1 when stopped - procInterrupt int32 // interrupt signaler for block processing + stopping atomic.Bool // false if chain is running, true when stopped + procInterrupt atomic.Bool // interrupt signaler for block processing - engine consensus.Engine - processor Processor // block processor interface - validator Validator // block and state validator interface - vmConfig vm.Config + engine consensus.Engine + validator Validator // Block and state validator interface + prefetcher Prefetcher // Block state prefetcher interface + processor Processor // Block transaction processor interface + vmConfig vm.Config IPCEndpoint string Client bind.ContractBackend // Global ipc client instance. @@ -260,8 +263,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par rejectedLendingItem: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit), finalizedTrade: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit), } - bc.SetValidator(NewBlockValidator(chainConfig, bc, engine)) - bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine)) + bc.validator = NewBlockValidator(chainConfig, bc, engine) + bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) + bc.processor = NewStateProcessor(chainConfig, bc, engine) var err error bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) @@ -554,31 +558,13 @@ func (bc *BlockChain) CurrentFastBlock() *types.Block { return bc.currentFastBlock.Load().(*types.Block) } -// SetProcessor sets the processor required for making state modifications. -func (bc *BlockChain) SetProcessor(processor Processor) { - bc.procmu.Lock() - defer bc.procmu.Unlock() - bc.processor = processor -} - -// SetValidator sets the validator which is used to validate incoming blocks. -func (bc *BlockChain) SetValidator(validator Validator) { - bc.procmu.Lock() - defer bc.procmu.Unlock() - bc.validator = validator -} - // Validator returns the current validator. func (bc *BlockChain) Validator() Validator { - bc.procmu.RLock() - defer bc.procmu.RUnlock() return bc.validator } // Processor returns the current processor. func (bc *BlockChain) Processor() Processor { - bc.procmu.RLock() - defer bc.procmu.RUnlock() return bc.processor } @@ -1045,7 +1031,7 @@ func (bc *BlockChain) saveData() { // - HEAD: So we don't need to reprocess any blocks in the general case // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle // - HEAD-127: So we have a hard limit on the number of blocks reexecuted - if !bc.cacheConfig.Disabled { + if !bc.cacheConfig.TrieDirtyDisabled { var tradingTriedb *trie.Database var lendingTriedb *trie.Database engine, _ := bc.Engine().(*XDPoS.XDPoS) @@ -1115,7 +1101,7 @@ func (bc *BlockChain) saveData() { // Stop stops the blockchain service. If any imports are currently in progress // it will abort them using the procInterrupt. func (bc *BlockChain) Stop() { - if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) { + if !bc.stopping.CompareAndSwap(false, true) { return } @@ -1142,12 +1128,12 @@ func (bc *BlockChain) Stop() { // errInsertionInterrupted as soon as possible. Insertion is permanently disabled after // calling this method. func (bc *BlockChain) StopInsert() { - atomic.StoreInt32(&bc.procInterrupt, 1) + bc.procInterrupt.Store(true) } // insertStopped returns true after StopInsert has been called. func (bc *BlockChain) insertStopped() bool { - return atomic.LoadInt32(&bc.procInterrupt) == 1 + return bc.procInterrupt.Load() } func (bc *BlockChain) procFutureBlocks() { @@ -1258,7 +1244,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ for i, block := range blockChain { receipts := receiptChain[i] // Short circuit insertion if shutting down or processing failed - if atomic.LoadInt32(&bc.procInterrupt) == 1 { + if bc.insertStopped() { return 0, nil } blockHash, blockNumber := block.Hash(), block.NumberU64() @@ -1426,7 +1412,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. } // If we're running an archive node, always flush - if bc.cacheConfig.Disabled { + if bc.cacheConfig.TrieDirtyDisabled { if err := triedb.Commit(root, false); err != nil { return NonStatTy, err } @@ -1666,7 +1652,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] defer close(abort) // Peek the error for the first block to decide the directing import logic - it := newInsertIterator(chain, results, bc.Validator()) + it := newInsertIterator(chain, results, bc.validator) block, err := it.next() switch { @@ -1712,7 +1698,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] // No validation errors for the first block (or chain prefix skipped) for ; block != nil && err == nil; block, err = it.next() { // If the chain is terminating, stop processing blocks - if atomic.LoadInt32(&bc.procInterrupt) == 1 { + if bc.insertStopped() { log.Debug("Premature abort during blocks processing") break } @@ -1733,12 +1719,31 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] if err != nil { return it.index, events, coalescedLogs, err } + + // If we have a followup block, run that against the current state to pre-cache + // transactions and probabilistically some of the account/storage trie nodes. + var followupInterrupt atomic.Bool + if !bc.cacheConfig.TrieCleanNoPrefetch { + if followup, err := it.peek(); followup != nil && err == nil { + go func(start time.Time) { + throwaway, _ := state.New(parent.Root, bc.stateCache) + bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) + + blockPrefetchExecuteTimer.Update(time.Since(start)) + if followupInterrupt.Load() { + blockPrefetchInterruptMeter.Mark(1) + } + }(time.Now()) + } + } + // Process block using the parent state as reference point. t0 := time.Now() isTIPXDCXReceiver := bc.Config().IsTIPXDCXReceiver(block.Number()) tradingState, lendingState, err := bc.processTradingAndLendingStates(isTIPXDCXReceiver, block, parent, statedb) if err != nil { bc.reportBlock(block, nil, err) + followupInterrupt.Store(true) return it.index, events, coalescedLogs, err } feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root, statedb) @@ -1746,10 +1751,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] t1 := time.Now() if err != nil { bc.reportBlock(block, receipts, err) + followupInterrupt.Store(true) return it.index, events, coalescedLogs, err } // Validate the state using the default validator - err = bc.Validator().ValidateState(block, statedb, receipts, usedGas) + err = bc.validator.ValidateState(block, statedb, receipts, usedGas) if err != nil { bc.reportBlock(block, receipts, err) return it.index, events, coalescedLogs, err @@ -1760,6 +1766,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, [] // Write the block to the chain and get the status. status, err := bc.writeBlockWithState(block, receipts, statedb, tradingState, lendingState) t3 := time.Now() + followupInterrupt.Store(true) if err != nil { return it.index, events, coalescedLogs, err } @@ -1948,8 +1955,8 @@ func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (i blocks, memory = blocks[:0], 0 // If the chain is terminating, stop processing blocks - if atomic.LoadInt32(&bc.procInterrupt) == 1 { - log.Debug("Premature abort during blocks processing") + if bc.insertStopped() { + log.Debug("Abort during blocks processing") return 0, nil, nil, nil } } @@ -2010,7 +2017,7 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu bc.calculatingBlock.Add(block.HashNoValidator(), calculatedBlock) // Start the parallel header verifier // If the chain is terminating, stop processing blocks - if atomic.LoadInt32(&bc.procInterrupt) == 1 { + if bc.insertStopped() { log.Debug("Premature abort during blocks processing") return nil, ErrBlacklistedHash } @@ -2021,7 +2028,7 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu } // Wait for the block's verification to complete bstart := time.Now() - err := bc.Validator().ValidateBody(block) + err := bc.validator.ValidateBody(block) switch { case err == ErrKnownBlock: // Block and state both already known. However if the current block is below @@ -2953,7 +2960,7 @@ func (bc *BlockChain) processTradingAndLendingStates(isValidBlockNumber bool, bl } for _, txMatchBatch := range txMatchBatchData { log.Debug("Verify matching transaction", "txHash", txMatchBatch.TxHash.Hex()) - err := bc.Validator().ValidateTradingOrder(statedb, tradingState, txMatchBatch, author, block.Header()) + err := bc.validator.ValidateTradingOrder(statedb, tradingState, txMatchBatch, author, block.Header()) if err != nil { return tradingState, lendingState, err } @@ -2964,7 +2971,7 @@ func (bc *BlockChain) processTradingAndLendingStates(isValidBlockNumber bool, bl } for _, batch := range batches { log.Debug("Verify matching transaction", "txHash", batch.TxHash.Hex()) - err := bc.Validator().ValidateLendingOrder(statedb, lendingState, tradingState, batch, author, block.Header()) + err := bc.validator.ValidateLendingOrder(statedb, lendingState, tradingState, batch, author, block.Header()) if err != nil { return tradingState, lendingState, err } diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index cfdbdaf28aef..a80925ab732a 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -63,7 +63,7 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor if timestamp := time.Unix(end.Time().Int64(), 0); time.Since(timestamp) > time.Minute { context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) } - context = append(context, []interface{}{"cache", cache}...) + context = append(context, []interface{}{"dirty", cache}...) if st.queued > 0 { context = append(context, []interface{}{"queued", st.queued}...) @@ -80,10 +80,13 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor // insertIterator is a helper to assist during chain import. type insertIterator struct { - chain types.Blocks - results <-chan error - index int - validator Validator + chain types.Blocks // Chain of blocks being iterated over + + results <-chan error // Verification result sink from the consensus engine + errors []error // Header verification errors for the blocks + + index int // Current offset of the iterator + validator Validator // Validator to run if verification succeeds } // newInsertIterator creates a new iterator based on the given blocks, which are @@ -92,6 +95,7 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid return &insertIterator{ chain: chain, results: results, + errors: make([]error, 0, len(chain)), index: -1, validator: validator, } @@ -100,17 +104,44 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid // next returns the next block in the iterator, along with any potential validation // error for that block. When the end is reached, it will return (nil, nil). func (it *insertIterator) next() (*types.Block, error) { + // If we reached the end of the chain, abort if it.index+1 >= len(it.chain) { it.index = len(it.chain) return nil, nil } + // Advance the iterator and wait for verification result if not yet done it.index++ - if err := <-it.results; err != nil { - return it.chain[it.index], err + if len(it.errors) <= it.index { + it.errors = append(it.errors, <-it.results) + } + if it.errors[it.index] != nil { + return it.chain[it.index], it.errors[it.index] } + // Block header valid, run body validation and return return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index]) } +// peek returns the next block in the iterator, along with any potential validation +// error for that block, but does **not** advance the iterator. +// +// Both header and body validation errors (nil too) is cached into the iterator +// to avoid duplicating work on the following next() call. +func (it *insertIterator) peek() (*types.Block, error) { + // If we reached the end of the chain, abort + if it.index+1 >= len(it.chain) { + return nil, nil + } + // Wait for verification result if not yet done + if len(it.errors) <= it.index+1 { + it.errors = append(it.errors, <-it.results) + } + if it.errors[it.index+1] != nil { + return it.chain[it.index+1], it.errors[it.index+1] + } + // Block header valid, ignore body validation since we don't have a parent anyway + return it.chain[it.index+1], nil +} + // previous returns the previous header that was being processed, or nil. func (it *insertIterator) previous() *types.Header { if it.index < 1 { diff --git a/core/chain_indexer.go b/core/chain_indexer.go index b1e7dbfcbf7b..e1e70187232a 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -73,7 +73,7 @@ type ChainIndexer struct { backend ChainIndexerBackend // Background processor generating the index data content children []*ChainIndexer // Child indexers to cascade chain updates to - active uint32 // Flag whether the event loop was started + active atomic.Bool // Flag whether the event loop was started update chan struct{} // Notification channel that headers should be processed quit chan chan error // Quit channel to tear down running goroutines ctx context.Context @@ -153,7 +153,7 @@ func (c *ChainIndexer) Close() error { errs = append(errs, err) } // If needed, tear down the secondary event loop - if atomic.LoadUint32(&c.active) != 0 { + if c.active.Load() { c.quit <- errc if err := <-errc; err != nil { errs = append(errs, err) @@ -183,7 +183,7 @@ func (c *ChainIndexer) Close() error { // queue. func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainEvent, sub event.Subscription) { // Mark the chain indexer as active, requiring an additional teardown - atomic.StoreUint32(&c.active, 1) + c.active.Store(true) defer sub.Unsubscribe() diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go new file mode 100644 index 000000000000..62910989d538 --- /dev/null +++ b/core/state_prefetcher.go @@ -0,0 +1,95 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package core + +import ( + "sync/atomic" + + "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/consensus" + "github.com/XinFinOrg/XDPoSChain/core/state" + "github.com/XinFinOrg/XDPoSChain/core/types" + "github.com/XinFinOrg/XDPoSChain/core/vm" + "github.com/XinFinOrg/XDPoSChain/params" +) + +// statePrefetcher is a basic Prefetcher, which blindly executes a block on top +// of an arbitrary state with the goal of prefetching potentially useful state +// data from disk before the main block processor start executing. +type statePrefetcher struct { + config *params.ChainConfig // Chain configuration options + bc *BlockChain // Canonical block chain + engine consensus.Engine // Consensus engine used for block rewards +} + +// newStatePrefetcher initialises a new statePrefetcher. +func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *statePrefetcher { + return &statePrefetcher{ + config: config, + bc: bc, + engine: engine, + } +} + +// Prefetch processes the state changes according to the Ethereum rules by running +// the transaction messages using the statedb, but any changes are discarded. The +// only goal is to pre-cache transaction signatures and state trie nodes. +func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) { + var ( + header = block.Header() + gaspool = new(GasPool).AddGas(block.GasLimit()) + blockContext = NewEVMBlockContext(header, p.bc, nil) + evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, p.config, cfg) + signer = types.MakeSigner(p.config, header.Number) + ) + // Iterate over and process the individual transactions + byzantium := p.config.IsByzantium(block.Number()) + for i, tx := range block.Transactions() { + // If block precaching was interrupted, abort + if interrupt != nil && interrupt.Load() { + return + } + // Convert the transaction into an executable message and pre-cache its sender + msg, err := tx.AsMessage(signer, nil, nil, header.BaseFee) + if err != nil { + return // Also invalid block, bail out + } + statedb.SetTxContext(tx.Hash(), i) + if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil { + return // Ugh, something went horribly wrong, bail out + } + // If we're pre-byzantium, pre-load trie nodes for the intermediate root + if !byzantium { + statedb.IntermediateRoot(true) + } + } + // If were post-byzantium, pre-load trie nodes for the final root hash + if byzantium { + statedb.IntermediateRoot(true) + } +} + +// precacheTransaction attempts to apply a transaction to the given state database +// and uses the input parameters for its environment. The goal is not to execute +// the transaction successfully, rather to warm up touched data slots. +func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { + // Update the evm with the new transaction context. + evm.Reset(NewEVMTxContext(msg), statedb) + // Add addresses to access list if applicable + _, err := ApplyMessage(evm, msg, gaspool, common.Address{}) + return err +} diff --git a/core/types.go b/core/types.go index 961e07b13632..3befed7067da 100644 --- a/core/types.go +++ b/core/types.go @@ -18,6 +18,7 @@ package core import ( "math/big" + "sync/atomic" "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate" @@ -43,13 +44,19 @@ type Validator interface { ValidateLendingOrder(statedb *state.StateDB, lendingStateDb *lendingstate.LendingStateDB, XDCxStatedb *tradingstate.TradingStateDB, batch lendingstate.TxLendingBatch, coinbase common.Address, header *types.Header) error } +// Prefetcher is an interface for pre-caching transaction signatures and state. +type Prefetcher interface { + // Prefetch processes the state changes according to the Ethereum rules by running + // the transaction messages using the statedb, but any changes are discarded. The + // only goal is to pre-cache transaction signatures and state trie nodes. + Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) +} + // Processor is an interface for processing blocks using a given initial state. -// -// Process takes the block to be processed and the statedb upon which the -// initial state is based. It should return the receipts generated, amount -// of gas used in the process and return an error if any of the internal rules -// failed. type Processor interface { + // Process processes the state changes according to the Ethereum rules by running + // the transaction messages using the statedb and applying any rewards to both + // the processor (coinbase) and any included uncles. Process(block *types.Block, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, cfg vm.Config, balanceFee map[common.Address]*big.Int) (types.Receipts, []*types.Log, uint64, error) ProcessBlockNoValidator(block *CalculatedBlock, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, cfg vm.Config, balanceFee map[common.Address]*big.Int) (types.Receipts, []*types.Log, uint64, error) diff --git a/eth/backend.go b/eth/backend.go index 9fb7db42e57f..824e5fd9ddfb 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -176,10 +176,11 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin var ( vmConfig = vm.Config{EnablePreimageRecording: config.EnablePreimageRecording} cacheConfig = &core.CacheConfig{ - Disabled: config.NoPruning, - TrieCleanLimit: config.TrieCleanCache, - TrieDirtyLimit: config.TrieDirtyCache, - TrieTimeLimit: config.TrieTimeout, + TrieCleanLimit: config.TrieCleanCache, + TrieCleanNoPrefetch: config.NoPrefetch, + TrieDirtyLimit: config.TrieDirtyCache, + TrieDirtyDisabled: config.NoPruning, + TrieTimeLimit: config.TrieTimeout, } ) if eth.chainConfig.XDPoS != nil { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 8d53405a9c44..6b1316c8305d 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -103,7 +103,9 @@ type Config struct { // zero, the chain ID is used as network ID. NetworkId uint64 SyncMode downloader.SyncMode - NoPruning bool + + NoPruning bool // Whether to disable pruning and flush everything to disk + NoPrefetch bool // Whether to disable prefetching and only load state on demand // Light client options LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests