Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the mining process of bytom?

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

本篇内容主要讲解"bytom的挖矿流程是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"bytom的挖矿流程是什么"吧!

当我们以bytom init --chain_id=solonet建立比原单机节点用于本地测试时,很快会发现自己将面临一个尴尬的问题:余额为0。就算我们使用bytom node --mining开启挖矿,理论上由于我们是单机状态,本机算力就是全网算力,应该每次都能够挖到,但是不知道为什么,在我尝试的时候发现总是挖不到,所以打算简单研究一下比原的挖矿流程,看看有没有办法能改点什么,给自己单机多挖点BTM以方便后面的测试。

所以在今天我打算通过源代码分析一下比原的挖矿流程,但是考虑到它肯定会涉及到比原的核心,所以太复杂的地方我就会先跳过,那些地方时机成熟的时候会彻底研究一下。

如果我们快速搜索一下,就能发现在比原代码中有一个类型叫CPUMiner,我们围绕着它应该就可以了。

首先还是从比原启动开始,看看CPUMiner是如何被启动的。

下面是bytom node --mining对应的入口函数:

cmd/bytomd/main.go#L54-L57

func main() { cmd := cli.PrepareBaseCmd(commands.RootCmd, "TM", os.ExpandEnv(config.DefaultDataDir())) cmd.Execute()}

由于传入了参数node,所以创建Node并启动:

cmd/bytomd/commands/run_node.go#L41-L54

func runNode(cmd *cobra.Command, args []string) error { // Create & start node n := node.NewNode(config) if _, err := n.Start(); err != nil { // ...}

在创建一个Node对象的时候,也会创建CPUMiner对象:

node/node.go#L59-L142

func NewNode(config *cfg.Config) *Node { // ... node.cpuMiner = cpuminer.NewCPUMiner(chain, accounts, txPool, newBlockCh) node.miningPool = miningpool.NewMiningPool(chain, accounts, txPool, newBlockCh) // ... return node}

这里可以看到创建了两个与挖矿相关的东西,一个是NewCPUMiner,另一个是miningPool。我们先看NewCPUMiner对应的代码:

mining/cpuminer/cpuminer.go#L282-L293

func NewCPUMiner(c *protocol.Chain, accountManager *account.Manager, txPool *protocol.TxPool, newBlockCh chan *bc.Hash) *CPUMiner { return &CPUMiner{ chain: c, accountManager: accountManager, txPool: txPool, numWorkers: defaultNumWorkers, updateNumWorkers: make(chan struct{}), queryHashesPerSec: make(chan float64), updateHashes: make(chan uint64), newBlockCh: newBlockCh, }}

从这里的字段可以看到,CPUMiner在工作的时候:

可能需要用到外部的三个对象分别是:chain(代表本机持有的区块链),accountManager(管理帐户),txPool(交易池)

numWorkers:应该保持几个worker在挖矿,默认值defaultNumWorkers为常量1,也就是说默认只有一个worker。这对于多核cpu来说有点亏,真要挖矿的话可以把它改大点,跟核心数相同(不过用普通电脑不太可能挖到了)

updateNumWorkers:外界如果想改变worker的数量,可以通过向这个通道发消息实现。CPUMiner会监听它,并按要求增减worker

queryHashesPerSec:这个没用上,忽略吧。我发现比原的开发人员很喜欢预先设计,有很多这样没用上的代码

updateHashes: 这个没用上,忽略

newBlockCh: 一个来自外部的通道,用来告诉外面自己成功挖到了块,并且已经放进了本地区块链,其它地方就可以用它了(比如广播出去)

然而这里出现的并不是CPUMiner全部的字段,仅仅是需要特意初始化的几个。完整的在这里:

mining/cpuminer/cpuminer.go#L29-L45

type CPUMiner struct { sync.Mutex chain *protocol.Chain accountManager *account.Manager txPool *protocol.TxPool numWorkers uint64 started bool discreteMining bool wg sync.WaitGroup workerWg sync.WaitGroup updateNumWorkers chan struct{} queryHashesPerSec chan float64 updateHashes chan uint64 speedMonitorQuit chan struct{} quit chan struct{} newBlockCh chan *bc.Hash}

可以看到还多出了几个:

sync.Mutex:为CPUMiner提供了锁,方便在不同的goroutine代码中进行同步

started:记录miner是否启动了

discreteMining:这个在当前代码中没有赋过值,永远是false,我觉得应该删除。已提issue #961

wg和workerWg:都是跟控制goroutine流程相关的

speedMonitorQuit:也没什么用,忽略

quit:外界可以给这个通道发消息来通知CPUMiner退出

再回到n.Start看看cpuMiner是何时启动的:

node/node.go#L169-L180

func (n *Node) OnStart() error { if n.miningEnable { n.cpuMiner.Start() } // ...}

由于我们传入了参数--mining,所以n.miningEnable是true,于是n.cpuMiner.Start会运行:

mining/cpuminer/cpuminer.go#L188-L205

func (m *CPUMiner) Start() { m.Lock() defer m.Unlock() if m.started || m.discreteMining { return } m.quit = make(chan struct{}) m.speedMonitorQuit = make(chan struct{}) m.wg.Add(1) go m.miningWorkerController() m.started = true log.Infof("CPU miner started")}

这段代码没太多需要说的,主要是通过判断m.started保证不会重复启动,然后把真正的工作放在了m.miningWorkerController()中:

mining/cpuminer/cpuminer.go#L126-L125

func (m *CPUMiner) miningWorkerController() { // 1. var runningWorkers []chan struct{} launchWorkers := func(numWorkers uint64) { for i := uint64(0); i

< numWorkers; i++ { quit := make(chan struct{}) runningWorkers = append(runningWorkers, quit) m.workerWg.Add(1) go m.generateBlocks(quit) } } runningWorkers = make([]chan struct{}, 0, m.numWorkers) launchWorkers(m.numWorkers)out: for { select { // 2. case numRunning { launchWorkers(m.numWorkers - numRunning) continue } for i := numRunning - 1; i >

= m.numWorkers; i-- { close(runningWorkers[i]) runningWorkers[i] = nil runningWorkers = runningWorkers[:i] } // 3. case

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report