主页 > 官网imtoken钱包苹果版下载 > 以太坊挖矿返回null源码分析
以太坊挖矿返回null源码分析
在以太坊1.7.3版本中,无论是dev环境还是公链环境,在控制台执行miner.start()总是返回null,而不是预期的true。 为什么是这样? 本文将带你从源码中寻找原因。 在这个过程中,我们会学到更多的底层知识。
采矿入门程序
先看调用挖矿的程序。 在控制台中,我们执行:
miner.start()
##或
miner.start(n)
参数n是系统CPU的核心数。 go语言中对应的方法是:
miner.Start(threads *rpc.HexNumber) (bool, error)
该方法对应的api调用在eth/api.go文件中,具体代码如下:
// Start the miner with the given number of threads. If threads is nil the number
// of workers started is equal to the number of logical CPUs that are usable by
// this process. If mining is already running, this method adjust the number of
// threads allowed to use.
func (api *PrivateMinerAPI) Start(threads *int) error {
// Set the number of threads if the seal engine supports it
if threads == nil {
threads = new(int)
} else if *threads == 0 {
*threads = -1 // Disable the miner from within
}
type threaded interface {
SetThreads(threads int)
}
if th, ok := api.e.engine.(threaded); ok {
log.Info("Updated mining threads", "threads", *threads)
th.SetThreads(*threads)
}
// Start the miner and return
if !api.e.IsMining() {
// Propagate the initial price point to the transaction pool
api.e.lock.RLock()
price := api.e.gasPrice
api.e.lock.RUnlock()
api.e.txPool.SetGasPrice(price)
return api.e.StartMining(true)
}
return nil
}
通过这段代码我们可以分析出以下几点:
- 挖矿时传递的参数是系统CPU的核心数,可以指定。 如果未指定,则默认为系统的核心数。
- 如果您已经在挖矿,请执行挖矿程序以更改使用的 CPU 内核数。
- 如果系统已经在挖矿,返回结果为nil(null)。
- 如果没有开始挖矿,执行api.e.StartMining(true)方法。
执行挖矿
看一下api.e.StartMining(true)方法对应的代码内容:
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)
}
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 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 noone will ever hit this path, whereas marking sync done on CPU mining
// will ensure that private networks work in single miner mode too.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
}
go s.miner.Start(eb)
return nil
}
通过上面的代码我们可以分析得到:
- 成功挖矿的前提是存在有效的coinbase账户;
- 即使挖矿成功(执行go s.miner.Start(eb))以太坊年底停止挖矿以太坊年底停止挖矿,该方法返回的结果也是nil(null)。
因此,通过以上两段代码分析,在这个版本中,无论挖矿成功还是挖矿失败,返回的结果都是null。 这就是为什么在这个版本中无法通过返回值判断是否开启挖矿成功。
挖矿代码渐进分析
仔细看看 s.miner.Start(eb) 中的代码:
func (self *Miner) Start(coinbase common.Address) {
atomic.StoreInt32(&self.shouldStart, 1)
self.worker.setEtherbase(coinbase)
self.coinbase = coinbase
if atomic.LoadInt32(&self.canStart) == 0 {
log.Info("Network syncing, will start miner afterwards")
return
}
atomic.StoreInt32(&self.mining, 1)
log.Info("Starting mining operation")
self.worker.start()
self.worker.commitNewWork()
}
这段代码的基本实现是设置一些相关的参数项,然后开始挖矿。 通过这段代码,我们可以获取到一条日志信息来判断是否开始挖矿——“Starting mining operation”,所以如果日志中有这行输出,可以作为确认挖矿已经开始的必要和不充分条件开始了。
停止功能
对应的停止函数不同:
// Stop the miner
func (api *PrivateMinerAPI) Stop() bool {
type threaded interface {
SetThreads(threads int)
}
if th, ok := api.e.engine.(threaded); ok {
th.SetThreads(-1)
}
api.e.StopMining()
return true
}
显然,无论stop是否执行成功,或者当前是否在挖矿,只要执行了stop,就会一直返回true。
总结
通过上面的分析,我们得到了一些经验和常识,也告诉我们在这个版本中调用miner.start()返回null并没有任何意义。 挖矿可能已经开始,也可能没有。
原文链接: