Part 0. 前言

前面我们已经了解到了:

  1. 比特币 代表了诞生于数字时代的对 货币问题 新的 技术解决方案
  2. 比特币 最大的价值在于 价值存储,是拥有极高存量-增量比的 健全货币
  3. ….

可是这一切是如何通过技术实现的呢?这一篇文章就将 尽可能通俗 地解答这一问题。

Part 1. 从一个例子入手

现在假设 A、B、C、D 四个人合租一套房子,因为时常有金钱上的往来,为了省事,他们选择使用客厅的一块白板 用来记账,到月底一起结清:

如果有人调皮,往白板上 凭空写一条记录,例如:A 需要向 C 支付 50,那么月底 A 就会多支付 50,为了避免这样的情况发生,每一条记录后面都需要 本人确认签字

后来由于账目过多,于是大家决定 转用电脑 来记录,但这样一来 签名成了问题

一方面在电脑上不方便手写签名,另一方面手写签名也很容易被复制,所以我们需要转换成专门用于电脑的 数字签名

Part 2. 哈希(hash)算法

使用数字签名,我们需要考虑严格的 对应性,也就是说一条签名只能用于指定的记录才行:

例如这里的第一条记录 (A→C 转账 50) 需要严格对应 数字签名 1,不能对应第二条,也不能允许金额变更 *(如果金额更改应该是其他的数字签名)*。

这样才能对记录的正确性有保证。

可是数字签名如何生成呢? 这里需要介绍一种被称为 哈希(hash)算法 的工具。

它的作用是能把 任意长度的输入 变成 固定长度的二进制输出

图示采用 CRC-32 Hash 算法

在比特币的世界中,采用了 SHA-256 算法 来生成数字签名,其中 SHASecure Hash Algorithm (安全哈希算法) 的简写,256 表示无论输入什么值都会生成一个 256 位的二进制数 *(由 0/1 组成)*。

并且 相同的输入,总会得到 相同的结果,结果又不能倒推回输入,所以我们可以使用 SHA-256 作为我们的数字签名。

例如,我们把第一条记录用 SHA-256 算法对应生成一条数字签名:

即使是相差一个字、一个点,都会造成最终通过 SHA-256 生成的签名完全不一样,且毫无规律可寻:*(这样就能满足一一对应)*

所以我们算是解决了对应性的难题:

Part 3. 非对称加密

但是这样还远远不够,即使一一对应,也不能证明像上述这样生成的数字签名是 本人生成 的,因为 SHA-256 是公开的算法,任何人都能通过它生成数字签名。

如何才能验证是 A 生成的签名而不是 B 生成的呢?

于是想出了一个办法,这个办法叫 非对称加密

加密和解密

先来解释一下什么叫加密,用大家平时比较喜欢的一串数字来举例:

5201314 是大家比较能知道的意思,但是把每一位数字都 +2 之后变成 7423536 就不那么容易明白了,这个过程就叫 加密,还原的过程则叫 解密

对称加密和非对称加密

像上面例子中那样加密和解密过程一样的 *(±2)*,我们称之为 对称加密,加密和解密过程不一样的则称之为 非对称加密

举个例子,假设我们现在需要加密的字符是 520,我们 加密 的方法是把这个数乘以 91,并把结果的最后三位公布出来:

解密 我们当然不能通过除以 91 来完成,而是通过 x11,取出结果后三位来还原:

这是因为 91*11=1001,任何一个三位数乘以 1001 显然后三位是不会变的。

这大概就是 非对称加密的原理 了,只是可能原理更为复杂。

通常,在这个原理被保密的情况下,我们把解密的方法公布到网上,数字 11 就被我们称为 公钥,人人都能知道,人人都能对应还原。

这个用来加密的数字 91 我们称之为 私钥,只有你自己知道。

图片来源:https://bitcoin.org/zh_CN/how-it-works

一组配对的公钥和私钥,也就能解决 可验证 的问题了,因为私钥有且仅有一个与之配对的公钥。

他人可以使用你的公钥加密信息,然后发送给你,你用私钥解密,取出信息。反过来,你也可以用私钥加密信息,别人用你的公钥解开,从而证明这个信息确实是你发出的,且未被篡改,这也就是 数字签名 了。(更详细的介绍请看《什么是数字签名》)。

于是我们又解决了 可验证 问题:

Part 4. 去中心化

好了,目前我们的账本已经算是可用了,但是整个过程我们是信赖 “电脑” 这个 第三方 的,如果出现什么问题 *(比如中毒了)*,那就是无可避免的损失。

现在我们的交易大部分都依赖于这样的 第三方,比如银行、支付宝,面对高昂的手续费、繁琐流程以及监管的问题,比特币给出的答案是:去中心化

比特币提出时,就说明了比特币是一种完全 点对点 的电子货币系统,也就是说交易就像给某人发电子邮件一样简单,完全不需要借助任何第三方。

(这当然也有缺点在上一篇中我们提到一些——比如违法活动的进行更难追溯和查找)

图片来源:https://bitcoin.org/zh_CN/how-it-works

每一个人 都拥有一个 完整的账本,每个人都是中心,这样即使部分账本存在问题也不会影响。

每一次交易的发生都会把这一次交易的信息公布到网上,每个人 验证成功 之后都会记录到自己的账本中。

比如,A 向 B 支付了 50,那么 A 就会使用自己的 私钥 进行加密然后 广播 到每一个人告诉他们这一消息:

每一个收到的人再使用 A 的 公钥 进行解密验证确实是 A 向 B 支付了 50,并且开始检查自己的账本,开始回溯检查 确保 A 的账户上有 50 用于支付给 B。

如果一切 OK,那么每个人的账本上都记录上了这一条消息。

三个一致性问题

每个人都存储 所有 的转账记录,这会存在三个关于 一致性 的问题。

第一个问题是:如何进行同步?

因为整个系统运行在网络,有的计算机可能会处于 “离线” 的状态,但交易时刻都在发生,这就会出现账本不一致的情况,如何才能保证不同计算机之间数据之间的数据同步问题呢?

第二个问题是:如何防止记录被篡改?

例如黑客可能篡改网络中某些账本中的部分数据,导致账目不一致甚至冲突的情况发生,最终比特币网络崩坏,如何才能保证数据不会被恶意篡改呢?

第三个问题是:如何防止同一笔比特币收入被重复使用?

之前看到有人问:如果在 ATM 机跟支付宝中同时转走账户剩余的钱,那么是不是会凭空多出一笔?

当然不会,因为 银行 这样的 第三方机构 会帮你做出决定:先转走哪一笔那么另一笔就会失效。

可是比特币网络中,由于有些人先收到消息有些人后收到消息,那么究竟使用哪一条消息为准,又如何防止 “凭空多出一笔” 这样的事情发生呢?

Part 5. 区块链

上述的一致性问题,比特币世界采用 区块链 的方式来解决。

区块链 = 区块 + 链

在比特币世界中,大约每 10 分钟会结算一次这 10 分钟以来的交易记录并输出一个新的 “账本”:

这些 “账本” 当然不是交易记录的 简单复合,而是包括了:前一个 “账本” 是哪一个、前一个 “账本” 所有数据计算出的 Hash 值等等信息的 复杂数据体

这样我们既能通过简单的验证保证 数据的正确性,又能把所有的 “账本” 都 串联 起来:

好了,换个名字,区块链有了:

辽宁沈阳一小区大门上,66 把锁串联在一起,被誉为 **”最便宜的门禁系统”**,也号称 “区块链实体化” 技术…

区块链实体化...

新区块由 “矿工” 生成

比特币网络中每一个新区块都由 “矿工” 生成,它们会 逐条检查每一条记录 是否符合要求,例如每一条记录是否有正确的数字签名、支付是否合理等。

然后将验证完之后的比特币交易记录添加到自己正在制作的 新区块 中,制作完成就马上发送到比特币网络中的每一个节点。

节点收到这个新区块的信息,如果验证之后符合要求,就添加到目前 区块链的末尾

那么问题来了,比特币网络有许许多多的 “矿工”,这也意味着这可能会 同一时间 内能生成很多 基本信息大致相同 的 **”新区块”**。

虽然这些 “新区块” 中大致都是近期内验证好的交易记录,但是每个区块具体包含哪些交易记录,可能各不相同。

比特币网络只能认可维护 同一条区块链,比特币网络上的 每个节点 都必须选择 同一个新区块 添加到末尾,但是这又很难制定一个统一的选择标准。

POW(Proof Of Work)工作量证明

比特币世界解决方法是:采用一个巧妙的方法限制单位时间内生成的新区块的数量

如果每过 10 分钟左右的时间,整个比特币世界只有 一个 “矿工” 能够生成 一个 新区块,那么也就不用再进行选择,区块链也将添加唯一一个新区块到末尾。

这个巧妙的方法就是:当 “矿工” 完成新区块的验证打包之后,还需要做一个 额外的工作 才能把生成的区块发布到网络上。

额外工作的整个过程可以分为 2 步:

  1. 将新制作区块所包含的 内容(前一个区块所有内容的 SHA-256 函数值 + 新区块基本信息 + 新区块所包含所有交易记录)组合成一个 字符串
  2. 在这个字符串的末尾添加一个 随机数,组成新字符串;

只有当这个新组成的字符串通过 SHA-256 算法得到的 256 位二进制数的前 72 位 **全是 0**,才算成功完成了这个额外的工作。

这个额外工作的难度非常高 *(前 72 位为 0 的概率为 1 / 272)*,高到整个比特币网络大约 10 分钟时间也只有一个 “矿工” 能够 找到这个随机数

原因就在于 SHA-256 函数的特点是:虽然每个输入值都对应一个输出值,但是这 256 位二进制数完全随机没有规律。

找到这个满足条件的随机数的 唯一方法 就是 以最快的速度输入不同的随机数不停地试

当 “矿工” 找到这个随机数之后,会将这个 随机数打包进当前区块 然后打包发布到比特币网络,所有节点就可以根据这个随机数和新区块的基本信息 快速验证 是否符合要求。

虽然找到这个 随机数 完全靠运气,但矿工的运算能力越强,这个运气就会越好,这也是 “矿工” 们不断升级设备的原因。

矿工激励机制

是什么支持着 “矿工” 们不停升级自己的设备去打包新的区块呢?

在比特币世界里,每成功打包一个新区块,就会奖励给 “矿工” 一定数量的比特币,最初是 50 个,每产生 21 万区块 *(也就是大约 4 年时间)*,奖励就会减半,2020 年这一奖励已降至 6.25 比特币。

另外当前区块中所有交易产生的交易费也归 “矿工” 所有。

拿 2017 年举例,每打包一个区块会得到 12.5 比特币的奖励,交易产生的交易费大约是 2 比特币 *(参照上图)*,也就是总收入约 14.5 比特币。

按照 2017 年 12 月 16 日的行情,这大约值 26 万美元,即 170 万人民币

换句话说,一个运气好的矿工,10 分钟左右,就能产生 170 万的收入。

工作难度调整

图片来源:http://www.time-weekly.com/post/264828

巨大的经济利益带来的是挖矿设备的不断升级,这也导致了整个比特币网络计算能力的提高。

为了维持平均 10 分钟生成一个区块的速度,比特币网络会每 2 个星期调整一次工作难度。

例如从前 72 位为 0 调整为前 73 位,难度也是几何级的增加。

一致性问题回顾

好了,我们来回顾一下区块链是如何解决上面提到过的一致性问题的。

如何进行同步?

比特币网络仅仅维护网络中唯一一条 最长的区块链,所以不论是新加入的节点还是需要同步的节点,都以此为准。

很容易知道,即使 “矿工” 有了 额外的工作 需要做,但仍然会发生 两个区块同时发布 到网络上的情况。

此时网络上一部分节点先接受到 A 的区块,另一部分接受到 B 的区块。

此时两个区块都不丢弃,直到下一个区块 C 产生,由于 额外的工作 不会凑巧得又有两个新区块同时产生,此时 C 区块前面的区块是 A 那么整个区块链网络就接受 A 这一条,反之则接受 B。

这时候 A 区块中未被打包的交易记录又会被丢到网络中等待打包。

就算很凑巧仍然有区块同时被打包在 A 和 B 区块的后面,那么继续等待 最长链 的产生就好了。

通常来说,正常的交易被区块链接受后,后面再接上 2-3 个区块就能确保已经被区块链完全接受了,大一点的交易则等待 3-6 个区块。

如此就保证了网络中 仅有一条唯一的长链 产生,所有的节点都以此为准。

如何防止篡改

额外工作 中我们提及到,每一个区块都带有 上一个区块所有交易信息 的 SHA-256 的值,区块由此链接起来:

即使是很微小的改动,也会导致该区块的 SHA-256 值不一致,导致后续链接的区块断裂:

由于区块链只维护一条最长链,所以只有当篡改者拥有的计算能力超过 整个网络中其他节点的计算能力的总和 时,才能通过不断完成 额外工作 添加新区块的方式,使当前修改的区块成为最长链

区块链的参与者越多,这一难度越大。

就算有人成功地篡改了交易记录,他也不大可能得到任何好处,因为由于他的攻击,比特币网络的价值会大幅下跌,乃至归零。

换句话说,为了摧毁比特币,攻击者需要付出极大的成本,却不会得到任何回报。

算力的分散、代码的强抗更改性、稳如山的货币政策,是比特币存活下来并成长到今天这个规模的原因。

如何防止同一笔比特币收入被重复使用

区块链中的每一条交易记录都记录了完整的 代码可追溯 的流转信息。

在打包新区块的时候,如果发现交易记录的 上一笔交易 已经出现在了 之前的区块 中,那么就会 放弃掉 该记录;

如果 同一个区块 中出现了 两笔来源相同 的记录,那么也只会 选择其中一条 进行记录。

总结

好了,到目前为止我们已经把比特币使用的技术和相关知识都通俗的讲述了一遍,不知道小伙伴们有没有真的理解比特币呢?

现在来对主要技术和特点做一下总结

  1. 利用 SHA-256 算法非对称加密 来制作 数字签名
  2. 利用 区块链 中的区块存储比特币交易记录;
  3. 设置 额外工作 从而控制单位时间内生成区块的个数,同时保护比特币网络;
  4. 将一定数额的比特币和区块内的所有交易费奖励,用于成功生成该区块的矿工奖励,激励 更多矿工加入比特币网络,促使比特币网络茁壮成长;
  5. 比忒不转账不依赖银行或其他金融机构;
  6. 比特币网络内比特币的总量不会超过 2100 万。

(完)