查看原文
其他

身价百亿的中本聪是如何打造出“创世区块”的?

Subhan Nadeem CSDN 2018-07-23

点击上方“CSDN”,选择“置顶公众号”

关键时刻,第一时间送达!

随着比特币逐渐被主流认识并接受,它的基础安全模型也以“挖矿”的形象出现在聚光灯下,并且需要接受越来越多的审查。

人们越来越担心比特币挖矿对环境的影响,底层模型的去中心化的安全性,甚至量子计算可能对比特币和其他加密货币造成的影响。

许多情况下,工作量证明被称为“加密谜题”,但这个谜题究竟是什么?

为了真正理解这些问题(以及许多可能的回答),你需要了解一些关于比特币挖矿及其演变过程的基础知识。

本文将介绍关于工作量证明的所有技术组成和工作原理,以及它们如何协同工作才造就了今日比特币的去中心化平台。


为什么挖矿可行:单向加密 hash


比特币区块链通常被描述为一个加密、安全的,而且不可修改的数据库。实现这种不可修改和安全性的底层技术叫做加密 hash

加密 hash 函数是一个数学函数,简单来说,它接受任何输入,将其映射称一个固定长度的字符串。

但是,这些函数有四个特点,从而使它们对于比特币网络极其有用。这些特点是:

  1. 决定性——加密 hash 函数对于任何给定的输入永远都会给出相同的输出。

  2. 高速——对于任何输入,计算 hash 函数相对很快(不需要大量繁重的计算)。

  3. 唯一——函数的每个输入都会导致唯一而且完全随机的输出(换句话说,没有两个输入会产生同样的输出)。

  4. 不可逆——给出 hash 函数的输出,无法推断出原始输入。

这些特点为比特币挖矿提供了安全的技术保障。

具体来说,比特币的创建者中本聪采用了 SHA-256 hash 函数作为比特币挖矿的基础。这个加密 hash 函数在数学上拥有以上四个特点。它的输出结果永远是 256 比特的数字(比特是最基本的计算单位),为了人类阅读方便,通常用 64 个字符的十六进制数表示。

SHA-256 函数的输出通常称为其输入的 hash。

hash 函数的输入会产生唯一的输出

下面是一个 SHA-256 函数的输入和输出的例子(这里(http://www.xorbin.com/tools/sha256-hash-calculator)可以亲自尝试):

Input to SHA-256:
<Bitcoin Transaction>
Output to SHA-256:
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf

有意思的是,在比特币协议中,使用 hash 的地方用的都是双 hash。这就是说,SHA-256 函数的原始输出会被放回到 SHA-256 函数中,获得另一个输出。其过程如下所示:

Input to SHA-256(first round):
<Bitcoin Transaction>
Output (first round):
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf
Input to SHA-256 (second round):
77077b1f4c3ad44c83dc0bdb8d937e9b71c0ef07a35c2664bb7da85be738eacf
Output (second round and final result):
3c6c55b0e4b607b672b50f04e028a6951aed6dc97b91e103fb0f348c3f1dfa00

双 hash 可以用于防止生日攻击。生日攻击是指攻击者利用完全不同的输入生成相同的 hash(称为冲突)。这会打破上述第三个特点:唯一性。没有唯一性,两个完全不同的比特币区块有可能会表示成完全相同的 hash,这样攻击者就有可能会替换区块。

有了 SHA-256 函数,这种攻击可能实施的可能就几乎不可能了。否则,就可以认为 SHA-256 被攻破了。

但是,其他 hash 函数被攻破的情况以前发生过。为了防止以后 SHA-256 被攻破(这样比特币的安全模型也被攻破了),最好是对 hash 再次进行 hash。这样能降低一半冲突的概率,让协议更安全。

简单地说,比特币挖矿就是个将所有比特币交易发送给比特币矿工的过程。矿工选择一兆字节的交易,打包后作为 SHA-256 函数的输入,然后尝试寻找一个网络能接受的输出。第一个找到符合条件的输出的矿工将公布该区块到网络上,并以交易费或新比特币的形式获得一点奖励。

我们来进一步看看比特币区块链的原理,看看矿工是如何让网络变得安全的。


比特币挖矿:技术介绍


挖矿是为了解决双花问题而引入的。如果我有 1 个比特币并且发送给了 Bob,然后我试图将同样的那个比特币发送给Alice,比特币网络可以保证只有一个交易会成功。这是通过众所周知的挖矿过程实现的。

在深入技术细节之前,重要的一点是理解为什么需要让网络更安全。现在还存在法定货币(即银行发行的货币)。由于比特币的基础是坚实的去中心化和共识算法,网络中并没有中心的权威机构来验证每个货币,以及与该货币相关的所有交易。

中本聪提出,目前解决这项验证问题的唯一方法就是通过共识系统。在比特币白皮书中称为“工作量证明”,这个算法可以让愿意验证的人通过真实的计算力和时间来判断交易的真实性,同时还引入了奖励措施,以促进市场竞争。这种竞争机制让去中心化特性有机地与生态系统结合起来。


区块的内部结构


一个比特币区块主要包括两个部分:

1.交易,以 merkle 树形式保存

挖矿的计算机收集足够的交易,以填满一个区块,然后将区块打包成 merkle 树。

merkle 树的概念很简单:交易位于树的底部,作为叶子,用 SHA-256 函数生成 hash。两个叶节点的交易一起通过 SHA-256 函数,构成一个父节点。父节点再继续上与其他父节点组合,直到生成单一的根节点。根节点的hash就能唯一地表示下面所有交易。

形象地表示 merkle 树是如何创建的——最底部的叶节点是交易

merkle 树的根节点就是所有交易的 hash 的组合。

回忆一下,hash 函数对于任何输入都会给出完全唯一的输出。因此,当网络上的大部分节点都收到一个挖好的区块后,这个区块的 merkle 树的根节点 hash 就成了该区块内所有交易的一个不可改变的摘要了。

如果恶意用户想要改变某个区块内的交易内容,那么交易的 hash 就会改变。这个改变会沿着交易的 merkle 树向上传递,导致根节点的 hash 发生改变。这样任何节点只需比较被改变的区块的merkle树根节点,就能迅速发现这个恶意行为。

2. 区块头

区块头是区块内容本身的总结。它包含以下六个部分:

  • 比特币客户端软件的版本

  • 区块的时间戳

  • 它包含的所有交易的merkle树的根节点

  • 上一个区块的hash

  • 一个nonce值

  • target

别忘了,merkle 树的根节点是区块内所有交易的摘要,因此无需去查看每个交易的内容。

上一个区块的 hash 可以让网络将区块按照时间顺序排序。这就是区块链这个词的来源——每个区块都连到上一个区块上。

nonce 和 target 是挖矿的关键。它们就是矿工需要解决 SHA-256 谜题。

区块头中的所有这些数据都被以 little-endian 方式压缩至 80 字节,使得节点之间传输区块更有效。为了说明方便,我们将忽略这个压缩,假设所有数据都以原始形式出现。


详解挖矿问题


区块头中保存的 target 是个以比特方式保存的数字。用十进制表示,target 值在 0 到大约 2224 之间(一个 67 位数),这个值取决于多少个矿工在同时竞争同一个问题。

回忆一下,SHA-256 的输出只不过是个数字。矿工的目的就是要计算当前区块头和一个随机数(称为 nonce)的 hash。hash 的数字值必须小于 target 值。

这就是挖矿的全部。不过实际上要复杂得多。

回想一下 SHA-256 的第一个特点:同一个输入永远会产生相同的输出。因此,矿工计算区块头的hash值,然后发现 hash 值比 target 大,他就得以某种方式改变输入,以找到另一个 hash 值使之小于 target。

这就要用到 nonce。

矿工会在区块头中添加一个从零开始的数字,该数字称为nonce,然后计算其hash值。如果hash值不小于target,矿工就会给nonce加一,放到区块头中,然后计算改变后的hash值。重复该过程直到找到一个小于target的hash值。

挖矿的例子

下面这个例子简单地模拟了第一个区块头的生成过程。

  • 创世区块中的交易的 merkle 树:

Merkle Root:
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
  • 第一个已知的比特币版本:0.1.0

  • 区块创建时间:2009-01-03 18:15:05

  • target(这也是最大的 target):

Target:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  • 没有前一个区块的 hash,因为这是第一个区块。

最后的区块头如下:

创世区块的数据(这个数据包含了 nonce,但让我们假设它不含 nonce),来源:bitcointalk(https://bitcointalk.org/index.php?topic=52706)

我们来计算这个区块头的双重 hash:

SHA-256 of header:
7d80bd12dfdccbdde2c41c9f406edfc05afb3320f5affc4f510b05a3394e1c91
SHA-256 of the previous result (final result):
c5aa3150f61b752c8fb39525f911981e2f9982c8b9bc907c73914585ad2ef12b

转化成十进制的话,target 和输出的 hash 都是非常大的数字(超过67位数)。因此这里就不再演示如何比较亮着大小,而是直接交给下面的 Python 函数来判断:

def isBlockHashLessThanTarget(blockHash, target):
    return int(blockHash, 16) < int(target, 16)

如果 hash 小于 target,这个函数返回真,否则返回假。

下面是比较结果:

然后我们将原来的十六进制区块头的值加一。下面是结果:

注意最后一位增加了1,这是由于nonce加一导致的

运行同一个 hash 算法并比较数据。如果仍然大于 target,就重复该过程。

一旦找到了符合条件的 hash,最后一次使用的 nonce 值就会被保存到区块中。

创世区块的 nonce 值是 2,083,236,893。

这意味着,中本聪重复了该过程超过 20 亿次,才找到一个合适的 hash。

我写了个 Python 程序实现该创世区块的挖矿过程,并共享到了GitHub上:http://github.com/subhan-nadeem/bitcoin-mining-python

警告:extraNonce

区块头中的 nonce 存储为 32 比特整数。这就是说,nonce 最大的取值就是232(大约是40亿)。在 40 亿次重复之后,nonce 就用完了,如果还没有找到解,矿工就没有办法了。

解决方案是在 coinbase(即区块的交易内容,存储为 merkle 树)中增加一个名为 extraNonce 的字段。该字段的大小只受限于区块本身的大小,因此它可以存储任意大的数字,最大可以到协议限制的区块大小。

如果 nonce 所有 40 亿的可能值都被用完,则 extraNonce 会加一并放到 coinbase 中。因此会生成一个新的 merkle 树的根节点,从而生成新的区块头,然后再次重复计算 nonce。重复该过程直到找到合适的 hash。

在 nonce 用完之前要避免使用 extraNonce,因为每次改变 extraNonce 都会改变 merkle 树,这会导致计算 merkle 树中的所有节点以生成新的 merkle 树根节点。

矿工奖励

最快地成功发布一个区块的矿工将获得一个新的比特币,该比特币是凭空创建出来的。目前的奖励是 12.5BTC。那么这些比特币是如何产生的?

每个矿工只需在开始挖矿之前,在区块中添加一个新的交易,给自己 12.5 个比特币。当接收到有效的区块时,网络就会接受这个特殊的交易。这个交易称为生成交易。

矿工有责任在挖矿之前向区块中添加该交易。以前发生过矿工忘记添加该奖励,从而让12.5BTC化为泡影的事情发生!


工作量证明的验证


我们假设矿工找到了一个小于 target 的 hash。该矿工要做的就是将这个区块发送到所有联网的节点。

收到该区块的节点将首先验证该交易,确保所有交易都是合法的(例如,所有交易都要有正确的签名,而且里面的货币没有被双花,没有被凭空创造)。

然后该节点将对区块头进行双重 hash,并确保该值小于区块中包含的 target 值。区块一旦被验证为合法,新的节点就会继续向网络上传播该区块,直到所有节点都有了最新的账本。

可见,新发布的区块可以由任何节点轻松地验证。但是,向网络发布一个区块则需要难以想象的庞大计算力(即电力和时间)。这种不对称性使得网络更安全,同时允许任何希望参与经济活动的人很容易地参与进来。


区块时间和 target 的调整


第一个矿工开始挖矿时,所有人都会监视区块时间。每个比特币区块的区块时间是 10 分钟。也就是说,对于网络上的特定的计算力(网络 hash 率),平均每 10 分钟就会产生一个新的区块。

可以合理地认为,网络每 10 分钟就会产生一个新区块,因为给定网络的 hash 率,找到区块的概率是已知的。

例如,考虑比特币中最容易的 target:创世区块。任意一个 hash 小于 target 的概率是 1/232。大约是 40 亿分之一。因此,我们可以认为,找到合适的 hash 需要大概 232 次重复。网络上的所有节点每 10 分钟就会进行 40 亿次计算。

如果在多个区块中,区块出现的速度小于 10 分钟,就说明网络进行 40 亿次计算的时间要小于10分钟。在这种情况下,每个节点都要调整其 target 值,根据网络计算力增加(或减少)该值以保证继续 10 分钟产生一个区块。

在实际中,网络中的节点会监视 2016 个区块的时间,这是正好两个星期产生的区块数量。每两个兴起,总的区块时间就会与期待的区块时间相比较(期待值为20160分钟)。

要计算新的 target,只需将已有 target 乘以过去两个星期的实际区块时间与期待区块时间的比值。这样就可以对 target 根据网络的计算力变化作出调整。

计算新 target 值的公式,每个比特币节点都会每隔 20160 分钟运行一次

区块时间和相对容易的概率计算方式,使得节点可以轻易地监视并确定网络的整体计算力,并对网络进行调整。不管网络计算力增加多少、增加得多块,平均来说,区块时间永远是 10 分钟。

当前网络的总体 hash 率是每秒 28.27 exahash。也就是说,整个网络上的所有计算机,每秒钟能运行 28.27 x 1018 次 hash 计算。


总结


我们详细介绍了以下内容:

  • 为什么加密的单向 hash 对工作量证明很重要;

  • 比特币区块的结构;

  • 实际的挖矿过程;

  • 节点怎样容易地验证其他区块;

  • 网络怎样通过监视区块时间并调整target来管理算法和竞争

现在你应该能理解并解释工作量证明的工作原理,以及为什么它是确保去中心化和共识的安全算法了吧!

原文:https://medium.freecodecamp.org/how-bitcoin-mining-really-works-38563ec38c87

作者:Subhan Nadeem

译者:弯月,责编:屠敏

  征稿啦!

CSDN 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。
如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 CSDN 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱(guorui@csdn.net)。

————— 推荐阅读 —————

点击图片即可阅读

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存