比特币的基础技术原理 | 拆解数字货币与区块链(1补充)

学习

体验

蜂群

拼拼

LeanCode

比特币的基础技术原理 | 拆解数字货币与区块链(1补充)

如果你听过或接触过比特币,对它的技术原理几乎一无所知,希望有所了解,这篇文章正适合你。你不需要有专业的密码学、计算机网络知识,只是可能需要花一些时间。
本文作者群蜂社CTO刁伟鸿,听听读懂比特币源代码的人讲解比特币的基础技术原理。点击标题下作者姓名,进一步了解作者。


使用现金支付时,钞票从一个人的口袋转移到另一个人手中,我们可以亲眼确认所有权发生了改变。


进行刷卡或者移动支付时,中心化的商业银行系统,将从一个账户中减去一定数额,在另一账户上增加相应数额。我们愿意使用这类支付,是因为信任银行系统会如实帮我们记账。


使用比特币支付时,我们既没有亲眼看到实物货币的转移,也不能依赖类似于银行体系的这种“可信”第三方来记账,那我们如何能信任它?


陈词滥调会告诉你,比特币通过密码学来控制比特币的产生和转移,比特币网络由全体成员共同拥有,通过分布式共识保证安全性。


可是这种定义并没有提高你对比特币、或者对任何其他基于区块链的资产的分析和判断能力。你得到一个字面的解释,但是它无法被运用。如果你想对比特币是什么有更深刻的理解,我相信这篇有点长的文章可以帮助到你。


比特币相关的概念和事实


也许你熟悉并使用过比特币,即便没有,我们也可以一起来设想这么一个场景:


大雄在小福店里买手机,小福接受比特币支付,定价 0.05 比特币(按 2018 年 3 月 14 日行情,大概不到三千人民币)。刚好几天前大雄从哆啦A梦那里得到了 0.1 比特币,他决定使用它。他打开比特币钱包 App,扫描小福提供的二维码,读出小福的地址,输入 0.05 ,点击转账。


几秒内,小福在自己的钱包 App 看到他收到了 0.05 比特币。只是,交易还没被“确认”。小福可以认为支付已完成。如果他希望更保险一点,则需等待几分钟,等交易被确认后再把手机交给大雄。


以上是一个典型的比特币支付场景。


接下来我将通过这次交易中在比特币网络中发生的活动,来介绍相关的概念和事实。这些活动发生在由许许多多平等节点组成的比特币网络中,没有任何中心化的机构进行组织和干预。


比特币网络是一个点对点(P2P)网络。网络中的每个节点都可以被理解为一台运行着的计算机。点对点的意思是,节点之间彼此平等:它们被允许做的事情是一样的,没有特殊节点。节点有自由选择做不同事情,所以网络中有不同的“参与者”。我们将提到的“钱包”、“矿工”,都是比特币网络中的参与者。钱包和矿工指的都是运行着在各自计算机上的程序。



比特币 P2P 网络


大雄的钱包首先检查他有没有足够的比特币来完成这次交易。钱包管理着大雄的“比特币地址”。钱包在比特币区块链中查找跟这些地址相关的交易。


比特币体系里,没有“账户”的概念,也不存储任何账户余额。比特币系统只存储着一笔一笔的交易(Transaction)。每一笔交易都有输入和输出信息。输入信息指定比特币的来源,输出信息指定比特币的去向。除了“铸币”交易,每一笔交易的输入,都指向过往发生的一笔交易中的一个输出。


交易表达的信息,大概等于“谁把他/她的哪些比特币支付了给谁”。这些交易串联起来,可以找到任何一个比特币的来龙去脉。如下图:

交易链,并不是区块链


对于特定的某比特币(如哆啦A梦给大雄的这 0.1 比特币),我们可以追溯它的整个历史。


这些交易被存储在区块链当中。这里说的区块链是指具体的一种数据结构,而不是人们谈论的那个比较广义的综合概念。我将在下文中详细介绍它。区块链被完整地复制在比特币网络中的许多节点上。钱包通常不存储完整的区块链,它们向其他节点查询区块链上的交易数据。


之前哆啦A梦给大雄的 0.1 比特币,转入了大雄的钱包管理着的其中一个地址。通过这个地址,钱包在区块链中查到了这笔交易:


输入(只有一个输入): 
- 指向之前某个交易的输出 
- 对本交易进行的数字签名 
(使用哆啦A梦的某个私钥进行的签名)  

输出 (也只有一个): 
- 0.1 比特币 
- 目标为大雄的地址


我们把这个交易命名为 A,把它的唯一输出命名为 A1。


钱包发现,在区块链中没有任何一个其他有效交易的输入是指向 A1 的。换句话说,大雄收到的这个 0.1 比特币,还没被“花掉”。因此,大雄至少有 0.1 比特币。


这些“未被花掉的交易输出”是一个很重要的概念,有专门的术语 - UTXO,英文 Unspent Transaction Output 的缩写。比特币就存在于这些 UTXO 中。


于是钱包创建一笔新的交易,用于大雄对小福的支付:


输入(只有一个输入) :
- 指向 A1 
- 对本交易进行的数字签名 
(使用大雄的私钥进行的签名)  

输出 1 
- 0.05 比特币 
- 目标为小福的比特币地址 

输出 2 
- 0.049 比特币 
- 目标为大雄的另一个比特币地址
 (在同一个钱包管理)


我们把这个交易命名为 B。


交易 B 的输入,指向 A 的输出(A1),表示 A1 所代表的 0.1 比特币被用在这里。输入中提供的数字签名,用于证明交易 B 的发起者 - 大雄,拥有 A1 所代表比特币的使用权(同时也是所有权)。


数字签名以及非对称加密算法,是比特币技术的重要组成部分,用于实现比特币的所有权。
非对称加密算法要求每个参与者有一对密钥(私钥以及公钥)。顾名思义,公钥可以被公开,私钥是要保密的。
比特币交易输出中指定的地址,由公钥转换而成,可以理解为公钥的代号。要花掉交易输出所代表的比特币,必须使用这个地址(公钥)对应的私钥,来对新交易进行数字签名。对私钥的拥有,代表了对相应比特币的所有权。
数字签名是使用私钥对目标数据(比如交易数据)进行加密得到的信息。其他人可以根据对应公钥,来验证数字签名是否有效。用传统的手写签名打比方,目标数据就是所签的文档,私钥就代表了签名者本人的手,而公钥就是签名笔迹。一次签名只能签在一份文档上,其他人可以根据文档上的签名笔迹来验证真伪。


因为 A1 指定比特币支付到大雄的地址,所以只有使用大雄的私钥对新交易进行签名,才能使用 A1 代表的 0.1 比特币。


交易 B 有两个输出。其中一个输出把 0.05 比特币转给小福;而另外一个输出把 0.049 比特币转给大雄的另一个比特币地址。第二个输出就等于找零。

0.05 加上 0.049 等于 0.099,比输入少 0.001。 少掉的部分是本次交易的交易费。交易费付给比特币网络中的矿工。矿工是什么,为什么要支付交易费,以及交易费应该付多少,下文将会说明。

比特币钱包创建好这样一个交易后,就发送给它相邻所有节点。这些节点收到后,先验证交易是否有效(输入的总金额是不是大于输出的总金额,每个输入对应的 UTXO 是否存在,签名是否正确有效,等等),再发送给它相邻的所有节点。


交易在网络中的扩散


如图,橙色节点为接收到交易的节点,它们进一步向外发送。这样,交易迅速在比特币网络中扩散开来。


如果小福的钱包此时连上了比特币网络,会在很短时间内接收到扩散而来的交易。钱包识别出交易的一个目标地址是小福的地址,便显示给小福,告诉他收到了 0.05 比特币。只是这个交易尚“未被确认”。


未被确认是指这个交易还没有被放入区块链。未被确认什么风险?确认如何消除这个风险?交易是如何被确认?


要回答这几个问题,我们先回到交易被扩散的那一刻。


交易确认以及矿工挖矿


比特币网络中,有一些节点在从事“挖矿”的工作,它们被称为矿工。它们不停地尝试创建区块,并把成功创建出来的区块,发送给网络上的其他节点。

前文所述的交易 B(大雄向小福发起的支付交易)被网络中的矿工节点接收到后,就会被它们存下来作为备选交易。矿工根据自己的策略,选择一些备选交易(加起来大小 1MB 左右),组成候选区块,进行挖矿。挖矿,就是尝试把候选区块变成一个有效的比特币区块。矿工需要进行大量的计算工作,才有可能成功挖到一个新区块。


要创建一个有效的比特币区块,非常困难。
密码学中,有一类函数叫哈希函数。比特币系统中使用的哈希函数 SHA256 ,可以根据一段数据,求出一串 256 位的二进制数值(哈希值)。 这种哈希函数对输入值很敏感,只要源数据稍微修改一点点,得到的哈希值便大相径庭
一个有效的比特币区块,它里面的数据经过哈希计算之后得到的数值,必须小于某个特定值。这个特定值是每个节点根据当前一段时间内比特币网络的状态算出来的,决定了比特币挖矿的难度,
候选区块的数据,包括被组合在一起的交易,以及区块的基本属性。根据这些数据计算出来的哈希值,并不一定满足比特币区块的要求。
为了满足要求,矿工要在候选区块属性中加入额外的数值,以调整结果哈希值。由于哈希值变化非常敏感,它只能不停地试,从 0 到非常非常大的数,直到找到能使结果满足要求的数值。这些尝试,就是常说的 POW - 工作量证明,Proof of Work
当前(2018 年 3 月 14 日),平均挖一个区块,预期要进行 3,290,605,988,755.001 次计算。一个天文数字。这是根据最近一段时间比特币网络整体挖矿的速度计算出来的难度,目的是要把区块的生成,控制在大约十分钟一个。


平均下来,每十分钟,有一个新的区块在比特币网络中被创建出来。新区块的哈希值满足比特币网络的要求,它里面也包含它所指定的前一个区块的哈希值,用来确定区块链上区块的前后顺序。


简化后的区块链逻辑示意图


这些区块就这样前后链接,形成了区块链。在比特币网络中,第一个区块被称为“创始区块”。这个区块被直接写进了比特币程序的代码中。第二个区块包含了“创始区块”的哈希值,依次类推,第 N 个区块包含了第 N - 1 个区块的哈希值。


由于第 N 个区块包含第 N - 1 个区块的哈希值,如果第 N - 1个区块的数据被改变,其哈希值也将改变,第 N 个区块将不再指向它,区块链从这个位置断开。此时区块链的长度便减小。我们后面会了解到,较短的区块链将不被比特币网络接受。


如果要维持原来的区块链长度,数据篡改者必须把原来的第 N 个区块重新指向第 N - 1 个区块。这要求第 N 个区块里面的“前一个区块哈希值”更改为新的值。这样的话,第 N 个区块的数据变化,会导致它自身的哈希值不再满足比特币 POW 的要求。因此,这个区块的挖矿工作必须重做。同样的原因,第 N + 1 个区块也需要重新挖。因此,这种计算量是非常大的。


了解了区块链结构的基本知识后,我们回到之前关于矿工的讨论。当矿工成功创建出一个有效区块后,它立即发给相邻的节点。和交易被扩散一样,新的区块也被迅速扩散。


网络中的节点在接收到新区块时,立即验证区块是否有效(区块的哈希值是不是满足 POW 的要求,区块的大小是不是在可接受范围内,等等)。如果有效,除了把区块扩散出去,也会把这个新区块接到区块链上面。


如果新区块包含我们上面所说的交易 B ,它就被“确认”了。


照这么说,交易被确认只是时间问题。那确不确认有什么安全性的不同?


假设在发起对小福的支付交易 B 后,大雄想办法创建了一笔新的交易 C,把交易 B 指定使用的 A1 中的比特币支付到他另一个地址,并发送到比特币网络。这种行为叫“双重支付”。


比特币网络禁止这种双重支付,因此如果交易 B 已经被放进区块链了,交易 C 会被网络上的节点直接认定为无效。

但如果由于某些原因,交易 B 迟迟没有被矿工放进候选区块,导致 C 先于 B 被放进区块链的话,那么交易 B 将失效。因为节点们会认为 B 中所使用的比特币已经被 C 花掉了。

因此,一笔未被确认的交易,比起已确认的交易,它的可信度要低很多。


当涉及很大金额时,接收方可能认为交易被确认了也不够保险,至少要有多个确认,交易才可信。多个确认为什么更安全,将在下文中解释,现在我们先插个话题,介绍为什么矿工要竞争挖矿,因为这一点非常重要。


解决分歧,达成共识


矿工千辛万苦挖矿,是因为它们可以在新区块中,添加一笔特殊交易。这就是“铸币”交易,它可以无中生有地把一定数量的比特币发送到矿工随意指定的某个地址上,作为挖矿奖励。奖励包括两部分:一部分是特定数额的全新比特币;另一部分就是新区块中所有的交易费。


这个交易有一个专门的名字,叫 coinbase。比特币的产生只来自于这种交易。目前,每个区块都会产生 12.5 个新比特币。一开始,每个区块奖励的新比特币为 50 个,每新增 210000 个区块(大约四年)后,这个数量会减少一半,直到 2140 年,不再有新比特币产生。到时被产生的比特币总量约为 2100 万个,但因为各种原因,能流通的比特币可能远小于这个数。


因为新区块中交易数据的总大小是有限的,为了得到更高奖励,在挑选交易组成候选区块时,矿工通常会优先考虑交易的性价比。一个交易的性价比,由交易费和该交易的数据大小的比值决定。因此,使用比特币支付时,需要付出的交易费,跟交易中涉及的金额完全没有关系,只跟交易数据的大小有关。


矿工挖到新区块并在其中的 coinbase 交易指定了自己的奖励后,并不能立即保证这个奖励归自己。因为矿工的工作是独立开展的,有可能同时多个矿工挖到新区块。矿工要寄希望于自己的新区块能成为最终达成共识的区块链中的一部分。这样矿工的主人才算是拥有并能使用那些奖励。


因此,根据目前比特币的规则,coinbase 产生的比特币,要等 100 个确认之后才能被使用。


如果这些矿工都把各自的新区块发送到网络中,其他节点就会在短时间内先后收到多个区块。它们是并排,而不是前后连接的。它们指定的前一个区块是同一个。这个被指定的区块,便有多个后续区块,区块链产生了分叉。换句话说,此时出现多条链。

分叉的区块链


比特币矿工节点在处理这种冲突时,遵循的规则非常简单:优先选择最长的分叉;如果长度一样,选择先到的那个。这种规则并不需要硬性规定,只要每个节点从自身的利益出发,会自然地选择最有可能成为全网共识的那条分叉


矿工对分叉链的选择,不仅仅关系到验证新交易时会使用哪条链上的数据,更重要地是,它将会在这条链上继续挖矿。如果它选择的链没有成为最终共识,那么即便它成功挖到一个新区块,它在新区块中给自己创造的比特币奖励,也将不会被网络认可。

作为一个利益驱动的理性矿工,当在很短时间内收到两个并排区块导致区块链分叉时,它会认为先到的更有可能已经被扩散到了其他节点上。这是一个合乎逻辑的假设,因此它将“投票”给先到的那个。当它发现了两个不同长度的分叉链时,接在更长链后面,则无疑是更理性的选择,因为更长链上有更多已经存在的矿工奖励,代表了更广大群众的利益,会被更多的矿工支持。

我们假设有个区块几乎同时被两个节点挖出,并各自发送到网络中。由于它们所处的位置不一样,有些节点先收到 Y1,有些节点先收到 Y2,此时比特币网络分成两部分,这两部分没有达成共识:

有分歧的比特币网络


橙色矿工们决定把票投给 Y1,而蓝色矿工把票投给 Y2。网络分成两个阵营,继续挖矿。如果蓝色阵营中某个矿工挖出下一个节点 - Z2,它会立即把新区块扩散给网络中所有的节点。


当橙色阵营的节点收到 Z2 时,它们发现 X -> Y2 -> Z2 这条链,比原先支持的 X -> Y1 更长,出于理性的考虑,它们会立即转向 X -> Y2 -> Z2,并接在 Z2 后面挖矿。此时网络便达成了共识。


达成共识的网络


也有一定可能会出现橙色阵营和蓝色阵营几乎同时挖出 Z1 和 Z2 的情况,那么分歧将依然存在。这种情况的概率很小,而且在第三轮挖矿中,共识仍然会大概率被达成。因此只要所有矿工都按这种自利的方式行事,比特币网络总能在很短的时间(十几二十分钟)内达成全网共识。


根据上面的设定,假设有些交易存在于区块 Y1 ,但不在 Y2 或者 Z2 中。那么,对于橙色阵营来说,这些交易,曾经是存在于区块链,有 1 个确认的,但是最终共识达成时,它们都从区块链中被删除了,变成了未被确认的状态。更糟糕的情况是,如果在 Y2、Z2 中存在把它们双重支付掉的交易的话,它们将变成无效交易。


因此,即使在比特币网络正常工作的情况下,区块链上的数据,也不是“百分之百不能被修改”的。越早期的区块,确定性越大,越新的区块,确定性越小。随着时间的流逝,一个区块“不会被移出”的概率,成指数级增长。用地壳来比喻比特币的区块链,越古老的地层越稳定,越新的地层则越可能会发生变化。


如果小福看到大雄支付给他 0.05 的交易被确认了,代表他钱包邻近节点认可的有效区块链,包含了交易 B。这些节点会在这条链上继续挖矿。如果这条链上再增加一个新区块,这笔交易便有 2 个确认;再增加 N 个区块,便有 N + 1 个确认。

得到确认越多的交易,在比特币中越安全,越不可能从区块链中被删除。

因此,当交易涉及的金额非常大时,接收方最好是等待几个确认。一般来说,等一个小时,6 个确认后,交易被更改的概率就会变得非常低。


至此,我们知道组成比特币网络的节点,都从自己的利益出发,在没有任何中心化组织协调的情况下,是如何共同记账的。


由于比特币网络是一个公开的网络,没有进入门槛,没有人能保证参与其中的节点都是诚实、没有恶意的。如果有节点想要做坏事,它们能做哪些坏事?做坏事需要多大的成本,能够得到什么收益?这些坏事,会对比特币网络造成多大的破坏?


我将在 比特币没你想的这么“去中心化” 一文中进行探讨。


最后,我们来回顾一下涉及到的主要概念和事实:

  1. 比特币网络是一个公开的点对点网络。网络中的节点是平等的。任何人都可以参与这个网络。
  2. 比特币体系中,用于记账的单位是只有一笔一笔的交易。交易有输入和输出:输入指定比特币的来源,通常是之前某一个交易的输出;而输出指定比特币的去向以及涉及的比特币金额。输出指定的去向通常是某人的比特币地址。
  3. 一个交易的输入,要使用之前某一个交易的输出作为比特币的来源,必须提供有效数字签名。这个数字签名的作用是解锁该交易输出代表的比特币。数字签名必须由地址对应的私钥生成。对这个私钥的拥有,代表了对该比特币的使用权。
  4. 如果一个交易的输出,已经被另一个交易使用了,它将不能再用在其他交易中。这是比特币规则中为避免“双重支付”做的设定。
  5. 如果一个交易的输出,还没有被任何交易使用过,这种交易输出叫 UTXO。比特币就存在于 UTXO 中。你拥有 10 个比特币,对于比特币网络来说,等价于,你掌握的私钥能够解锁总值为 10 个比特币的 UTXO。
  6. 比特币中,交易被存储在区块链中。区块链是由许多个逻辑上彼此前后相连的区块组成。这些区块都通过指定前一个区块的哈希值,来确定前后顺序,这个哈希值也保证了它前一个区块的数据没有被修改。第一个区块被称为“创始区块”,这个区块的数据被写入了比特币的程序中。
  7. 区块的哈希值有特殊的要求。它必须小于某个特定值。这个特定值在生成的时候由当时全网的计算能力决定,为了区块在大约每十分钟左右被生成一个。
  8. 比特币网络中任何节点,都可以发起一次交易。任何节点发起的交易,都会被扩散到整个网络中。网络中有矿工节点,这些矿工节点在接收到交易后,会把交易作为备选,用于挖矿。
  9. 矿工节点挖矿时,根据自身策略选择一组备选交易,组成候选区块,并在区块中添加额外的随机值,以便让区块的哈希值满足要求。这个工作需要花费大量的计算。当矿工成功得到满足要求的哈希值时,便把新区块发送到网络中。新区块的数据可以证明矿工挖矿所进行的工作,因此这种方式叫工作量证明, POW。
  10. 如果一笔交易被放进新区块中,成为区块链的一部分, 那这笔交易便是被确认了。一笔交易获得 N 个确认,表示它所在的区块后面已经有 N - 1 个有效区块在区块链中了。
  11. 矿工在新区块中,可以添加一笔特殊的铸币交易,把一定数额的比特币支付到自己的地址,作为挖矿奖励。这里面包含特定数额的全新比特币,以及区块中所有交易支付的交易费综合。
  12. 比特币只通过挖矿产生。一开始,一个新区块能产生 50 个新比特币,之后每产生 2100000 个区块(大约四年)后减少一半。直到 2140 年,不再有新的比特币产生。到时被产生的比特币总量为 2100 万个。但由于各种原因,能流通的数量可能远小于这个数。
  13. 矿工竞争挖矿,有可能会同时挖出新区块发送到网络中。接收到多个区块的节点,看到区块链产生了分叉。节点在处理这种冲突时遵循简单的规则:优先选择最长的分叉;如果长度一样,选择先到的那个。节点都遵循这种简单的规则,能让比特币网络很快重新达成共识。
  14. 由于可能产生分叉和竞争,最新的比特币区块是不稳定的。越古老的区块越稳定。稳定的意思是,区块上不会被移出共识区块链,区块上的交易不会被“删除”。


区块链技术将带来深远的影响,整个领域的研究和发展还处在非常活跃的阶段,值得我们持续参与。接下来我们会从不同角度写一些关于其他公有区块链技术以及应用的文章,欢迎加入群蜂社,共同讨论和学习。