move traced block processing to own func

This commit is contained in:
Sina Mahmoodi 2023-11-24 14:37:29 +03:30
parent 1d136450d8
commit 856c0791a6
1 changed files with 127 additions and 114 deletions

View File

@ -1848,11 +1848,88 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
}
}
// Process block using the parent state as reference point
pstart := time.Now()
// The traced section of block import.
err, stop := func() (blockEndErr error, _ bool) {
err, stop, res := bc.processBlock(block, statedb, followupInterrupt, start, setHead)
if err != nil || stop {
return it.index, err
}
// Report the import stats before returning the various results
stats.processed++
stats.usedGas += res.usedGas
var snapDiffItems, snapBufItems common.StorageSize
if bc.snaps != nil {
snapDiffItems, snapBufItems = bc.snaps.Size()
}
trieDiffNodes, trieBufNodes, _ := bc.triedb.Size()
stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead)
if !setHead {
// After merge we expect few side chains. Simply count
// all blocks the CL gives us for GC processing time
bc.gcproc += res.procTime
bc.logger.OnBlockEnd(nil)
return it.index, nil // Direct block insertion of a single block
}
switch res.status {
case CanonStatTy:
log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(),
"uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(),
"elapsed", common.PrettyDuration(time.Since(start)),
"root", block.Root())
lastCanon = block
// Only count canonical blocks for GC processing time
bc.gcproc += res.procTime
case SideStatTy:
log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(),
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
"root", block.Root())
default:
// This in theory is impossible, but lets be nice to our future selves and leave
// a log, instead of trying to track down blocks imports that don't emit logs.
log.Warn("Inserted block with unknown status", "number", block.Number(), "hash", block.Hash(),
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
"root", block.Root())
}
bc.logger.OnBlockEnd(nil)
}
// Any blocks remaining here? The only ones we care about are the future ones
if block != nil && errors.Is(err, consensus.ErrFutureBlock) {
if err := bc.addFutureBlock(block); err != nil {
return it.index, err
}
block, err = it.next()
for ; block != nil && errors.Is(err, consensus.ErrUnknownAncestor); block, err = it.next() {
if err := bc.addFutureBlock(block); err != nil {
return it.index, err
}
stats.queued++
}
}
stats.ignored += it.remaining()
return it.index, err
}
// blockProcessingResult is a summary of block processing
// used for updating the stats.
type blockProcessingResult struct {
usedGas uint64
procTime time.Duration
status WriteStatus
}
// processBlock executes and validates the given block. If there was no error
// it writes the block and associated state to database.
func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, followupInterrupt atomic.Bool, start time.Time, setHead bool) (blockEndErr error, _ bool, _ *blockProcessingResult) {
if bc.logger != nil {
td := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
bc.logger.OnBlockStart(block, td, bc.CurrentFinalBlock(), bc.CurrentSafeBlock())
@ -1860,11 +1937,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
bc.logger.OnBlockEnd(blockEndErr)
}()
}
// Process block using the parent state as reference point
pstart := time.Now()
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
if err != nil {
bc.reportBlock(block, receipts, err)
followupInterrupt.Store(true)
return err, true
return err, true, nil
}
ptime := time.Since(pstart)
@ -1872,7 +1952,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
bc.reportBlock(block, receipts, err)
followupInterrupt.Store(true)
return err, true
return err, true, nil
}
vtime := time.Since(vstart)
proctime := time.Since(start) // processing + validation
@ -1906,7 +1986,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
}
followupInterrupt.Store(true)
if err != nil {
return err, true
return err, true, &blockProcessingResult{usedGas: usedGas, procTime: proctime, status: status}
}
// Update the metrics touched during block commit
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
@ -1917,74 +1997,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
blockWriteTimer.Update(time.Since(wstart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits)
blockInsertTimer.UpdateSince(start)
// Report the import stats before returning the various results
stats.processed++
stats.usedGas += usedGas
var snapDiffItems, snapBufItems common.StorageSize
if bc.snaps != nil {
snapDiffItems, snapBufItems = bc.snaps.Size()
}
trieDiffNodes, trieBufNodes, _ := bc.triedb.Size()
stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead)
if !setHead {
// After merge we expect few side chains. Simply count
// all blocks the CL gives us for GC processing time
bc.gcproc += proctime
return nil, true // Direct block insertion of a single block
}
switch status {
case CanonStatTy:
log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(),
"uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(),
"elapsed", common.PrettyDuration(time.Since(start)),
"root", block.Root())
lastCanon = block
// Only count canonical blocks for GC processing time
bc.gcproc += proctime
case SideStatTy:
log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(),
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
"root", block.Root())
default:
// This in theory is impossible, but lets be nice to our future selves and leave
// a log, instead of trying to track down blocks imports that don't emit logs.
log.Warn("Inserted block with unknown status", "number", block.Number(), "hash", block.Hash(),
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
"root", block.Root())
}
return nil, false
}()
if err != nil || stop {
return it.index, err
}
}
// Any blocks remaining here? The only ones we care about are the future ones
if block != nil && errors.Is(err, consensus.ErrFutureBlock) {
if err := bc.addFutureBlock(block); err != nil {
return it.index, err
}
block, err = it.next()
for ; block != nil && errors.Is(err, consensus.ErrUnknownAncestor); block, err = it.next() {
if err := bc.addFutureBlock(block); err != nil {
return it.index, err
}
stats.queued++
}
}
stats.ignored += it.remaining()
return it.index, err
return nil, false, &blockProcessingResult{usedGas: usedGas, procTime: proctime, status: status}
}
// insertSideChain is called when an import batch hits upon a pruned ancestor