区块链技术入门学习笔记。
系统讲解
区块链前世今生
密码朋克(Cypherpunk)邮件组成员:
- 维基解密的创始人——阿桑奇
- BT 下载的作者——布莱姆·科恩
- WWW 的发明者——蒂姆伯纳斯·李
- 智能合约概念的提出者——尼克·萨博
- Facebook 创始人——肖恩·帕克
- 中本聪
在这个邮件组里,就讨论了关于数字货币的问题,这些给了中本聪很多的灵感和技术的铺垫,比如:
- Adam Back 发明了 Hashcash,使用了 POW(工作量证明);
- Haber / Stornetta 提出时间戳方法保证数字文件安全的协议;
- 戴伟发明了 B-money,强调点对点交易和不可更改记录;
- 哈尔·芬尼推出了「加密现金」;
在这些前人的铺垫上,中本聪于 2008 年发表了一份白皮书《比特币:一个点对点的电子现金系统》,创建了一个完全去中心化的电子现金系统,并在 2009 年挖出了 50 个比特币。用来实现比特币的上述的这些技术,不单单能用于数字货币,也可应用于其他领域,这些技术经过后人综合提炼后被统称为区块链技术。「区块链」名称的由来,是因为比特币系统里面的数据,是由一个个区块来存储的,并且通过 Hash 的方式将这些区块链接起来,由此形成一个区块的链条。
区块链前景
区块链的应用场景有:
- 资产:数字资产发行、支付(跨境支付)、交易、结算
- 记账:股权交易、供应链金融、商业积分
- 不可篡改:溯源、众筹、医疗证明、存在性证明
- 点对点:共享经济、物联网
- 隐私:匿名交易
比特币是什么
Point1 是一种数字货币
在凯恩斯《货币论》里,货币被定义为是可以承载价值的一般等价物,我国的货币历史从铜币、金银发展到银票、法币,不同的地方在于纸币是一种信任货币,纸币本身没有任何价值,它的价值来源于人们对它的信任。同理,当一串数字可以当做货币的时候,并且大家都认可它,它就被称为数字货币,或虚拟货币,它的价值同样来源于信任,这种「信任」在区块链里被称为「共识」。
那比特币的这种「信任」从何而来?
- 财产只受自己控制,或者说只受自己的私钥控制(不像现实中的银行可以冻结我们的钱);
- 无通胀,比特币的总量是不变的,2100万个(不像纸币会因为银行发行更多的钞票而贬值);
- 没有假钞,因为任何作弊的支付都无法得到比特币网络中其他矿工的确认,从而无法支付;
- 流通性好,全球无缝流通,可以点对点直接到账(不像现实中的跨国汇款有许多中间环节)。
Point2 是一个去中心化的记账系统
中心化的系统会有一个中央的服务器/数据库,来存储所有的数据。比特币与之相反,它将数据存储在比特币网络中的每一个节点里,也就是说每一个节点都会存一份账本数据。这里有个问题,如果某一个节点的账本和其他节点的账本不一样,此时该用谁的账本呢?这涉及到比特币的原理。
比特币的原理
Key1 账本如何验证?
有这样一种情况:在比特币系统中,每一个节点/服务器都会存一份相同的账本数据,如果有人想拥有更多的比特币,然后他私自修改了其中某一个节点的账本数据,此时我们该如何证明这个账本还是有效的呢?或者说如何才能发现这个账本是不是被篡改过了的?
方案一
把这个账本和剩下的其他账本数据一一核对,一旦发现不同,使用少数服从多数的原则(此方案要跟海量的节点和记录作比较,效率太低,行不通);
方案二
用 Hash 函数:Hash(原始信息) = 摘要信息,比如 MD5 就是一个哈希函数(可用来校验下载的文件有没有损坏),哈希函数的特点有:
- 同样的原始信息用同一个哈希函数总能得到相同的摘要信息;
- 原始信息任何微小的变化都会哈希出面目全非的摘要信息;
- 从摘要信息无法逆向推算出原始信息。
利用哈希函数的这些特点,可以简化比对账本的过程。首先对校验账本进行 Hash,得到一个摘要信息,然后再跟剩下的其他账本的摘要信息作对比即可。
Hash 值、时间戳、序号、交易记录,这四者就会形成一个区块,其中的 Hash 值、时间戳、序号被称为区块的头信息。比特币的记账时间大概是每十分钟记录一次,假设十分钟后来了一个新的账本,序号为 1,那么在对新账本进行 Hash 的时候,新账本的原始信息不仅包含它自己本身的记录,而且还会加入序号为 0 的账本的摘要信息 / Hash 值,两者合在一起作为新账本的原始信息,再进行 Hash。有了新账本的 Hash 值后,就形成了第二个区块,以此类推,从而产生无数个区块,由 Hash 值串联起来(存上一个区块的 Hash 值),像链条一样。核对账本的时候,只要最后一个区块的摘要能对上,就说明整个区块链的账本是正确的。
注意:在中心化的系统里面,存储的都是最终的数据,且只有一份,一旦被人篡改,是无法验证其真实性的。
Key2 账户所有权问题?
也就是如何确定某个账户下的比特币是属于谁的?或者说谁可以支付这个账户下的比特币?
首先来了解一下现实中的银行是如何处理这个问题的:我们平时在用银行卡的时候,需要两个东西,一个是银行卡,另一个是密码,如果银行卡号、密码和系统里的对上了,就可以付款。那么如果我的银行卡丢了,或者密码泄漏了,然后被别人盗刷,这个时候怎么证明刷卡的是别人而不是我自己呢?首先报警,然后银行会核对我们的账户所有者等信息,靠什么核对呢?靠的是我们在银行开户的时候输入的那些个人信息。当我们在银行开户的时候,我们的个人信息就跟银行卡账号绑定在了一起,我们也就拥有了这张银行卡的所有权。
而在比特币系统里面,由于是点对点交易,没有银行这样的第三方参与进来,所以比特币的账户跟我们的个人信息没有任何绑定关系,它的所有权,是通过私钥确定的。在比特币系统里,账户是用一个地址来表示的,一个地址会有一个对应的私钥,谁拥有了这个私钥,谁就能用这个地址支付,谁能用这个地址支付,谁就拥有这个账户的所有权。因此,转账的过程就是把比特币从一个地址转到另一个地址,而账本上不会保存任何的个人信息,这很好地保证了比特币的隐私性,比如像下面的这样一条信息就是一条转账记录:
私钥和地址之间的关系是一种非对称关系,私钥在经过一系列的 Hash 运算之后(其中包括两次 Hash),可以得到比特币的地址,但是不能由地址反推出私钥:
所以,私钥非常重要,一定要保管好,只要私钥没泄漏,比特币的安全就是掌握在我们自己手里的。私钥一旦泄露,比特币有可能会丢失,而且丢失之后没法重置,也没法找,这不像现实中的银行可以帮我们重置密码,找回损失。那么在没有泄露私钥的情况下,如果我们现在在比特币系统中转账,其他的节点又是如何确认这笔转账交易是合法的呢?这里要用到非对称加密技术,在转账时,首先会对交易进行签名:
- 对原始交易记录进行 Hash 运算得到摘要信息;
- 用私钥对摘要信息进行签名得到签名信息(此步要在安全环境下,避免私钥泄漏)。
签名之后,付款的节点就会在整个网络中进行广播,让其他相邻节点来验证,这是一个循环的过程,当相邻节点收到广播且验证通过之后,它会再次对与之相邻的节点再次进行广播,直至所有节点验证通过。广播的内容包含两部分:
- 原始交易记录;
- 签名信息。
验证过程:
可以发现,签名和验证是一个逆运算,可以将付款地址理解为公钥,签名的过程是对摘要信息进行加密的过程,验证是对签名信息解密的过程(除了上面介绍的步骤外,在实际验证的时候,还会验证付款账户有没有足够的余额等等)。
Key3 为什么要记账(挖矿)?
记账是一个将交易记录、时间戳、序号等信息进行 Hash 打包的过程,它会消耗计算机的资源。
既然需要付出成本,那么节点为什么要参与记账呢?那是因为在比特币系统的设计里,完成记账的节点可以获得系统一定数量的比特币奖励,这个奖励机制就是比特币的发行过程。假设在某一时期,记账的奖励为 12.5 个比特币,这相当于 50 多万人民币,如此大额的奖励引起人们争相地去记账,而当大量的节点去同时记账时,将会造成冲突、记账不一致的问题。为了解决这一问题,比特币系统制定了如下规则:
- 一段时间内只能有一人可以记账成功(一段时间通常是十分钟);
- 通过解决密码学难题(即工作量证明)来竞争获得唯一记账权;
- 其他节点复制由前面两步得到的记账结果。
前两个规则会相互影响,由于工作量证明具有随机性,且有概率获得奖励,因此形象地把记账的过程称为挖矿。
解决密码学难题的过程是这样的:在讲账本验证的时候,讲到每次记账的时候是把上一个 Hash 值和当前的交易记录放在一起作为原始信息后,再进行 Hash,如果仅仅只是这样的话,那记账就太简单了,为了保证一段时间内只有一人可以记账成功,必须要提高记账的难度,因此又制定了相应的规则:计算出的 Hash 值必须要以 n 个 0 开头。这就需要给原始信息中再加入一个随机数,然后不断改变随机数的值,直至找到一个符合规则的 Hash 值:
现在的电脑要计算出一个 4 个 0 开头的 Hash 值,大概需要两分钟,率先找到满足要求的 Hash 值的节点就可以获得唯一记账权。获得唯一记账权的节点会把整个这笔交易打包成区块放入到区块链中,然后自己获得这笔奖励。上图中原始信息中的「交易记录集」是这样得到的:
- 首先收集广播中还没有被记账的交易;
- 然后验证这些交易的有效性(也就是前面讲到过的验证交易是否有正确的签名、是否有足够的余额等);
- 验证通过后,系统会在交易记录集里面添加一笔给自己地址转账的交易(也就是挖矿奖励,比如目前是给自己的地址转 12.5 个比特币)。
现在由于参与比特币的矿工越来越多,算力越来越大,现在的挖矿规则已经增长到要以 18 个 0 开头才行(Hash 值是一个十六进制的字符串,所以理论上要进行 16 的 18 次方次 Hash 运算才有可能得到 18 个 0),如此大的工作量需要投入大量的设备,同时也要消耗大量的电力,所以目前已没有独立的矿工去挖矿,因为可能几十年也算不出来符合要求的 Hash 值,现在都是矿工联合起来组成矿池进行挖矿,矿池里面的矿工按照算力的百分比进行收益的分成(从经济学角度来讲,只要挖矿还有收益,就总会有新的矿工加入来加剧竞争,这样就导致算力的难度再次提高,需要消耗的算力和电力变得更多,这两者相互作用,最终会让挖矿的成本接近收益)。在中国,电力成本比较低,所以相对收益更高,现在中国的算力占据了整个网络的一半以上。
Key4 以谁的账本为准?(共识机制)
在工作量证明的时候,每个矿工都是独立地完成工作量证明,那么如果有两个节点同时完成工作量证明,这个时候该用谁打包的区块呢?比特币是没有第三方的仲裁机构帮我们做裁决的,比特币系统通过共识机制来解决这个问题(共识就是说大家都去遵守的一种规范或协议,遵守协议的原因是节点的工作量只有在其他节点都认同、验证通过的时候才是有效的):每个独立节点只认可累计工作量最大的区块链,或者说每次总是选择最长的链去挖矿,然后延长最长链。共识机制最终的目的是要保证比特币不停地在最大工作量的区块链上运转。
举例:如果有两个节点同时完成工作量证明,打包好的区块分别为 A 和 B,那么在广播的时候,有的节点会先收到 A,从而认为 A 所在的链是最长链,有的节点会先收到 B,从而认为 B 所在的链是最长链,也有的节点会 A、B 都收到,此时会对两者进行工作量的比较,然后选择其中一条为主链,另外一条为备用链,链由此产生了分叉。在后续不断地进行工作量证明的过程中,A、B 所在的链总会有一条链先发现新打包好的区块 C,从而形成更长的链,分叉问题也就自然而然解决了(因为网络的不确定性,有的时候节点会先收到区块 C,后收到区块 A 或 B,这时候区块 C 会被当做孤块放到孤块池里,一旦收到 A 或 B,它就可以把各个块串起来)。
比特币将出块间隔设计为十分钟,其实是在更快地交易确认和更低的分叉概率间作了妥协,更短的出块间隔会让交易更快地交易完成,但会导致频繁地产生分叉,反之,更长的间隔减少分叉的数量,但会导致更长的交易确认时间。
实现 + 实战
待思考的问题:
(1)比特币 P2P 网络(节点之间如何通信?因为在比特币网络中无法事先知道其他节点的 IP);
(2)区块结构 Merkle 树(一种保存交易的数据结构,让交易更容易验证);
(3)比特币 UTXO 及交易脚本(每一笔交易都要用脚本去验证 UTXO);
(4)比特币白皮书。