前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >比特币POW难度调节分析

比特币POW难度调节分析

作者头像
happy123.me
发布2018-06-04 12:30:22
2K0
发布2018-06-04 12:30:22
举报
文章被收录于专栏:乐享123

比特币白皮书在工作量证明章节中解释了工作量证明(PoW)的方式:

我们在区块中补增一个随机数(Nonce),这个随机数要使得该给定区块的随机散列值出现了所需的那么多个0。我们通过反复尝试来找到这个随机数,直到找到为止,这样我们就构建了一个工作量证明机制。只要该CPU耗费的工作量能够满足该工作量证明机制,那么除非重新完成相当的工作量,该区块的信息就不可更改。由于之后的区块是链接在该区块之后的,所以想要更改该区块中的信息,就还需要重新完成之后所有区块的全部工作量。

那这个随机数难度值是怎么产生的呢?

原理是简单的,但是细节总是需要穷根究底。

比特币难度值Difficulty

难度值在区块中并不记录,仅仅是为了人类直观感受解题难度而演变出的一个浮点数。难度每2016个区块改变一次,公式如下:

1

diffculty = difficulty_1_target / currentTarget

此处的 difficulty_1_target 为一个常数,非常大的一个数字。表示矿池挖矿最大难度。目标值越小,区块生成难度越大。区块中存储的是这个名为target的值。

难度值如何存储在区块中的

在区块中存储的是Target,但是将Target经类似于浮点数的一种压缩表示法,字段为nbits。例如,如果区块bits记录为0x1b0404cb,那么他表示的十六进制的Target值为:

1

0x0404cb * 2**(8*(0x1b - 3)) = 0x00000000000404CB000000000000000000000000000000000000000000000000

在计算时,后面3个字节0x0404cb作为底,前面1字节0x1b表示次方数。具体压缩过程如下:

  • 将数字转换为256进制数
  • 如果第一位数字大于127(0x7f),则前面添加0
  • 压缩结果中的第一位存放该256进制数的位数
  • 后面三个数存放该256进制数的前三位,如果不足三位,则后面补零
例如,将数字1000压缩,先转换为256进制数

1

1000 = 0x03 * 256 + 0xe8 * 1

那么是由两个数字构成:

1

03 e8

第一个数未超过0x7f,则不需填0,但长度两位低于三位,在后面补零,最终表示为:0x0203e800

等等,我有点晕了,为什么要采取这种绕弯的存储方式呢?

  • 比特币的工作量证明本质是计算一个256bits的hash值,并保证这个值小于target,表示为公式如下: SHA256(SHA256(区块头)) < Target
  • 初始Target,即difficulty_1_target设置为0x00000000FFFF0000000000000000000000000000000000000000000000000000,此时难度为1
  • Target是一个256位的很大的数,对这个数进行乘除运算需要特殊的库来处理,所以中本聪考虑用一个32位的数来近似表示Target
  • 256 / 32 = 8, 28 = 256,因此我们需要用256进制来表示Target,256进制的运算规则如上所述
  • 那么初始Target其实可以表示为0x1D00FFFFFF,解压验证一下: 0x00ffff *256** (0x1d - 3) = ff ff 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  • 0x1D00FFFFFF 这个值可以称为nbits,就是存储在区块中的原始值,通过nbits可以推算当前Target,通过当前Target及初始Target可以推算当前难度

难度如何调节

目标值计算公式如下,但在实际计算时有些特别处理,将目标值控制在一定范围内。

1

新目标值= 当前目标值 * 实际2016个区块出块时间 / 理论2016个区块出块时间(2周)。

  1. 判断是否需要更新目标值(2016的整数倍),如果不是则继续使用最后一个区块的目标值
  2. 计算前2016个区块出块用时
  3. 如果用时低于半周,则按半周计算。防止难度增加4倍以上。
  4. 如果用时高于8周,则按8周计算。防止难度降低到4倍以下。
  5. 用时乘以当前难度, 再除以2周
  6. 如果超过最大难度限制,则按最大难度处理

代码参考这里:

https://github.com/memoryboxes/bitcoin/blob/a1c3d8f14dca6a86fa103d86ef125e95372f860c/src/main.cpp#L857

知道nbits,如何推算全网算力

  • nbits为0x1b0404cb时,难度为: 0x00000000FFFF0000000000000000000000000000000000000000000000000000 / 0x00000000000404CB000000000000000000000000000000000000000000000000 = 16307.420938523983
  • 为了找到新区块,该区块的target值必须小于目标target值,实际上是一个在0到2256-1之间的随机数,难度1的偏移量是: 0xffff * 2^208
  • 难度D的偏移量是 (0xffff * 2^208)/D
  • 在难度D下,为了找到新区块,我们预期要计算的HASH数量是 D * 2^256 / (0xffff * 2^208)
  • 难度的设定,是为了以每10分钟一个区块的产生速度产生2016个区块,因而我们在600秒内计算 (D * 248 / 0xffff) 个HASH,这就意味着产生2016个区块的网络HASH速率(算力)是 D * 2^48 / 0xffff / 600 可以进一步简化为: D * 2^32 / 600
  • 2018-02-12 21:00:00(UTC+8), 难度值D为2,874,674,234,415; 此时全网算力为20.75EH/S
  • 如果我有一台蚂蚁S9,算力13T/S,那么一个区块周期(10分钟)的期望BTC收益为12.5 * 13T / 20.75EH

一点小TIPS

  • 难度为1时,目标target在比特币客户端中表示为

1

0x00000000FFFF0000000000000000000000000000000000000000000000000000

但是在绝大部分矿池里面表示为

1

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

这样挖矿的时候,挖矿软件显示的难度和比特币客户端api调用算出来的难度有微小差别,可以忽略。这个其实时早期矿池实现的时候找方便造成的不统一,因为比特币客户端判断HASH合法性的时候用的是nbits来判断,所以不影响最终计算结果

  • 现有的算法中,难度值每2016个区块调整一次,但新的难度值不需要与难度“1”进行比较运算,而是根据前2015个块的出块时间来计算,所以严谨的计算公式为:

1

difficulty = [prev_target] * 【前2015个区块生成所用的时间】 / 1209600 (按标准每10分钟出一个块,2016个块所需要的秒数)

为啥?就是中本聪早期的代码比较糙,他在循环的时候因为还有一个genius block要处理,可能为了代码干净起见就不去特殊处理了,其实也没啥影响

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 比特币难度值Difficulty
  • 难度值如何存储在区块中的
    • 在计算时,后面3个字节0x0404cb作为底,前面1字节0x1b表示次方数。具体压缩过程如下:
      • 例如,将数字1000压缩,先转换为256进制数
    • 等等,我有点晕了,为什么要采取这种绕弯的存储方式呢?
    • 难度如何调节
    • 知道nbits,如何推算全网算力
    • 一点小TIPS
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档