github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/miner/miner.go (about) 1 package miner 2 3 import ( 4 "fmt" 5 "sync/atomic" 6 7 "github.com/neatio-net/neatio/chain/accounts" 8 "github.com/neatio-net/neatio/chain/consensus" 9 "github.com/neatio-net/neatio/chain/core" 10 "github.com/neatio-net/neatio/chain/core/state" 11 "github.com/neatio-net/neatio/chain/core/types" 12 "github.com/neatio-net/neatio/chain/log" 13 "github.com/neatio-net/neatio/neatdb" 14 "github.com/neatio-net/neatio/neatptc/downloader" 15 "github.com/neatio-net/neatio/params" 16 "github.com/neatio-net/neatio/utilities/common" 17 "github.com/neatio-net/neatio/utilities/event" 18 ) 19 20 type Backend interface { 21 AccountManager() *accounts.Manager 22 BlockChain() *core.BlockChain 23 TxPool() *core.TxPool 24 ChainDb() neatdb.Database 25 } 26 27 type Pending interface { 28 Pending() (*types.Block, *state.StateDB) 29 PendingBlock() *types.Block 30 } 31 32 type Miner struct { 33 mux *event.TypeMux 34 35 worker *worker 36 37 coinbase common.Address 38 mining int32 39 eth Backend 40 engine consensus.Engine 41 exitCh chan struct{} 42 43 canStart int32 44 shouldStart int32 45 46 logger log.Logger 47 cch core.CrossChainHelper 48 } 49 50 func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, gasFloor, gasCeil uint64, cch core.CrossChainHelper) *Miner { 51 miner := &Miner{ 52 eth: eth, 53 mux: mux, 54 engine: engine, 55 exitCh: make(chan struct{}), 56 worker: newWorker(config, engine, eth, mux, gasFloor, gasCeil, cch), 57 canStart: 1, 58 logger: config.ChainLogger, 59 cch: cch, 60 } 61 miner.Register(NewCpuAgent(eth.BlockChain(), engine, config.ChainLogger)) 62 go miner.update() 63 64 return miner 65 } 66 67 func (self *Miner) update() { 68 events := self.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{}) 69 defer events.Unsubscribe() 70 71 for { 72 select { 73 case ev := <-events.Chan(): 74 if ev == nil { 75 return 76 } 77 switch ev.Data.(type) { 78 case downloader.StartEvent: 79 self.logger.Debug("(self *Miner) update(); downloader.StartEvent received") 80 atomic.StoreInt32(&self.canStart, 0) 81 if self.Mining() { 82 self.Stop() 83 atomic.StoreInt32(&self.shouldStart, 1) 84 self.logger.Info("Mining aborted due to sync") 85 } 86 case downloader.DoneEvent, downloader.FailedEvent: 87 88 self.logger.Debug("(self *Miner) update(); downloader.DoneEvent, downloader.FailedEvent received") 89 shouldStart := atomic.LoadInt32(&self.shouldStart) == 1 90 91 atomic.StoreInt32(&self.canStart, 1) 92 atomic.StoreInt32(&self.shouldStart, 0) 93 if shouldStart { 94 self.Start(self.coinbase) 95 } 96 97 return 98 } 99 case <-self.exitCh: 100 return 101 } 102 } 103 } 104 105 func (self *Miner) Start(coinbase common.Address) { 106 atomic.StoreInt32(&self.shouldStart, 1) 107 self.SetCoinbase(coinbase) 108 109 if atomic.LoadInt32(&self.canStart) == 0 { 110 self.logger.Info("Network syncing, will start miner afterwards") 111 return 112 } 113 self.worker.start() 114 self.worker.commitNewWork() 115 } 116 117 func (self *Miner) Stop() { 118 self.worker.stop() 119 atomic.StoreInt32(&self.shouldStart, 0) 120 } 121 122 func (self *Miner) Close() { 123 self.worker.close() 124 close(self.exitCh) 125 } 126 127 func (self *Miner) Register(agent Agent) { 128 if self.Mining() { 129 agent.Start() 130 } 131 self.worker.register(agent) 132 } 133 134 func (self *Miner) Unregister(agent Agent) { 135 self.worker.unregister(agent) 136 } 137 138 func (self *Miner) Mining() bool { 139 return self.worker.isRunning() 140 } 141 142 func (self *Miner) SetExtra(extra []byte) error { 143 if uint64(len(extra)) > params.MaximumExtraDataSize { 144 return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize) 145 } 146 self.worker.setExtra(extra) 147 return nil 148 } 149 150 func (self *Miner) Pending() (*types.Block, *state.StateDB) { 151 return self.worker.pending() 152 } 153 154 func (self *Miner) PendingBlock() *types.Block { 155 return self.worker.pendingBlock() 156 } 157 158 func (self *Miner) SetCoinbase(addr common.Address) { 159 self.coinbase = addr 160 self.worker.setCoinbase(addr) 161 }