主页 > imtoken如何区分官网 > 矿叔科普——深度剖析挖矿逻辑与技术实现

矿叔科普——深度剖析挖矿逻辑与技术实现

imtoken如何区分官网 2023-02-09 07:39:45

btc客户端挖矿_b端客户c端客户的意思_btc挖矿软件安卓版

深入分析挖矿逻辑和技术实现。 挖矿是进行算法计算的过程。 从计算机和代码的角度来看,它是一个重复执行Hash函数并检测执行结果的具体过程。 和讨论算法一样,挖矿也是在采用POW共识机制的前提下讨论的。

深入分析挖矿逻辑和技术实现。 挖矿是进行算法计算的过程。 从计算机和代码的角度来看,它是一个重复执行Hash函数并检测执行结果的具体过程。 和讨论算法一样,挖矿也是在采用POW共识机制的前提下讨论的。

大家已经很清楚,挖矿是从CPU挖矿开始,过渡到GPU挖矿,最后演变成现在的ASIC(专业矿机)挖矿时代。 本文分析了逻辑设计和技术实现。 挖矿的进化是硬件进化的过程,也是软件进化的过程,尤其是软硬件对接协议的完善过程。 因此,本文直接将与挖矿相关的几个核心协议作为字幕,逐条展开讨论。

在查看文章时,我发现“矿工”一词使用含糊不清。 这种情况在英国文学中也类似。 在日常交流中,一般指拥有矿机的人。 本文关注区块链,挖矿程序或机器统称为矿工。

矿业

本节讨论挖矿原理。 首先分析比特币的区块头(Blockheader)结构。 我们说挖矿的本质就是执行Hash函数的过程,而Hash函数是单输入单输出的函数。 输入数据是区块头。 比特币区块头中有 6 个字段:

int32_t n版本; //版本号,4字节

uint256 hashPrevBlock; //上一个区块的区块头哈希值,32字节

uint256 hashMerkleRoot; // 该区块包含的所有交易结构的 Merkle 根,32 字节

uint32_t nTime; //Unix时间戳,4字节

uint32_t nBits; //记录这个区块的难度,4字节

uint32_t nNonce; //随机数,4字节

如上,每次比特币挖矿都是对这80个字节进行两次连续的SHA256运算(SHA256D),运算结果是固定的32个字节(二进制256位)。

b端客户c端客户的意思_btc客户端挖矿_btc挖矿软件安卓版

以上6个字段的情况不同,

nVersion,块版本号,只会在升级时改变。

hashPrevBlock,由前一个块决定。

nBits,由全网共同决定btc客户端挖矿,每2016个区块重新调整一次,调整算法是固定的。

所以,以上三个字段可以理解为固定的,对每个矿工来说都是一样的。 矿工可以自由调整的地方就是剩下的3个字段,

nNonce,提供 2^32 个可能的值

nTime,其实这个字段能提供的取值空间是非常有限的,因为合理出块时间是有一个范围的,这个范围是根据上一个出块时间来确定的,如果太早或者太超前上一个块时间,它会被其他节点拒绝拒绝。 值得一提的是,后一个区块的出块时间略早于前一个区块的时间,这是允许的。 一般来说,矿工会直接使用机器当前的时间戳。

hashMerkleRoot,理论上提供了2^256种可能性。 该字段的变化来自于添加或删除包含在区块中的交易,或更改顺序,或修改 Coinbase 交易的输入字段。

根据Hash函数的特点,即使三个字段中的任何一个发生变化,都会引起Hash运算结果的巨大变化。 在 CPU 挖矿时代,搜索空间主要由 nNonce 提供。 在矿机时代,nNonce提供的4个字节远远不够,搜索空间转向hashMerkleRoot。

btc挖矿软件安卓版_b端客户c端客户的意思_btc客户端挖矿

比特币挖矿的逻辑过程如下:

1. 打包交易,检索待确认的交易内存池,选择待入块的交易。 矿工可以任意选择,甚至不选择(空块),因为每个块都有容量限制(目前1M),所以矿工不能无限选择。 对于矿工来说,最合理的策略是先将待确认的交易集合按照手续费排序,然后从高到低尽量包含最多的交易。

2. 构建Coinbase,确定区块包含的交易集后,即可统计出该区块的交易总手续费。 结合产出规则,矿工可以计算出自己在该区块的收益。

3.构造hashMerkleRoot,为所有交易构造Merkle数。

btc挖矿软件安卓版_btc客户端挖矿_b端客户c端客户的意思

4.填写其他字段以获得完整的区块头。

5.哈希运算,对区块头进行SHA256D运算。

6、如果验证结果遇到困难,将向全网广播,挖出下一个区块; 如果不满足难度,根据一定的策略改变上述其中一个字段,再进行Hash计算和验证。

合格区块条件如下:

SHA256D(Blockherder) < F(nBits)

其中SHA256D(Blockherder)为挖矿结果,F(nBits)为难度对应的目标值,均为256位,均视为大整数,直接比较大小判断是否满足难度要求。

为了节省区块链存储空间,将256位的目标值通过一定的变换和无损压缩存储在32位的nBits字段中。 具体转换方法是拆分使用4个字节的nBits。 第一个字节表示右移的位数,用V1表示,后3个字节记录数值,用V3表示,则:

另外,难度是有下限的,也就是说有一个最大值。 比特币的最小难度值为nBits=0x1d00ffff,对应的最大目标值为:

0x00000000FFFF0000000000000000000000000000000000000000000000000000

因此,挖矿可以直观地比作抛硬币。 例如,有256枚硬币,给定的数字是1、2、3……256。 每进行一次哈希运算,就如同抛硬币一样。 同时抛出 256 个硬币。 所有编号在 n 之前的硬币都是正面朝上的。

设置生成

Setgenerate 协议接口代表了 CPU 挖掘的时代。

中本聪在他的论文中描述了“1 CPU 1 Vote”的理想数字民主概念。 在初始版本中,客户端具有挖矿功能。 客户端挖掘非常简单。 当然,需要先完成同步数据,才能进行挖矿。 有很多算力很低的山寨币,还是直接用客户端挖的。 有两种方式开始挖矿:

1)在配置文件中设置gen=1,然后启动客户端,节点会自行开始挖矿。

b端客户c端客户的意思_btc客户端挖矿_btc挖矿软件安卓版

2)客户端启动后,使用RPC接口setgenerate控制挖矿。

如果使用经典QT客户端,点击“帮助”菜单,打开“调试窗口”,在“控制台”中输入以下命令:setgenerate true 2,然后回车,客户端开始挖矿,数量behind代表挖矿线程如果想关闭挖矿,在控制台使用如下命令:setgenerate false,可以使用getmininginfo命令查看挖矿状态。

节点挖矿流程:

btc挖矿软件安卓版_b端客户c端客户的意思_btc客户端挖矿

构造区块,初始化区块头的各个字段,计算Hash并对区块进行验证,如果失败则自增nNonce,然后进行计算验证等。 在CPU挖矿时代,nNonce提供的4字节搜索空间完全够用(4字节有4G的可能,单核CPU的SHA256D算力一般在2M左右)。 事实上,nNonce 只是在遍历了两个字节后才返回。 转到重构块。

找份工作

getwork协议代表GPU挖矿时代。 需求主要是由于挖矿程序与节点客户端的分离,以及区块链数据与挖矿组件的分离。

使用客户端节点直接挖矿需要同步完整的区块链,数据和程序紧密结合。 也就是说,如果有多台电脑进行挖矿,每台电脑都需要同步一个单独的区块链数据。 这实际上是没有必要的。 对于矿工来说,至少一个全节点就够了。 同时,GPU挖矿时代的到来也需要一种协议来与客户端节点进行交互。

getwork的核心设计思想是:

区块由节点客户端构建,然后将区块头数据交给外部挖矿程序。 挖矿程序遍历nNonce进行挖矿,验证通过后返回给节点客户端。 节点客户端验证通过后向全网广播。

如前所述,区块头一共有80个字节。 由于没有待确认的区块链数据和交易池,nVersion、hashPrevBlock、nBits和hashMerkleRoot这4个字段必须由节点客户端提供共计72字节。 挖矿程序主要是增量遍历nNonce,必要时可以微调nTime字段。

对于显卡GPU,不用担心nNonce缺少4字节搜索空间,而且挖矿程序从节点客户端拿到一条数据后,不要工作太久,否则就是这个区块很可能已被其他矿工占用。 人挖,继续挖只能做无用功。 对于比特币来说,虽然它被设计为每 10 分钟出一个块,但一个好的策略应该是在几秒钟内重新向节点申请新的挖矿数据。 对于显卡来说,运行SHA256D的算力一般在200M~1G之间。 nNonce提供了4G的搜索空间,也就是说再好的显卡也能支持4秒左右。 调整一次nTime可以再挖4秒。 这一次绰绰有余。

节点提供RPC接口getwork,有一个可选参数。 如果没有参数,就是申请挖矿数据。 如果有参数,就是提交挖出的区块数据。

不带参数调用getwork,返回数据如下:

b端客户c端客户的意思_btc挖矿软件安卓版_btc客户端挖矿

{

“中间状态”:“9226a024e0b77f61d49fd5ffdf828c6b5c4330c61ea2778c606a8e49d4ad8bd6”,

“data” :”00000002e9337bac28ee28a949d2140f9fb0a0ab740acfd739d7bcf67ca31c2301db858ad2ca54d92c8c1cded715922c4df2b07d9f10fa1a6cf3db7e949b320615761ed4581c76f21b12d87500000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000″,

“hash1”:“000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

“目标”:“0000000000000000000000000000000000000000000000075d8120000000000”

}

数据字段

一共128字节(80个块头字节+48个完成字节),因为SHA256将输入数据分成固定长度的切片,每个切片为64字节,输入总长度必须是64字节的整数倍,输入length一般不满足要求,按照一定的规则在metadata末尾完成数据。 其实对于挖矿来说,补全数据是固定的,这里不需要提供。 外部挖矿软件可以自行完成。 连nNonce字段都不需要提供,数据只需要提供至少前76个字节即可。 nTime字段也是必不可少的,外部挖矿程序需要参考节点提供的出块时间来调整nTime。

目标领域

即当前区块难度目标值,采用小端字节序,需要翻转后才能使用。

其实对于外部挖矿程序来说,data和target这两个字段就可以正常挖矿,但是getwork协议充分考虑了各种情况,尽量帮助外部挖矿程序做力所能及的事情,额外提供了两个字段,data字段返回完整补全数据也是基于这个思路。

中州油田

如上所述,SHA256 对输入数据进行拆分。 矿工拿到数据后,第一次分裂(前64字节)是固定的,midstate就是第一次分裂的计算结果。 该节点有助于计算 Out。

因此,借助midstate字段,外部挖矿程序仅用44字节的数据就可以正常挖矿:32字节的midstate + 第一个分片中剩余的12(76-64)字节的数据。

b端客户c端客户的意思_btc客户端挖矿_btc挖矿软件安卓版

Hash1字段

比特币挖矿每次都需要连续执行两次 SHA256。 第一次执行的结果是32字节,需要补充32字节的数据,组成64字节作为第二次执行SHA256的输入。 hash1为补全数据,同理hash1也是固定的。

外部挖矿程序挖出合格区块后,再次调用getwork接口,将修改后的数据字段提交给节点客户端。 节点客户端返回的数据也必须是128字节。

每次外部调用不带参数的getwork,节点客户端都会构造一个新块。 在返回数据之前,新区块必须完全存储在内存中,并使用 hashMerkleRoot 作为唯一标识符。 节点使用一个Map来存储所有构造的Block,当下一个block已经被别人挖出后,立即清除Map。

getwork接收到一个参数后,首先从参数中提取出hashMerkleRoot,在Map中找到之前保存的区块,然后从参数中提取出nNonce和nTime填充到区块对应的字段中,即可对区块进行验证. 如果难度满足要求,说明已经挖出一个区块,节点向全网广播。

getwork协议是最早版本的挖矿协议,实现了节点与挖矿的分离。 经典的 GPU 挖矿驱动 cgminer、sgminer 和 cpuminer 都使用 getwork 协议进行挖矿。 Getwork + cgminer一直是非常经典的组合。 许多新算法上线后,很快就被移植到cgminer中。 即使是现在,除了 BTC 和 LTC 之外,许多其他山寨币仍在使用 getwork 协议进行挖矿。 矿机出现后,挖矿速度有了很大的提升,目前比特币矿机算力已经达到10T/s的水平。 而getwork只为外部挖矿程序提供了32字节共计4G的搜索空间。 如果继续使用getwork协议,矿机需要频繁调用RPC接口,显然是行不通的。 现在BTC和LTC节点都禁用了getwork协议,转而使用更新更高效的getblocktemplate协议。

获取块模板

getblocktemplate协议诞生于2012年年中,当时矿池已经出现。 矿池使用getblocktemplate协议与节点客户端交互,使用stratum协议与矿工交互。 这是最典型的矿池建设模式。

与getwork相比,getblocktemplate协议最大的不同在于getblocktemplate协议允许矿工自行构建区块。 这样,节点和挖矿就完全分离了。 对于getwork来说,区块链是黑暗的,getwork对区块链一无所知,他只知道修改data字段的4个字节。 对于getblocktemplate来说,整个区块链是透明的btc客户端挖矿,getblocktemplate掌握了区块链上所有与挖矿相关的信息,包括需要确认的交易池,getblocktemplate可以选择包含在区块中的交易。

getblocktemplate 开发出来之后,就不是一成不变的了。 客户端在后续的每个版本都进行了升级和改动,主要是增加了一些字段,但核心概念和核心字段没有变化。 目前比特币客户端返回的数据如下。 考虑到空间限制,交易字段中只保留一个交易数据。 事实上,根据目前的实际情况,交易池中有数万笔交易需要实时确认。 目前blocks基本是满的(1M容量限制),再加上额外的信息,所以每次调用getblocktemplate基本上返回1.5M左右的数据,和getwork的几百字节不一样。

btc挖矿软件安卓版_b端客户c端客户的意思_btc客户端挖矿

加入麦大叔的知识星球

你也会得到

如何加入