|
|
|
@ -102,12 +102,18 @@ func (s *Ethereum) AddLesServer(ls LesServer) { |
|
|
|
|
// New creates a new Ethereum object (including the
|
|
|
|
|
// initialisation of the common Ethereum object)
|
|
|
|
|
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { |
|
|
|
|
// Ensure configuration values are compatible and sane
|
|
|
|
|
if config.SyncMode == downloader.LightSync { |
|
|
|
|
return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") |
|
|
|
|
} |
|
|
|
|
if !config.SyncMode.IsValid() { |
|
|
|
|
return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) |
|
|
|
|
} |
|
|
|
|
if config.MinerGasPrice == nil || config.MinerGasPrice.Cmp(common.Big0) <= 0 { |
|
|
|
|
log.Warn("Sanitizing invalid miner gas price", "provided", config.MinerGasPrice, "updated", DefaultConfig.MinerGasPrice) |
|
|
|
|
config.MinerGasPrice = new(big.Int).Set(DefaultConfig.MinerGasPrice) |
|
|
|
|
} |
|
|
|
|
// Assemble the Ethereum object
|
|
|
|
|
chainDb, err := CreateDB(ctx, config, "chaindata") |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
@ -333,32 +339,66 @@ func (s *Ethereum) SetEtherbase(etherbase common.Address) { |
|
|
|
|
s.miner.SetEtherbase(etherbase) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Ethereum) StartMining(local bool) error { |
|
|
|
|
eb, err := s.Etherbase() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error("Cannot start mining without etherbase", "err", err) |
|
|
|
|
return fmt.Errorf("etherbase missing: %v", err) |
|
|
|
|
// StartMining starts the miner with the given number of CPU threads. If mining
|
|
|
|
|
// is already running, this method adjust the number of threads allowed to use
|
|
|
|
|
// and updates the minimum price required by the transaction pool.
|
|
|
|
|
func (s *Ethereum) StartMining(threads int) error { |
|
|
|
|
// Update the thread count within the consensus engine
|
|
|
|
|
type threaded interface { |
|
|
|
|
SetThreads(threads int) |
|
|
|
|
} |
|
|
|
|
if clique, ok := s.engine.(*clique.Clique); ok { |
|
|
|
|
wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) |
|
|
|
|
if wallet == nil || err != nil { |
|
|
|
|
log.Error("Etherbase account unavailable locally", "err", err) |
|
|
|
|
return fmt.Errorf("signer missing: %v", err) |
|
|
|
|
if th, ok := s.engine.(threaded); ok { |
|
|
|
|
log.Info("Updated mining threads", "threads", threads) |
|
|
|
|
if threads == 0 { |
|
|
|
|
threads = -1 // Disable the miner from within
|
|
|
|
|
} |
|
|
|
|
clique.Authorize(eb, wallet.SignHash) |
|
|
|
|
th.SetThreads(threads) |
|
|
|
|
} |
|
|
|
|
if local { |
|
|
|
|
// If local (CPU) mining is started, we can disable the transaction rejection
|
|
|
|
|
// mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous
|
|
|
|
|
// so none will ever hit this path, whereas marking sync done on CPU mining
|
|
|
|
|
// will ensure that private networks work in single miner mode too.
|
|
|
|
|
// If the miner was not running, initialize it
|
|
|
|
|
if !s.IsMining() { |
|
|
|
|
// Propagate the initial price point to the transaction pool
|
|
|
|
|
s.lock.RLock() |
|
|
|
|
price := s.gasPrice |
|
|
|
|
s.lock.RUnlock() |
|
|
|
|
s.txPool.SetGasPrice(price) |
|
|
|
|
|
|
|
|
|
// Configure the local mining addess
|
|
|
|
|
eb, err := s.Etherbase() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error("Cannot start mining without etherbase", "err", err) |
|
|
|
|
return fmt.Errorf("etherbase missing: %v", err) |
|
|
|
|
} |
|
|
|
|
if clique, ok := s.engine.(*clique.Clique); ok { |
|
|
|
|
wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) |
|
|
|
|
if wallet == nil || err != nil { |
|
|
|
|
log.Error("Etherbase account unavailable locally", "err", err) |
|
|
|
|
return fmt.Errorf("signer missing: %v", err) |
|
|
|
|
} |
|
|
|
|
clique.Authorize(eb, wallet.SignHash) |
|
|
|
|
} |
|
|
|
|
// If mining is started, we can disable the transaction rejection mechanism
|
|
|
|
|
// introduced to speed sync times.
|
|
|
|
|
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) |
|
|
|
|
|
|
|
|
|
go s.miner.Start(eb) |
|
|
|
|
} |
|
|
|
|
go s.miner.Start(eb) |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Ethereum) StopMining() { s.miner.Stop() } |
|
|
|
|
// StopMining terminates the miner, both at the consensus engine level as well as
|
|
|
|
|
// at the block creation level.
|
|
|
|
|
func (s *Ethereum) StopMining() { |
|
|
|
|
// Update the thread count within the consensus engine
|
|
|
|
|
type threaded interface { |
|
|
|
|
SetThreads(threads int) |
|
|
|
|
} |
|
|
|
|
if th, ok := s.engine.(threaded); ok { |
|
|
|
|
th.SetThreads(-1) |
|
|
|
|
} |
|
|
|
|
// Stop the block creating itself
|
|
|
|
|
s.miner.Stop() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Ethereum) IsMining() bool { return s.miner.Mining() } |
|
|
|
|
func (s *Ethereum) Miner() *miner.Miner { return s.miner } |
|
|
|
|
|
|
|
|
|