《比特币挖矿难度精讲供参考》由会员分享,可在线阅读,更多相关《比特币挖矿难度精讲供参考(22页珍藏版)》请在金锄头文库上搜索。
1、比特币主链上,平均每十分钟会出一个块。随着数字货币的发展,参与的 miner 数量与日俱增,挖矿技术日新月异,全网的算力也是以惊人的速度增长。BTC 中为了保证主链平均的高度增加速度依然维持最初设定,进而设置了挖矿难度调整的功能。深入理解挖矿难度的概念,以及挖矿难度调整的方案,对开发人员以及 miner 都很重要,因为挖矿难度设置不合理可能会导致全网出块速度极不稳定。本文将详细介绍 BTC&BCH 挖矿难度及调整方案,我们先从 PoW 算法讲起。1、PoW 算法PoW (Proof-of-Work)工作量证明算法是一种对应服务与资源滥用、或是阻断服务攻击的经济对策。一般是要求用户进行一些耗时适
2、当的复杂运算,并且答案能被服务方快速验算,以此耗用的时间、设备与能源做为担保成本,以确保服务与资源是被真正的需求所使用。PoW 算法具有:去中心化,单向,随机性,目标难度易调整等特点,所以现在包括 BTC,BCH 在内的很多币种都采用了 PoW 共识机制。从实现上来说,PoW 算法的输入为任意长度,输出为固定长度,比如通常使用 SHA256 算法对应输出 256-bit。在挖矿过程中 miner 用 PoW 算法计算整个块头的 hash 值,由于 SHA256 的特性:块头任意一位发生变化,得到的 hash 值会变得完全不一样,而且大小变化方向不确定。于是,我们比较 hash 值是否小于某个值
3、(实际上这个值是保存在块头中的 nBit解压后的 current_target 值)来判断是否满足要求;如果小于,则广播这个区块;如果不小于,则按照当前挖矿节点的规则改变块头中可以改变的值,然后再次计算块头 hash 值,以此往复,直到结果小于目标值。由此可知,current_target 值越小,满足挖矿要求的概率就越小,挖矿难度就越大。2、块头 & Coinbase 交易块头的生成: 当 miner 开始新一轮打包之后,首先会创建一个空的块,块结构分为块头以及块信息两部分。先打包块信息,再根据块信息填充块头。首先看一下已经成功打包的块。下图是写本文稿时截取最新的 BTC block 详情。
4、块信息 存放的是从 mempool 里取出来的一系列交易信息,miner 并以此创建了一个 Merkle Tree,交易信息的 hash 值作为 leaf,最终生成的 Merkle Root 将填到块头里。值得注意的是,交易列表中的第一个是一个非常独特的交易:Coinbase Transaction。Coinbase Transaction 与普通交易主要的区别有:1) Coinbase Transaction 不消耗 UTXO2) input 只有一个,叫做 Coinbase3) output 的 addresss 为 miner 的 btc/bch 地址4) value 由挖矿奖励和交易费
5、组成5)更值得注意的是 input 中没有 Unlocking-script,取而代之的是 Coinbase Data (这部分数据包含 Extra Nonce,在挖矿难度非常高时,将起非常重要的作用)Coinbase 交易 input 的结构如下:Coinbase data,该字段数据长度范围为 2-byte100-byte:block height 起初 Coinbase 是不包含块高度信息,由于重复交易的问题出现,诞了 BIP30,随后第二套解决方案 BIP34)。BIP34 规定 Coinbase data 最高字节表示用于表示块高度的数据段的字节数,接下来的字节以端法表示具体的块高度
6、,创世块的高度为 0。例如:2013-12-28 BTC 的一个块的 Coinbase 解析中 coinbase data 为 0x03443b04.,则块高度用 16 进制表示为 0x043b44,十进制为 277316;extra nonce 作为中间字段,将会在后续提及的 Extra Nonce Solution 详细说明作用;上图 Coinbase data 中用以结尾的/P2SH/是 12 年 miner 进行投票支持 BTC 是采用 BIP16 还是 BIP17 的产物,现已弃用。(众所周知,BIP16 P2SH 获得了更多票数,被 BTC 采用)在交易信息聚合完毕得到了 Merk
7、leRoot 之后,接下来填充区块头。块头结构如下(其中 nBit 就是 PoW 小节提到的 current-target 的压缩版):区块头 80-byte,一共 6 个字段:1. 版本号,允许改变但不推荐2. 前一个块的 hash 值,不允许改变3. MerkleRoot 的 hash 值,用于存块信息里的交易的 Merkle Tree 的 root 节点的值,允许改变(改变 coinbase 中 input 中的值)4. 时间戳,允许基于 MTP11 进行调整改变5. nonce,用于 PoW 算法的随机值,允许改变6. nBit,PoW 算法结果必须小于这个数对应的 current_t
8、arget 才能算块打包成功。这个值是在每一个块开始打包之前就确定了,不允许改变块头中 80 bytes 任意一个值发生改变,PoW 的 Hash 结果就会发生改变。3、挖矿难度及难度调整理解了 PoW 运算以及运算结果可能受哪些个因素影响,接下来了解一下我们要满足的难度要求是什么。挖矿难度的描述可以认为有三种形式,difficulty (难度值,浮点数),current_target (当前目标值,256-bit),nbits (32-bit);形式不同其实实质是表达的同一个难度要求,而且这个难度要求在每个块打包前就确定了。difficulty 不写在区块中,而是以浮点数的形式展现,给人直观
9、的感受难度程度。 difficulty = difficulty_1 / current_target;difficulty_1 为常数:0x00000000ffff0000000000000000000000000000000000000000000000000000创世块的 current_target = difficulty_1,所以创世块的 difficulty = 1.0。nbits 就是区块头 nBits 字段的值,用长度为 32-bit 的数值表示 256-bit 的数值,是需要牺牲一定精度的 , 可以理解它为压缩后的 current_target。在计算 current_ta
10、rget 时,我们先转换为二进制然后用公式(a)来计算 256-bit 的 current_target。(值得注意的是:current_target 是一个无符号 256-bit 的值,之所以设置一个 Sign 字段,是为了与 bitcoind 代码保持一致,保留符号位参考的是 IEEE 浮点型表示法,其实是无用的)This compact form is only used in bitcoin to encode unsigned 256-bit numbers which represent difficulty targets, thus there really is not a
11、need for a sign bit, but it is implemented here to stay consistent with bitcoind.计算 current_target 的公式为:例如 nBits = 0x180192d4,current_target = 0x192d4 * 2 (8 * (0x18 - 3)(最高 16 位为零)相较于创世块,current_target 减小了大约 1/(236) 倍,difficulty 增加了大约 7184404942701 倍。为了维持平均每十分钟生成一个块的频率,BTC 中 current_target 设计为了一个动态
12、值,current_target 根据全网算力的改变而做一些相应的调整,这就是挖矿难度调整。在 BTC 中,挖矿难度调整 idea 为:以 2016 个块(两周)为一个周期,每个周期根据前一个周期的实际耗时与理论耗时之间的差别进行调整。新目标值 = 当前目标值 * 实际 2016 个区块出块时间 / 理论 2016 个区块出块时间 (2 周)。方案具体逻辑是:1. 判断是否需要更新目标值 ( 2016 的整数倍),如果不是则继续使用最后一个区块的目标值2. 计算 2016 个块实际使用时长:如果用时低于半周,则按半周计算,防止难度增加 4 倍以上;如果用时高于 8 周,则按 8 周计算。防止难
13、度降低到 4 倍以下。3. 实际使用时长乘以当前难度,再除以 2 周4. 如果超过最大难度限制,则按最大难度处理计算过程,Go 代码如下 :4、BCH 难度调整BCH 诞生于区块高度 478558,两条链都采用相同 PoW 共识算法(平均 10 分钟生成一个块),所以 miner 可以任意在 BTC 与 BCH 间切换,但由于通常 BCH 全网算力只占有 BTC 的 7% 左右,当 BCH 获利大于 BTC 的时候,大量原 BTC miner (尤其是大的矿场)会切入 BCH,一段时间后随着算力提升,难度值也会提升,miner 会纷纷离开切回 BTC,算力降低,难度居高不下将导致接下来出块十分
14、困难。倘若继续沿用 BTC 的难度调整方案,BCH 将无法保证出块速率稳定在平均 10mins/block,事实上 BCH 的难度值调整算法已经先后经历了两种,第一种是紧急难度调整规则(EDA),目前使用的是难度调整规则(DAA)。紧急难度调整规则(EDA)EDA 是在沿用 BTC 难度调整算法的基础上,增加了一个 Emergency Difficulty Adjustment 处理方案,主要是针对于出块缓慢情况及时降低难度。算法具体逻辑是:对于高度为 2016 倍数的就拿到此高度前 2016 块的 blocktime,沿用 BTC 难度调整方案;对于高度非 2016 倍数的块,则计算生成前六
15、块的块总共耗时是否超过 12h,如果超过则降低挖矿难度 20%。 具体实现代码如下:难度调整规则(DAA)然而在运行三个多月中,EDA 表现不尽如人意(非常差),由于其应对出块速率过高并没有做相应及时调整而依赖于 BTC 原有的 2016 块一次的调整机制,所以在面对算力波动时表现并不是很好。本人分别截取了三段典型数据,为了对上述观点进行说明:1. 2017.8.26 号的算力攻击,2017.8.27 号大算力切走之后出块困难,23 小时只出 13 个块,导致连续调整(降低)挖矿难度。1. 2017.10.2 由于矿工趋利性导致 BCH 网络算力突然增加,仅仅 30mins 就出了 20 多区
16、块。1. 用一个更直观的数据,BTC 和 BCH 的起跑线都是一样的,都是 2017 年 8 月 1 日,高度同为 478,558,而截止到 17 年 11 月 12 日晚 BTC 挖到了 494,079 高度,而 BCH 挖到了 503,815 高度,多了将近 10000 个块。所以优化 BCH 的难度调整方案刻不容缓,在得到几大矿池的稳定算力支持后,17 年 11 月 13 日,BCH 再次升级,就是为了优化 EDA。BCH 开发团队(并非社区)收到几份 DAA,最终采用了 BTCABC 开发团队 Amaury Sechet 的 DAA 提案。 这份 proposal 的 ieda 可以用一句俗语来形容魔高一尺,道高一