捋一捋比特币的实现思路
前言
比特币的概念很多,每个理解起来都挺费劲。以至于比特币科普牛人——汤强老师解释其中的任何一个概念的时候都需要用一大篇文章来解释。
但是好不容易单个概念弄懂了,又不明白中本聪为什么要这么设计。不识庐山真面目,只缘身在此山中。当我们钻进细节中的时候,反倒迷糊了。
所以我们可以先知其所以然,然后再去探究细节本身的时候就会轻松很多了。下面我就尝试忖度一下中本聪大神是如何一步一步设计出整个比特币系统的。
由于本人水平有限,改了几遍,发现还是有些地方说的不清楚,但是又不知道怎么改更好,大家凑合读吧。只希望给大家换个角度看问题,能有一些启发。
实现思路
那我们就从中本聪要实现的目标出发。如比特币白皮书的标题所示,比特币的目标是:比特币——一种点对点的电子现金系统。
1
点对点,意味着不能有第三方机构来确认交易,那么就需要有一个只能添加数据和查看数据的记账系统(数据库系统),添加完了以后就不能修改和删除了。
2
为了实现这个目的,这个记账系统需要是分布式的,这样就没有人可以一下子修改全部的节点上的数据了。
节点是分布式的,就需要用P2P技术进行数据的同步。而P2P技术的直观感受就是——我们经常用种子下载电影的那种技术。
3
为了让数据不能被修改,那么需要把一段时间的交易数据放到一个盒子里,然后想办法把这个盒子存起来,不让人修改,这个盒子就是区块(block)。
4
单个的放数据的区块还是可以人为的修改,那么就需要想办法把单个区块前后串起来,修改其中任何一个,后面的就连不上了,从而保证任何一个块一旦放到链当中就不可修改了。
5
用于连接的这个链,就是在后一个区块中保存前一个区块的哈希值。这样,改动了前一个区块中的任何一个数据,它的哈希值都会发生巨大的变化,就会和后一个区块中所保存哈希值不相等。
所以,链入区块链中的区块是无法修改的。
至此,区块链的雏形已经出现了,下面要解决的是转账的问题了。
6
为了保证转账的可靠性,用非对称加密的解决方案最好。首先在一个很大的范围(0-2^256)设置一个私钥,根据概率学的原理(在附录中说明),不可能有两个人会有相同的私钥,然后用这个私钥给交易签名。查询和确认交易的人只需要用私钥对应的公钥进行解密就可以了。
7
下面要解决的就是记账的问题了。记账虽然也是机器处理的,但是每个节点的机器背后还是一些活生生的人,要想让他们不作弊,就需要给予诚实的记账以奖励,同时也保证了这个系统中的货币的供给。这就是比特币节点挖矿奖励比特币的原因了。
一个节点取得了记账权,如果他好好记账,那么就可以拿到奖励,如果有了记账权,却故意记错了账,那么这个奖励就没有了。
8
记账有奖励,那很好,人人都想记账,所以得想个公平公正的法子去争夺记账权了。于是就需要设计一个“共识算法”——让所有节点都能达成共识,同意用这样的方式来解决问题。
9
那就随机呗,掷骰子。在加密的世界里,哈希算法就是很随机的掷骰子的方式。账记完了,那我们就用这个账本的内容,加上一个随记的数字,去掷骰子(哈希计算),保证他们合在一起的哈希值前面有几个零,谁先找到这个哈希谁就有记账权。这个很公平随机,不过谁的电脑计算的快就能更大概率地找到这个随机数,但是只要方法是公平公正的,硬件问题就需要记账的人自己解决了。大家都升级硬件,只要每次奖励的比特币够硬件升级的花费就行。
10
记完账,问题又出现了。如果有人几乎同一时间画出两笔BTC,而这个地址的余额又不够同时支付两笔交易,怎么办?中本聪的办法就是看交易的时间戳,哪个先发生就以哪个为合法的交易。
还有一个问题,如果由于网络问题,上面所说的两笔交易被不同的矿工几乎同时打包进区块又怎么解决呢?中本聪的办法是随它去,让区块自由生长,最终以增长快的链为准,废弃短的链。
以上解决问题的办法看似不怎么负责,但是却是解决问题最简单有效的途径。所以我们在转账最终到账需要若干个区块的确认。因为当出块的数量达到一定数量的时候,即使有分叉的链也不会比当前的链长,会被废弃掉,从而使当前最长链中保存的交易也就不可篡改了。
11
继续看矿工的选择。好不容易轮到一次记账权,只要诚实记账就有奖励,谁也不会乱记账。即使有位作恶的矿工乱记账,但是如果他算力不够大,不能保证一直在错误的链上记账下去,把错误的链打造成最长的链,也不会作恶成功。最终不仅作恶失败,还失去了记账的奖励,赔了夫人又折兵,正常人都不会去做的。
12
如此这般,比特币的系统差不多设计完成了。但是还有一点漏洞,如果作恶的矿工不仅坏,还拥有了超过了51%强大的算力,为了谋取自己的私利,故意记错账,怎么办呢。这个时候,由于比特币会选择最长的一条链,拥有超过51%算力的矿工可以制造出一条错误的较长的链,虽然颠倒黑白了,但是别人拿他也没有办法了。这个时候,作恶的矿工虽然拿到了双重支付的好处,但是却破坏了系统,会导致币价大跌,作弊弄来的比特币也不值钱了,连手上花重金买来的矿机都成废铁了。
所以,即使拥有超过51%算力的矿工也不会做损人不利己的事情,放弃作恶的行为。所以至今为止都没有出现拥有巨大算力而为所欲为的矿工,因为他被绑定在了比特币系统了,只有整个系统好他才会受益。
小结
至此,整个比特币系统的设计算是复盘完成,能顺利实现一种点对点的电子现金系统的意图了。其他的技术细节,如merkle树,UTXO等,都是让整个系统更巧妙的锦上添花的设计。
我们复盘一下都是如此艰难,真不到中本聪大神当年是怎么想到把这么多技术和思想杂糅到一起设计出这么精妙的系统的。
想实现不可篡改的数据库系统似乎没有那么复杂。但是要结合密码学、经济学等因素防止恶意破坏的交易者和矿工却是花费了很多考虑。这也是比特币能稳定运行这么多年的关键——用代码的规则去惩恶扬善。
附录:概念简单解释
1.数据区块:
比特币的区块链中记录数据的单个区块。
包含当前版本号(version)、前一区块的哈希(pre-block)、时间戳(timestamp)、随机数(nonce)、当前区块的哈希值、merkle树(merkle-root,类似纸牌屋)的根值。
2.挖矿:
找到随机数(nonce)值,使得区块高度+前一区块的哈希值+时间戳+当前区块的数据+nonce的哈希值满足一定的规则,也就是区块难度,哈希值的前面有若干个零。哈希不可预测,所以nonce只能一个个数字尝试,直到找到为之。
3.时间戳:
时间戳是指从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。每个时间点是唯一值。防止双重支付的时候就是根据这个时间戳判断,时间靠前的交易生效,时间靠后的交易无效。
时间戳的值在世界各地的同一个时间都是相同的,与时区无关。每个时区的时间就是通过时间戳加上时区换算而成的。
4.分布式(Decentralized)数据库:
每个挖矿的节点保留了所有的交易数据,当一个节点被破坏不影响整个数据库的运行。
其中,英文原文为“decentralized”,翻译为分散式,或者叫分布式,现在却被翻译成去中心化的,造成很多问题。
分散式的,可以有一个或多个中心节点,权限比较大。去中心化,似乎就不能有中心了。目前比特币矿池算力集中,不是很去中心化,但是还是分散式的。大家都在争论的是否“去中心化”本身就是个翻译的谬误,失之毫厘,差之千里。
5.UTXO(unspent transaction output):
未花费交易输出,计算某个地址的比特币数量,只是统计这个地址汇入的,但是还没有花出去的比特币。如果一个地址有100条交易,需要记账100次,但是记账未花费的交易输出就简单了,搜索一下一个地址上的未花费的交易输出就可以了。一个地址的总的UTXO可以理解为每次交易后余额的汇总的值。
所以BTC转账的记录的方式就比较奇怪了,每次转账都会把一个账户的UTXO收集起来。比如转账1BTC,可能会收集这个地址的1.1个BTC,转1个BTC到目标账户,剩下的除去一部分旷工费,然后转到自己的地址,也就是“找零”。
一开始我对“找零”这个说法感到特别奇怪,理解了UTXO后才明白比特币为什么会有“找零”。
总而言之,设计UTXO这个概念的目的是为了节省硬盘存储——不需要记录每一次转账的过程,只需要记录转账的结果。
6.哈希:
SHA256算法,任何数据都可以转化为一个长度为256的二进制数字。这有点像数学中的求余数,再大的数,除以一个2256后的余数一定是在0和2256之间的数。不过哈希算法要复杂很多,因为要尽量避免不同的内容计算出的哈希值重复。
7.merkle数:
一种数据结构。
有点像纸牌屋,最底下的牌代表了每一笔交易,上面纸牌是紧邻的下一层的哈希值,最终只保存最上面一个点的哈希值。任何一笔交易数据的改动都会导致最上面的点的哈希值的改变。就像纸牌屋搭好了,不要妄想动任何一个最下面的纸牌,因为一动就全部倒了。
主要目的是为了保证数据的可靠性,顺带节省存储空间。
8.双重支付:
只记录最早的交易。实际过程中需要考虑分叉、孤块、确认等的问题,但是核心的原则只有一个——如果花费的钱超过地址上的余额,只记录最早发起的那一次交易。
9.P2P网络:
这个概念很早就有了,迅雷等下载软件用的就是P2P技术,网络中每个节点的地位相等,更新数据的时候从相邻的电脑下载即可。这个技术保证了比特币的账本资源在每个用于挖矿或者是记账的全节点中都是一样的,同时任何一个节点被破坏了,也能从相邻的节点重新下载账本数据。
10.非对称加密:
以往的加密方式,加密的密码和解密的密码是相同的。非对称加密的特点就是加密和解密的密码不同。用私钥进行加密就只能用公钥进行解密,用公钥进行加密只能用私钥进行解密。这就保证了用某个地址进行交易的时候只有私钥的拥有者才能发起交易,而其他人用公钥就能查看交易。公钥和地址都是可以用私钥计算而得出,反之却无法计算出来。
私钥是在一个很大的范围(0-2256)内随机选择的。而2256是一个非常大的数,仅比整个宇宙的原子数量少几个量级。这个范围内遇到重复的私钥的概率比这个概率还要小:一个不知道在宇宙的某个角落有个外星人,把一颗写上他名字的玻璃珠随手扔到太空中,然后我们地球上的人在茫茫宇宙中找到这颗玻璃球。
科技发展,这么多年都没有发现外星人,更别说找到那个特定的不知道在宇宙的某个角落的玻璃珠。所以这是不可能事情。所以地球上的人会遇到两个同样的私钥的可能性比这件事的概率还要低。
11.数字签名:
数字签名就是用私钥对发送的交易进行签名加密,保证这个交易是由私钥持有者发出的,矿工验证的时候只需要用私钥对应的公钥进行解密就知道数字签名是否有效。没有用私钥进行签名的交易就没有权限花费这个私钥对应的地址上的UTXO。