【区块链|以太坊挖矿返回null源码分析】在以太坊版本1.7.3中,无论是dev环境或是公链环境在console中执行miner.start()始终返回null,而不是期待的true。这是为什么呢?这篇文章就带大家从源码中找找原因。在这个过程中我们会了解到更多底层的知识。挖矿入口程序 首先看一下调用挖矿的程序,在console中我们执行的是:
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 = coinbaseif 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函数 与之相对应的stop函数就不一样了:
// 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并不能说明什么,有可能已经开始挖矿,有可能没有。
原文链接:http://www.choupangxia.com/topic/detail/12
延伸阅读:
《以太坊同步模式源码解析》
更多资讯 **获取更多资讯,请关注微信公众号:程序新视界。或加入QQ技术交流群:659809063。个人博客:www.choupangxia.com
本人诚接以太坊相关研发及技术支持(以太坊接口封装&代币开发等),如有需要请联系QQ:541075754。非诚勿扰。**
文章图片
获得一对一技术咨询请扫码加入知识星球(小密圈)
文章图片
推荐阅读
- 推动NFT走出监管困境,BSN推出支持NFT基础设施网络
- 腾讯|SaaS的收入模型有哪些(终于有人讲明白了)
- 就业方向上什么才是最重要的(--- 来自程序猿的迷茫。(C++?Java?or算法?))
- 区块链中加密货币的含义
- 波场万倍潜力币HYL23号21:09分 正式上线JustSwap
- 《瀚兰房地产开发区块链应用及案例分享》BSN培训精华回顾
- 对联盟链而言,跨链协议为什么重要()
- 区块链能够应用在哪些行业
- BSN区块链服务网络中密钥托管模式和公钥上传模式有啥区别()
- 币圈人物传|币圈大佬今何在 唯有一诺正当时