Skip to content

Commit

Permalink
worker: add double sign check for safety. (bnb-chain#1201)
Browse files Browse the repository at this point in the history
* worker: add double sign check for safety.

And for corner cases, such as reorg after reorg...
use slice to record all broadcast blocks's parents to avoid overwritten.
  • Loading branch information
brilliant-lx authored and setunapo committed Nov 25, 2022
1 parent 17423ad commit 8cc26c8
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
lru "github.com/hashicorp/golang-lru"
)

const (
Expand All @@ -63,6 +64,10 @@ const (

// staleThreshold is the maximum depth of the acceptable stale block.
staleThreshold = 11

// the current 4 mining loops could have asynchronous risk of mining block with
// save height, keep recently mined blocks to avoid double sign for safety,
recentMinedCacheLimit = 20
)

var (
Expand Down Expand Up @@ -226,13 +231,15 @@ type worker struct {
isLocalBlock func(header *types.Header) bool // Function used to determine whether the specified block is mined by local miner.

// Test hooks
newTaskHook func(*task) // Method to call upon receiving a new sealing task.
skipSealHook func(*task) bool // Method to decide whether skipping the sealing.
fullTaskHook func() // Method to call before pushing the full sealing task.
resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval.
newTaskHook func(*task) // Method to call upon receiving a new sealing task.
skipSealHook func(*task) bool // Method to decide whether skipping the sealing.
fullTaskHook func() // Method to call before pushing the full sealing task.
resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval.
recentMinedBlocks *lru.Cache
}

func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(header *types.Header) bool, init bool) *worker {
recentMinedBlocks, _ := lru.New(recentMinedCacheLimit)
worker := &worker{
prefetcher: core.NewStatePrefetcher(chainConfig, eth.BlockChain(), engine),
config: config,
Expand All @@ -256,6 +263,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
exitCh: make(chan struct{}),
startCh: make(chan struct{}, 1),
resubmitIntervalCh: make(chan time.Duration),
recentMinedBlocks: recentMinedBlocks,
}
// Subscribe NewTxsEvent for tx pool
worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh)
Expand Down Expand Up @@ -661,6 +669,30 @@ func (w *worker) resultLoop() {
logs = append(logs, receipt.Logs...)
}

if prev, ok := w.recentMinedBlocks.Get(block.NumberU64()); ok {
doubleSign := false
prevParents, _ := prev.([]common.Hash)
for _, prevParent := range prevParents {
if prevParent == block.ParentHash() {
log.Error("Reject Double Sign!!", "block", block.NumberU64(),
"hash", block.Hash(),
"root", block.Root(),
"ParentHash", block.ParentHash())
doubleSign = true
break
}
}
if doubleSign {
continue
}
prevParents = append(prevParents, block.ParentHash())
w.recentMinedBlocks.Add(block.NumberU64(), prevParents)
} else {
// Add() will call removeOldest internally to remove the oldest element
// if the LRU Cache is full
w.recentMinedBlocks.Add(block.NumberU64(), []common.Hash{block.ParentHash()})
}

// Broadcast the block and announce chain insertion event
w.mux.Post(core.NewMinedBlockEvent{Block: block})

Expand Down

0 comments on commit 8cc26c8

Please sign in to comment.