主页 > imtoken苹果版下载官网怎样下载 > 共识算法PoW的算力与挖矿难度
共识算法PoW的算力与挖矿难度
大家好,我是余双奇,本文是关于区块链共识算法系列文章。 在上一篇《共识算法PoW的由来》中,我们讲解了工作量证明的基本原理。 核心是用穷举法暴力寻找一个满足难度值的随机数。 这篇文章解释了比特币的计算能力。 通过这一部分,你可以掌握算力的概念,了解算力造成的悲剧。
大家好,我是余双奇,本文是关于区块链共识算法系列文章。 在上一篇《共识算法PoW的由来》中,我们讲解了工作量证明的基本原理。 核心是用穷举法暴力寻找一个满足难度值的随机数。 这篇文章解释了比特币的计算能力。 通过这一部分比特币难度值计算公式,你可以掌握算力的概念,了解算力造成的悲剧。
计算能力
比特币挖矿就像猜数字。 矿工需要找到一个随机数(Nonce)参与哈希运算[1]
Hash(Block+Nonce)
使区块哈希值满足难度要求。 计算能力是指计算机每秒可以进行哈希运算的次数,也称为哈希率(hashrate)。
上图是当前比特币算力走势图[2]。 到 2017 年,比特币挖矿所需的计算能力猛增。 这与不断研发新的矿机投入市场有关——这些矿机采用新技术,拥有更强的算力比特币难度值计算公式,即单位成本下的算力增长迅速,带来了算力的增加。综合计算能力。
算力单元
算力以每千位为一个单位进行划分,最小单位为H=1次,其他划分为:
如果不知道单位的缩写,可以查看下面的国际单位前缀表[3]:
因子名称符号
10^24
尤塔
是
10^21
泽塔
Z
10^18
exa
E、
10^15
善待动物组织
P
10^12
特拉
吨
10^9
千兆
G
10^6
巨型
米
10^3
公里
k
10^2
百
H
10^1
德卡
哒
挖矿难度计算挖矿难度Difficulty动态调整
上图红线是比特币从推出到现在的难度值变化图。 可以看出,难度一直在增加,难度越大,矿工找到随机数的时间就越长。 同时可以观察到难度值是周期性调整的。 这是因为比特币协议预计每十分钟产生一个区块,而 2016 年的区块需要两周才能完成。 每2016个区块,全网节点根据前2016个区块的支付时间自动调整难度值。 如果超过两周,则降低难度,否则增加难度。 为了保持一个块是10分钟。 更多图表数据可在bitcoinwisdom网站查看。
难度值代表了寻找随机数的耗时程度,耗时越长,计算机需要进行哈希计算的次数就越多。 普通笔记本电脑每秒可以进行 800 次哈希运算,中端显卡可以进行 2000 多次哈希运算。
中本聪在自己的电脑上挖出了创世区块(比特币区块链的第一个区块)。 本来,中本聪设计了一个公平的、完全去中心化的数字货币系统,每个人都可以用个人电脑来挖矿(他还预言网络上会有挖矿服务商(矿池))。 但是在盈利的时候,不断有大量新的算力加入,矿工之间的竞争激烈,以至于单个矿工的挖矿成功率几乎为零。 2011年开始出现矿池,大量矿工加入矿池稳定收益,摊薄成本。 大量算力的融合,使得比特币的挖矿难度越来越大。 数字货币挖矿行业就像一场军事竞赛。 挖矿设备不断更新迭代,不再遵循摩尔定律。 专业矿机针对哈希算法、散热、能耗进行了优化,背离了比特币网络节点运行数千次普通计算、公平参与挖矿的初衷。 矿池占用的算力也让比特币的风险始终存在:51%算力攻击。
挖矿难度计算公式
找到一个随机数需要多少算力取决于当前区块的挖矿难度。 难度越大,需要的计算能力就越大。 但是,挖矿难度不包含在区块信息中。 它只是根据规则在网络节点中动态计算。 公式如下:
$D = T_1/T $
字母T是Target的缩写,字母D是DiFFiculty的缩写。 $T_1$和T都是一个256位的大数,其中$T_1$是一个非常大的常数$2^{256-32}-1=2^224-1$。 根据公式,T越小,挖矿难度D越大。
根据公式,当T=0时,D为无穷大,即无法计算结果。 好在T不会为0,最小值为1,此时难度值最大,为$2^{256-32}-1=2^224-1$。 当$T = T_1$时,难度值为最小值1。
目标值 目标与挖矿难度换算
为了方便人类直观估计难度,比特币协议将大数T压缩成浮点数记录在区块头中,字段为bits。
如果一个块的目标值是0x1b0404cb,它会被转换成一个目标值$$0x0404cb * 256^{0x1b-3}$$
T采用类浮点压缩表示[4]进行压缩,压缩计算过程如下:
将数字转为256进制,如果第一位大于127(0x7f),则在前面加0。 压缩结果中的第一位存储了 256 进制数的位数。 后三位存放256进制数的前三位,不足三位则从后面补零。
例如,要压缩数字1000,首先将其转换为256的数字: $$1000=0x03 256^{2-1} + 0xe8 256^{1-1}$$ 结果为[0x03,0xe8]。 如果第一个数不超过0x7f,则可以不填0。但是两位长度小于三位,后面补零,最终表达式为:0x0203e800。
再比如数字$$2^{256-32}-1$$,转换为256的十六进制:
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
第一个数字0xFF大于0x7f,所以前面加零后就变成了:
00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
其长度等于28+1=29(0x1d),长度超过三位,不补零,压缩结果为:0x1d00FFFF。 因为压缩后的存储容量只有4个字节,前两个字节已经被长度和添加的00占用,只剩下2个字节存储数字,所以后面的26个FF值被丢弃。
如果我们对压缩后的结果0x1d00FFFF进行解压,它还会是原来的值吗? 事实上,结果是:$$T=0x00FFFF × 256 ^{0x1b−3}$$ =
0x00000000FFFF0000000000000000000000000000000000000000000000000000
这个数字在解压的时候被截断了,不再是原来的$$2^{256-32}-1$$了。 比特币的 $$T_1$$ 值就是这个 0x1d00FFFF。 如果区块中的比特位为0x1d00FFFF,则表示该区域的区块挖矿难度为最小挖矿难度1。
事实上,专业的矿池程序保留了截断的 FF:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
我们称上述号码池难度为1(pool diFFiculty 1)。 所以根据公式,区块目标值的挖矿难度为0x1b0404cb,在挖机上看到:
D = 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF /
0x00000000000404CB000000000000000000000000000000000000000000000000
= 16307.669773817162 (pdiFF)
称为 pdiFF。 但有些比特币客户端可能无法精确到这么大的尺寸,所以尾随的 FF 没有保留:
0x00000000FFFFFF0000000000000000000000000000000000000000000000000000
此时挖矿难度为:
D = 0x00000000FFFF0000000000000000000000000000000000000000000000000000 /
0x00000000000404CB000000000000000000000000000000000000000000000000
= 16307.420938523983 (bdiFF)
称为 bidFF。
在哪里可以查看当前的比特币挖矿难度
您可以在一些提供服务的网站上查看图表数据,例如:
下图是撰写本文时比特币区块 546336 的摘要。
如何根据难度值计算算力
既然我们知道了挖矿难度是如何计算的,那么需要进行多少次哈希运算才能找到随机数才能挖出一个区块,使得该区块的哈希值小于目标值呢?
之前已经确定$T_1=0x1d00FFFF$,解压后为$:0xFFFF×2^208$,对于难度D的目标值:
因此,估计挖出一个难度为D的区块所需的哈希数为:
目前的难度计算速度要求是在10分钟内找到,即在600秒内完成计算,也就是说最低的网络算力必须是:
根据上面的计算,当D=1时,每秒需要计算7158278个哈希,即:7.15Mhahs/s。
目标值计算源码
调整难度时,调整的是目标值。 目标值的计算公式如下,但在实际计算中有一些特殊处理,将目标值控制在一定范围内。
新目标值= 当前目标值 * 实际2016个区块出块时间 / 理论2016个区块出块时间(2周)。
计算过程,Go代码如下,点击
var (
bigOne = big.NewInt(1)
// 最大难度:00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,2^224,0x1d00FFFF
mainPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne)
powTargetTimespan = time.Hour * 24 * 14 // 两周
)
func CalculateNextWorkTarget(prev2016block, lastBlock Block) *big.Int {
// 如果新区块(+1)不是2016的整数倍,则不需要更新,仍然是最后一个区块的 bits
if (lastBlock.Head.Height+1)%2016 != 0 {
return CompactToBig(lastBlock.Head.Bits)
}
// 计算 2016个区块出块时间
actualTimespan := lastBlock.Head.Timestamp.Sub(prev2016block.Head.Timestamp)
if actualTimespan < powTargetTimespan/4 {
actualTimespan = powTargetTimespan / 4
} else if actualTimespan > powTargetTimespan*4 {
// 如果超过8周,则按8周计算
actualTimespan = powTargetTimespan * 4
}
lastTarget := CompactToBig(lastBlock.Head.Bits)
// 计算公式: target = lastTarget * actualTime / expectTime
newTarget := new(big.Int).Mul(lastTarget, big.NewInt(int64(actualTimespan.Seconds())))
newTarget.Div(newTarget, big.NewInt(int64(powTargetTimespan.Seconds())))
//超过最多难度,则重置
if newTarget.Cmp(mainPowLimit) > 0 {
newTarget.Set(mainPowLimit)
}
return newTarget
}
测试代码如下,计算是出块高度为497951+1时计算的新目标值。
func TestGetTarget(t *testing.T) {
firstTime, _ := time.Parse("2006-01-02 15:04:05", "2017-11-25 03:53:16")
lastTime, _ := time.Parse("2006-01-02 15:04:05", "2017-12-07 00:22:42")
prevB := Block{Head: BlockHeader{Height: 497951, Bits: 0x1800d0f6, Timestamp: lastTime}}
prev2016B := Block{Head: BlockHeader{Height: 495936, Bits: 0x1800d0f6, Timestamp: firstTime}}
result := CalculateNextWorkTarget(prev2016B, prevB)
bits := BigToCompact(result)
if bits != 0x1800b0ed {
t.Fatalf("expect 0x1800b0ed,unexpected %x", bits)
}
}
比特币哈希算法使用 SHA256 进行工作证明。 在比特币上实时查看比特币算力。 二进制浮点运算的 IEEE 标准 (IEEE 754)
本文参与登联社区写作激励计划,好文章好收益,欢迎正在阅读的你加入。