比特币POW难度调节分析

比特币白皮书在工作量证明章节中解释了工作量证明(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要处理,可能为了代码干净起见就不去特殊处理了,其实也没啥影响

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据小魔方

动态地理信息可视化——leaflet在线地图简介

最近稍微涉猎了一下leaflet这个包,突然感到发现了动态可视化的新大门,这个包所提供的地图类型、动态效果、图层展示方式都大大扩展了ggplot作图系统的在数据...

3304
来自专栏NewbieWeb

ThreeJS的DeviceOrientationControls源代码解析

在学习ThreeJS和WebGL的过程中想着实现一个基于手机陀螺仪的3D环绕视角的例子,遇到了很多困难,一直都没有完成;后来发现ThreeJS中已经有了类似的例...

581
来自专栏杨建荣的学习笔记

对于随机数的一些分析

多年前我朋友圈的一个朋友公司年会抽奖出现了下面的这样一幕:CTO现场review代码。本来带着一丝娱乐精神,结果被无限放大了。所以年会中大家都会很自然想revi...

3218
来自专栏小尘哥的专栏

能买几颗糖??

Q:又来买糖,兜里装了一块零一分,即(¥1.01),,糖果也涨价了,变成0.56元一个,问买一个之后兜里还剩多少钱?

932
来自专栏小樱的经验随笔

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 9...

2856
来自专栏数说工作室

哈希函数的套路 | 文本分析:大规模文本处理(1)

这个系列打算以文本相似度为切入点,逐步介绍一些文本分析的干货。 第一篇中,介绍了文本相似度是干什么的; 第二篇,介绍了如何量化两个文本,如何计算余弦相似度,穿...

4148
来自专栏工科狗和生物喵

【机器视觉与图像处理】基于MATLAB的角度计算

正文之前 最近新开了一门课,我十分感兴趣,或者是说老早就想接触类似方面的学习,但是一直没有真正着手,所以说,其实上课还是很有必要的,很多时候你想做的事情但是你根...

3399
来自专栏深度学习之tensorflow实战篇

python—结巴分词的原理理解,Hmm中的转移概率矩阵和混淆矩阵。

结巴分词的过程: jieba分词的python 代码 结巴分词的准备工作 开发者首先根据大量的人民日报训练了得到了字典库、和Hmm中的转移概率矩阵和混...

4105
来自专栏ml

2015编程之美(资格赛)--基站选址

题目3 : 基站选址 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建...

3235
来自专栏圣杰的专栏

DDD理论学习系列(5)-- 统一建模语言

1.引言 上一节讲解了领域模型,领域模型主要是将业务中涉及到的概念以面向对象的思想进行抽象,抽象出实体对象,确定实体所对应的方法和属性,以及实体之间的关系。然后...

2807

扫码关注云+社区