mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
miner: subscribe downloader event by feed
This commit is contained in:
parent
d0b3667037
commit
13cb67effa
2 changed files with 42 additions and 16 deletions
|
|
@ -16,10 +16,10 @@
|
||||||
|
|
||||||
package downloader
|
package downloader
|
||||||
|
|
||||||
// StartEvent is posted when downloader start to synchronization
|
// StartEvent is posted when downloader starts synchronization
|
||||||
type StartEvent struct{}
|
type StartEvent struct{}
|
||||||
|
|
||||||
// FinishEvent is posted when downloader finish synchronization.
|
// FinishEvent is posted when downloader finishes synchronization.
|
||||||
// If synchronization is not successful, a relevant error will be returned.
|
// If synchronization is not successful, a relevant error will be returned.
|
||||||
type FinishEvent struct {
|
type FinishEvent struct {
|
||||||
Err error
|
Err error
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,11 @@ type Backend interface {
|
||||||
BlockChain() *core.BlockChain
|
BlockChain() *core.BlockChain
|
||||||
TxPool() *core.TxPool
|
TxPool() *core.TxPool
|
||||||
ChainDb() ethdb.Database
|
ChainDb() ethdb.Database
|
||||||
|
Downloader() *downloader.Downloader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miner creates blocks and searches for proof-of-work values.
|
// Miner creates blocks and searches for proof-of-work values.
|
||||||
type Miner struct {
|
type Miner struct {
|
||||||
mux *event.TypeMux
|
|
||||||
|
|
||||||
worker *worker
|
worker *worker
|
||||||
|
|
||||||
coinbase common.Address
|
coinbase common.Address
|
||||||
|
|
@ -55,16 +54,34 @@ type Miner struct {
|
||||||
|
|
||||||
canStart int32 // can start indicates whether we can start the mining operation
|
canStart int32 // can start indicates whether we can start the mining operation
|
||||||
shouldStart int32 // should start indicates whether we should start after sync
|
shouldStart int32 // should start indicates whether we should start after sync
|
||||||
|
|
||||||
|
// Channels
|
||||||
|
startCh chan downloader.StartEvent
|
||||||
|
finishCh chan downloader.FinishEvent
|
||||||
|
|
||||||
|
// Subscriptions
|
||||||
|
startSub event.Subscription
|
||||||
|
finishSub event.Subscription
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine) *Miner {
|
func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine) *Miner {
|
||||||
miner := &Miner{
|
miner := &Miner{
|
||||||
eth: eth,
|
eth: eth,
|
||||||
mux: mux,
|
|
||||||
engine: engine,
|
engine: engine,
|
||||||
worker: newWorker(config, engine, common.Address{}, eth, mux),
|
worker: newWorker(config, engine, common.Address{}, eth, mux),
|
||||||
canStart: 1,
|
canStart: 1,
|
||||||
|
startCh: make(chan downloader.StartEvent, 10),
|
||||||
|
finishCh: make(chan downloader.FinishEvent, 10),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscribe downloader events and make sure all the
|
||||||
|
// subscriptions are not empty.
|
||||||
|
miner.startSub = eth.Downloader().SubscribeStartEvent(miner.startCh)
|
||||||
|
miner.finishSub = eth.Downloader().SubscribeFinishEvent(miner.finishCh)
|
||||||
|
if miner.startSub == nil || miner.finishSub == nil {
|
||||||
|
log.Crit("Subscribe downloader events failed")
|
||||||
|
}
|
||||||
|
|
||||||
miner.Register(NewCpuAgent(eth.BlockChain(), engine))
|
miner.Register(NewCpuAgent(eth.BlockChain(), engine))
|
||||||
go miner.update()
|
go miner.update()
|
||||||
|
|
||||||
|
|
@ -72,22 +89,28 @@ func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine con
|
||||||
}
|
}
|
||||||
|
|
||||||
// update keeps track of the downloader events. Please be aware that this is a one shot type of update loop.
|
// update keeps track of the downloader events. Please be aware that this is a one shot type of update loop.
|
||||||
// It's entered once and as soon as `Done` or `Failed` has been broadcasted the events are unregistered and
|
// It's entered once and as soon as finish event has been broadcasted the events are unregistered and
|
||||||
// the loop is exited. This to prevent a major security vuln where external parties can DOS you with blocks
|
// the loop is exited. This to prevent a major security vuln where external parties can DOS you with blocks
|
||||||
// and halt your mining operation for as long as the DOS continues.
|
// and halt your mining operation for as long as the DOS continues.
|
||||||
func (self *Miner) update() {
|
func (self *Miner) update() {
|
||||||
events := self.mux.Subscribe(downloader.StartEvent{}, downloader.FinishEvent{})
|
defer func() {
|
||||||
out:
|
// Unsubscribe all downloader events
|
||||||
for ev := range events.Chan() {
|
self.startSub.Unsubscribe()
|
||||||
switch ev.Data.(type) {
|
self.finishSub.Unsubscribe()
|
||||||
case downloader.StartEvent:
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-self.startCh:
|
||||||
atomic.StoreInt32(&self.canStart, 0)
|
atomic.StoreInt32(&self.canStart, 0)
|
||||||
if self.Mining() {
|
if self.Mining() {
|
||||||
self.Stop()
|
self.Stop()
|
||||||
atomic.StoreInt32(&self.shouldStart, 1)
|
atomic.StoreInt32(&self.shouldStart, 1)
|
||||||
log.Info("Mining aborted due to sync")
|
log.Info("Mining aborted due to sync")
|
||||||
}
|
}
|
||||||
case downloader.FinishEvent:
|
|
||||||
|
case <-self.finishCh:
|
||||||
|
// We only interested the downloader finish event once.
|
||||||
shouldStart := atomic.LoadInt32(&self.shouldStart) == 1
|
shouldStart := atomic.LoadInt32(&self.shouldStart) == 1
|
||||||
|
|
||||||
atomic.StoreInt32(&self.canStart, 1)
|
atomic.StoreInt32(&self.canStart, 1)
|
||||||
|
|
@ -95,10 +118,13 @@ out:
|
||||||
if shouldStart {
|
if shouldStart {
|
||||||
self.Start(self.coinbase)
|
self.Start(self.coinbase)
|
||||||
}
|
}
|
||||||
// unsubscribe. we're only interested in this event once
|
// Stop immediately and ignore all further pending events
|
||||||
events.Unsubscribe()
|
return
|
||||||
// stop immediately and ignore all further pending events
|
|
||||||
break out
|
case <-self.startSub.Err():
|
||||||
|
return
|
||||||
|
case <-self.finishSub.Err():
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue