Skip to content

Commit 457e930

Browse files
rjl493456442karalabe
authored andcommitted
eth, miner: prefer locally generated uncles vs remote ones (#17715)
* core, eth: fix dependency cycle * eth, miner: perfer to locally generated uncle
1 parent ba0a8b7 commit 457e930

File tree

4 files changed

+53
-27
lines changed

4 files changed

+53
-27
lines changed

eth/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
177177
return nil, err
178178
}
179179

180-
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil)
180+
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock)
181181
eth.miner.SetExtra(makeExtraData(config.MinerExtraData))
182182

183183
eth.APIBackend = &EthAPIBackend{eth, nil}

miner/miner.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ type Miner struct {
5252
shouldStart int32 // should start indicates whether we should start after sync
5353
}
5454

55-
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64) *Miner {
55+
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(block *types.Block) bool) *Miner {
5656
miner := &Miner{
5757
eth: eth,
5858
mux: mux,
5959
engine: engine,
6060
exitCh: make(chan struct{}),
61-
worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil),
61+
worker: newWorker(config, engine, eth, mux, recommit, gasFloor, gasCeil, isLocalBlock),
6262
canStart: 1,
6363
}
6464
go miner.update()

miner/worker.go

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ type worker struct {
149149
resubmitIntervalCh chan time.Duration
150150
resubmitAdjustCh chan *intervalAdjust
151151

152-
current *environment // An environment for current running cycle.
153-
possibleUncles map[common.Hash]*types.Block // A set of side blocks as the possible uncle blocks.
154-
unconfirmed *unconfirmedBlocks // A set of locally mined blocks pending canonicalness confirmations.
152+
current *environment // An environment for current running cycle.
153+
localUncles map[common.Hash]*types.Block // A set of side blocks generated locally as the possible uncle blocks.
154+
remoteUncles map[common.Hash]*types.Block // A set of side blocks as the possible uncle blocks.
155+
unconfirmed *unconfirmedBlocks // A set of locally mined blocks pending canonicalness confirmations.
155156

156157
mu sync.RWMutex // The lock used to protect the coinbase and extra fields
157158
coinbase common.Address
@@ -168,14 +169,17 @@ type worker struct {
168169
running int32 // The indicator whether the consensus engine is running or not.
169170
newTxs int32 // New arrival transaction count since last sealing work submitting.
170171

172+
// External functions
173+
isLocalBlock func(block *types.Block) bool // Function used to determine whether the specified block is mined by local miner.
174+
171175
// Test hooks
172176
newTaskHook func(*task) // Method to call upon receiving a new sealing task.
173177
skipSealHook func(*task) bool // Method to decide whether skipping the sealing.
174178
fullTaskHook func() // Method to call before pushing the full sealing task.
175179
resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval.
176180
}
177181

178-
func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64) *worker {
182+
func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(*types.Block) bool) *worker {
179183
worker := &worker{
180184
config: config,
181185
engine: engine,
@@ -184,7 +188,9 @@ func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend,
184188
chain: eth.BlockChain(),
185189
gasFloor: gasFloor,
186190
gasCeil: gasCeil,
187-
possibleUncles: make(map[common.Hash]*types.Block),
191+
isLocalBlock: isLocalBlock,
192+
localUncles: make(map[common.Hash]*types.Block),
193+
remoteUncles: make(map[common.Hash]*types.Block),
188194
unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth),
189195
pendingTasks: make(map[common.Hash]*task),
190196
txsCh: make(chan core.NewTxsEvent, txChanSize),
@@ -405,11 +411,19 @@ func (w *worker) mainLoop() {
405411
w.commitNewWork(req.interrupt, req.noempty, req.timestamp)
406412

407413
case ev := <-w.chainSideCh:
408-
if _, exist := w.possibleUncles[ev.Block.Hash()]; exist {
414+
// Short circuit for duplicate side blocks
415+
if _, exist := w.localUncles[ev.Block.Hash()]; exist {
416+
continue
417+
}
418+
if _, exist := w.remoteUncles[ev.Block.Hash()]; exist {
409419
continue
410420
}
411-
// Add side block to possible uncle block set.
412-
w.possibleUncles[ev.Block.Hash()] = ev.Block
421+
// Add side block to possible uncle block set depending on the author.
422+
if w.isLocalBlock != nil && w.isLocalBlock(ev.Block) {
423+
w.localUncles[ev.Block.Hash()] = ev.Block
424+
} else {
425+
w.remoteUncles[ev.Block.Hash()] = ev.Block
426+
}
413427
// If our mining block contains less than 2 uncle blocks,
414428
// add the new uncle block if valid and regenerate a mining block.
415429
if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 {
@@ -421,7 +435,10 @@ func (w *worker) mainLoop() {
421435
if !ok {
422436
return false
423437
}
424-
uncle, exist := w.possibleUncles[hash]
438+
uncle, exist := w.localUncles[hash]
439+
if !exist {
440+
uncle, exist = w.remoteUncles[hash]
441+
}
425442
if !exist {
426443
return false
427444
}
@@ -651,7 +668,10 @@ func (w *worker) updateSnapshot() {
651668
if !ok {
652669
return false
653670
}
654-
uncle, exist := w.possibleUncles[hash]
671+
uncle, exist := w.localUncles[hash]
672+
if !exist {
673+
uncle, exist = w.remoteUncles[hash]
674+
}
655675
if !exist {
656676
return false
657677
}
@@ -859,23 +879,29 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
859879
misc.ApplyDAOHardFork(env.state)
860880
}
861881
// Accumulate the uncles for the current block
862-
for hash, uncle := range w.possibleUncles {
863-
if uncle.NumberU64()+staleThreshold <= header.Number.Uint64() {
864-
delete(w.possibleUncles, hash)
865-
}
866-
}
867882
uncles := make([]*types.Header, 0, 2)
868-
for hash, uncle := range w.possibleUncles {
869-
if len(uncles) == 2 {
870-
break
883+
commitUncles := func(blocks map[common.Hash]*types.Block) {
884+
// Clean up stale uncle blocks first
885+
for hash, uncle := range blocks {
886+
if uncle.NumberU64()+staleThreshold <= header.Number.Uint64() {
887+
delete(blocks, hash)
888+
}
871889
}
872-
if err := w.commitUncle(env, uncle.Header()); err != nil {
873-
log.Trace("Possible uncle rejected", "hash", hash, "reason", err)
874-
} else {
875-
log.Debug("Committing new uncle to block", "hash", hash)
876-
uncles = append(uncles, uncle.Header())
890+
for hash, uncle := range blocks {
891+
if len(uncles) == 2 {
892+
break
893+
}
894+
if err := w.commitUncle(env, uncle.Header()); err != nil {
895+
log.Trace("Possible uncle rejected", "hash", hash, "reason", err)
896+
} else {
897+
log.Debug("Committing new uncle to block", "hash", hash)
898+
uncles = append(uncles, uncle.Header())
899+
}
877900
}
878901
}
902+
// Prefer to locally generated uncle
903+
commitUncles(w.localUncles)
904+
commitUncles(w.remoteUncles)
879905

880906
if !noempty {
881907
// Create an empty block based on temporary copied state for sealing in advance without waiting block

miner/worker_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (b *testWorkerBackend) PostChainEvents(events []interface{}) {
133133
func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, blocks int) (*worker, *testWorkerBackend) {
134134
backend := newTestWorkerBackend(t, chainConfig, engine, blocks)
135135
backend.txPool.AddLocals(pendingTxs)
136-
w := newWorker(chainConfig, engine, backend, new(event.TypeMux), time.Second, params.GenesisGasLimit, params.GenesisGasLimit)
136+
w := newWorker(chainConfig, engine, backend, new(event.TypeMux), time.Second, params.GenesisGasLimit, params.GenesisGasLimit, nil)
137137
w.setEtherbase(testBankAddress)
138138
return w, backend
139139
}

0 commit comments

Comments
 (0)