Skip to content

Commit

Permalink
worker: always drop on new block imported.
Browse files Browse the repository at this point in the history
When new block is imported, there is no need to commit the current
work, even the new imported block is offturn and itself is inturn.

That is because when offturn block is received, the inturn block is
already later to broadcast block, deliver the later block will cause
many reorg, which is not reasonable.

And also make sure all useless work can be discarded, to avoid goroutine leak.
  • Loading branch information
setunapo committed Nov 18, 2022
1 parent 58481ea commit c63c4ec
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 41 deletions.
4 changes: 0 additions & 4 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,6 @@ func (beacon *Beacon) SetThreads(threads int) {
}
}

func (p *Beacon) DropOnNewBlock(*types.Header) bool {
return true
}

// IsTTDReached checks if the TotalTerminalDifficulty has been surpassed on the `parentHash` block.
// It depends on the parentHash already being stored in the database.
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
Expand Down
5 changes: 0 additions & 5 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,11 +705,6 @@ func (c *Clique) APIs(chain consensus.ChainHeaderReader) []rpc.API {
}}
}

func (p *Clique) DropOnNewBlock(header *types.Header) bool {
// drop the block if it is not in turn.
return header.Difficulty.Cmp(diffNoTurn) == 0
}

// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
Expand Down
6 changes: 0 additions & 6 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,6 @@ type Engine interface {

// Close terminates any background threads maintained by the consensus engine.
Close() error

// DropOnNewBlock determine the action of mining when it is interrupted by new imported block.
// Return
// true: the mining result will be dropped
// false: the mining result will be kept and move on to the next mine step.
DropOnNewBlock(header *types.Header) bool
}

// PoW is a consensus engine based on proof-of-work.
Expand Down
4 changes: 0 additions & 4 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -647,10 +647,6 @@ var (
big32 = big.NewInt(32)
)

func (p *Ethash) DropOnNewBlock(*types.Header) bool {
return true
}

// AccumulateRewards credits the coinbase of the given block with the mining
// reward. The total reward consists of the static block reward and rewards for
// included uncles. The coinbase of each uncle block is also rewarded.
Expand Down
5 changes: 0 additions & 5 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,11 +976,6 @@ func (p *Parlia) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64,
return CalcDifficulty(snap, p.val)
}

func (p *Parlia) DropOnNewBlock(header *types.Header) bool {
// drop the block if it is not in turn.
return header.Difficulty.Cmp(diffNoTurn) == 0
}

// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
// that a new block should have based on the previous blocks in the chain and the
// current signer.
Expand Down
44 changes: 27 additions & 17 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1084,8 +1084,6 @@ func (w *worker) commitWork(interruptCh chan int32, timestamp int64) {

// validator can try several times to get the most profitable block,
// as long as the timestamp is not reached.
var bestWork *environment
bestReward := new(big.Int)
param := generateParams{
timestamp: uint64(timestamp),
coinbase: coinbase,
Expand All @@ -1095,23 +1093,25 @@ func (w *worker) commitWork(interruptCh chan int32, timestamp int64) {
if err != nil {
return
}
var bestWork *environment
bestReward := new(big.Int)
LOOP:
for {
// StateDB can not be shared, create for each time.
work, err := w.prepareWorkEnv(&param, parentBlock, header)
if err != nil {
return
}
if bestWork == nil {
bestWork = work
}

delay := w.engine.Delay(w.chain, work.header, &w.config.DelayLeftOver)
if delay == nil {
log.Warn("commitWork delay is nil, something is wrong")
stopTimer = nil
} else if *delay <= 0 {
log.Debug("Not enough time for commitWork")
if bestWork == nil {
bestWork = work
}
break
} else {
log.Debug("commitWork stopTimer", "block", work.header.Number,
Expand All @@ -1130,26 +1130,35 @@ LOOP:
err = w.fillTransactions(interruptCh, work, stopTimer)
fillDuration := time.Since(fillStart)

// To get the most profitable work
curReward := work.state.GetBalance(consensus.SystemAddress)
log.Debug("Get the most profitable work", "curReward", curReward, "bestReward", bestReward)
if curReward.Cmp(bestReward) > 0 {
bestWork.discard()
if bestWork == nil {
// it is the first work, update bestReward
bestWork = work
bestReward = curReward
bestReward = work.state.GetBalance(consensus.SystemAddress)
log.Debug("The first work", "bestReward", bestReward)
} else {
// To get the most profitable work
curReward := work.state.GetBalance(consensus.SystemAddress)
log.Debug("The more profitable work", "curReward", curReward, "bestReward", bestReward)
if curReward.Cmp(bestReward) < 0 {
// this work will not be selected, discard it.
work.discard()
} else {
// get a better one, update and discard the previous one
bestWork.discard()
bestWork = work
bestReward = curReward
}
}

switch {
case errors.Is(err, errBlockInterruptedByNewHead):
// For Parlia, it will drop the work on receiving new block if it is not inturn.
if w.engine.DropOnNewBlock(work.header) {
log.Debug("drop the block, when new block is imported")
return
}
log.Debug("commitWork abort", "err", err)
bestWork.discard()
return
case errors.Is(err, errBlockInterruptedByTimeout):
case errors.Is(err, errBlockInterruptedByOutOfGas):
// break the loop to get the best work
log.Debug("commitWork abort", "err", err)
log.Debug("commitWork finish", "reason", err)
break LOOP
}

Expand All @@ -1171,6 +1180,7 @@ LOOP:
break LOOP
case <-interruptCh:
log.Debug("commitWork interruptCh closed, new block imported or resubmit triggered")
bestWork.discard()
return
case ev := <-txsCh:
delay := w.engine.Delay(w.chain, work.header, &w.config.DelayLeftOver)
Expand Down

0 comments on commit c63c4ec

Please sign in to comment.