最近几期阅读量似乎锐减,大概因为我大谈特谈枯燥的密码学。好在最基本的技术干货算是有过交代了,现在开始用它来做菜,第一道大菜,咱们也学学怎么做一个加密数字货币!
一、加密数字货币的样子
很多朋友谈到比特币,还以为就是图片中那种金灿灿的金币呢。这些朋友可真需要从头看这个漫谈系列,了解一下加密数字货币到底在货币史中处于什么样的历史阶段或地位,我想您一定有收获,如果觉得脑洞大开那就恭喜你突破思维禁锢了。
在第二篇《货币起源的技术路线》里我简单结合货币史说了货币实现的两种路线,其中加密数字货币就是指在网络中实现像真实世界黄金一样的东西,但这样东西到底该是什么形式的存在呢?
带着这个问题我们进入第三篇《“密码朋克”用了二十年打造出第一个成功的密码货币-比特币》。介绍了密码朋克的专家们前仆后继探索了二十年,才弄出了一个叫比特币的东西。可见,加密数字货币一定不是谁随便就能想出来的,同样加密数字货币也一定不是谁随便看看听听就知道是什么东西的。尽管去了解一样东西会比发明这样东西要简单得多,可是当你知道史上只要因为密码留名的,必定是天才中的天才,精英中的精英,这些绝顶聪明的脑袋们用了20多年才发明出来的东西,咱们希望能一下子就秒懂速成,显然是不可能的。
进入第四篇《“区块链”其实就是一种数据结构》到第八篇《数字签名技术是“萝卜章”终结者》,我开始直线掉粉了,因为触及到许多人都畏难的密码学部分。我其实介绍得并不深,一来我掌握的也是皮毛,二来区块链用到的密码学真的很容易懂。没有这些基础的密码学知识,也许未来你有可能发现被时代抛弃了。
在这二十年里,这些专家可谓是各种奇思妙想。但是最开始,也是最基础的部分,几乎所有人都想到模仿纸币出现时的样子来设计加密数字货币。我们来设想这样的场景:阿土伯开了个钱庄,当约翰乔去存100两银子的时候,阿土伯便取来一张纸条,写上“拿到此条之人可以到我这里来换100两银子”,然后签上自己的名字给约翰乔当收据。假如钱夫人、孙小美等信任阿土伯不会食言且阿土伯的签名无法伪造,她们就接受这个纸条,约翰乔可以就用它当作100两银子去钱夫人和孙小美开的商场里买买买。事实上,纸币最初就是银行(古时候叫钱庄)发放的支付承诺,只是到了近代,政府才介入进来接管了货币发行。
北宋的“交子”
如果把阿土伯纸条上的字作为一个信息数据在计算机上写下来,同时阿土伯采用我们上一篇谈的签名技术对这个信息数据进行数字签名,然后一并发布出去。这就在形式上实现了纸币的雏形样子,而且数字签名技术可是比现实纸上签名更有防伪能力。
有了这个思路,加密数字货币最核心的部分,或者说最小单元应该是”信息数据+数字签名“。而现实世界最小币值的那枚金灿灿的实物在数码世界里被一个有特殊结构的数据取代了。有了第一步的思路和抽象数据结构,那么我们就着手来设计制造一种数码虚拟货币,我们要解决两个最基本问题,能够造出来并且花出去。
二、GoofyCoin(高飞币)——史上最简单的加密数字货币
(本部分关于高飞币应用实例以及插图均来自普林斯顿大学Arvind Narayanan, Joseph Bonneau, Edward Felten, Andrew Miller, Steven Goldfeder等四位教授编著的网络课程教材《Bitcoin and Cryptocurrency Technologies》,本人重新改写,特此注明,请转载者也注明出处)
我们给这个货币取名为GoofyCoin(高飞币),它只有两个规则:
1、Goofy可以随时创造新币;
2、拥有此币的人可以转给其他人。
另外记住,我们是要在网络上实现,一些都是数字化的。好,我们现在开始造钱啦!
高飞币交易过程示意图,我们需要从下往上看
Goofy首先凭空创造了一枚货币(CreateCoin),并随即选择了一个唯一的货币编号(uniqueCoinID),创造货币的过程在计算机网络上其实就是一句命令,我们可以看成是最下面框的下半部。然后Goofy对这句话进行签名,形成了一个签名数字串,把两部分合并成一个创造货币的记录。此时,新造出来的这枚虚拟货币属于Goofy自己。
现在Goofy想把这枚货币转给Alice。他直接把Alice的公钥(pk,我们介绍不对称加密时说过公钥=身份=账号)当作她的账号,然后发布了一个声明“将此币支付给Alice的公钥”,“此币”就是哈希指针,是对Goofy创造货币的整个交易记录(最下面的整个框)进行哈希计算得到的。最后Goofy再对这个转账交易的声明进行签名,并与转账交易申明合并成一条转账交易记录发布出去。此时,这枚虚拟货币就属于Alice,不再属于Goofy了。
当Alice想把这枚货币转给Bob时,她就像Goofy转账给她一样,发布一个声明“将此币支付给Bob的公钥”,此时哈希指针的哈希值是对她得到这枚虚拟货币的交易记录(中间的整个框)进行哈希计算得到的。随后Alice再对这个转账交易的命令进行签名(用的是Alice自己的私钥),并与转账交易命令合并成一条转账记录发布出去。于是,这枚虚拟货币就变成Bob的了。
这里我们看到哈希指针把虚拟货币从创建到支付的所有过程全部串起来,得到支付的人很容易就能验证这枚货币到自己手中的过程是不是有效。但是,这种最最简单形式的虚拟货币有个致命弱点,也是加密数字货币需要解决的第一个重大问题——双重支付问题(double spending,也有中文翻译为“双花”)。这种问题在现实世界中并不是主要问题,甚至不是问题,可是数字世界复制实在是太简单了。当Alice支付给Bob之后,她可以对这枚货币做同样的操作再支付给Chuck。
双重支付(Double Spending)
Bob和Chuck收到Alice同样来历的虚拟货币时,按照哈希指针校验都是合法的有效的,但是显然Alice可以无限制的重复使用下去。而Bob、Goofy和Chuck也可以如法炮制,大家一起花花花买买买,其实都反复花同一枚虚拟货币。可见,这个虚拟货币体系注定是失败的,或者说是不完善的。尽管如此,这种以私钥签名来确认交易申明方式还是可取的。那么我们现在要对这个高飞币进行改造来解决双重支付问题。
高飞币为啥对付不了双重支付问题呢?我们总结下来是校验机制有不完善的问题。高飞币的校验方式只是证明了这枚虚拟货币是根正苗红的,但无法查证这枚货币有没有被复制到其他交易链条上去。
完整的验证必须对全部交易历史和路径进行验证。对于高飞币,补救的办法就是需要Goofy从启动发行虚拟货币开始,提供所有的交易记录或者总账本供大家校验。只有这样Chuck在收到Alice支付的虚拟币时,不仅可以校验这枚币是不是从Goofy那里发行出来的,还能检查这枚虚拟币有没有在到他手上之前被支付过。现在他就能发现已经支付给Bob了。
三、流水币——基于流水帐的加密数字货币
明确了这个思路,我们淘汰掉Goofy,由阿土伯出场来发行升级版的虚拟货币。阿土伯可以有两个办法让所有人看到整个系统的大账本。第一个办法是由阿土伯维护一个公共账本,上面记录着每个账号的余额情况。这样每次转账交易的时候,交易接受方可以去查询转出方账上有没有那么多钱。阿土伯要发行货币,就在某个账户上直接加上他要发行的数量;如果钱夫人要转账给孙小美,那么阿土伯就在钱夫人账上扣除相应数量,加到孙小美账上。咦?!这个方案不就是信用方案吗?显然不是探索加密数字货币所希望的方向(见第二篇),不过这种办法很多人在做,支付宝和微信都在这么干。
那么阿土伯要采用第二个办法,不再那么费力的不停汇总修改那个总账本,而是把流水帐公布出来。流水帐有个好处,就是永远只增加交易记录,从来不删除和修改历史的交易记录。这样阿土伯只要及时把新的交易加到流水帐里面就行,不用再去统计了。而需要验证自己的交易是不是有效的,自己去流水账本里面查,反正这个账本从第一枚虚拟币造出来就一直记录下来了。我们来看看一般情况下如何记录交易流水帐。(见下表)
如果阿土伯按照这样记录流水,并公布在网上,那么最后一笔小丹尼在收到钱夫人转给他4枚虚拟币的时候,需要用整个流水帐去检验这笔交易是否有效。他要找遍整个流水帐,把钱夫人账号收支情况进行累加,才能确定钱夫人有没有4枚币支付给他。随着时间越来越久,交易量越来越多,这样的追溯将消耗大量计算时间,效率一定低下。于是,阿土伯就想办法进行改进,最后他进行了一些巧妙的设计,优化流水帐的记录方式,实现记录与校验的高效组合。阿土伯很得意地把这种数字虚拟货币称之为”流水币“(见下表)
这种记录流水帐的方法几乎就是比特币采用交易记录方式,我想我的漫谈也就介绍到这种深度,再细节一直到代码还有很多讲究和精妙设计,不过能看懂那个程度的朋友,已经可以自己去看很专业的书籍了,不需要看我的漫谈。
我来仔细介绍一下这张表表达的意思,注意哦,看懂这张表以后就能懂比特币的转账交易是如何发生的了。表中列出了5笔交易记录,每笔交易记录都有一个唯一的流水号,在这里我是用数字来排序的。(需要提醒的是在比特币实际运行的计算机环境里,这里的流水号换成了这笔交易的哈希值。)
最大的变化是”交易内容“,我们看到,每笔交易都分成两个部分,”上笔收入“和”本笔支出“。
“上笔收入”,是指这笔交易里需要花出去钱的来历。在流水号为1的交易里,上笔收入为0,说明这笔交易是一个制造货币的交易。签名人就是这个货币的发明管理人阿土伯,他制造了5枚流水币转给了钱夫人。除了这笔交易收入为0,其它交易的“上笔收入”都是指向得到那笔钱的交易流水号和那笔交易里支出部分的序号。
支出部分的序号,是指每笔交易内容中”本笔支出“部分,每笔交易的支出可能有好多去处,这怎么理解呢?这就是阿土伯设计的这种交易记录方式的精髓所在之二(精髓之一是每笔交易都指向了”上笔收入“),他设定了一个原则,就是每笔交易里,输入部分指向的数额必须与输出部分的数额相同。换句话说,就是每次花一笔钱,是把这笔钱来历的那笔交易输出给清零了(或者作废了),同时在本次交易里全部重新分配去处。所以无论输入还是输出,都会在同一笔交易里可能出现多笔输入或者多笔输出的情况,而这些输出是排序的,就是每笔交易里“本笔支出”后面的方括号里的数字。
上面介绍了这个流水帐的记录方式和讲究,现在我再来把这五笔交易分别解读一遍,各位就应该能理解这种交易记录方式了,从此也能理解比特币的交易记录方式了。
第一笔,流水号为1,因为“上笔收入”为0,所以这是一笔制造货币的交易类型,签名人就是这个系统的主人阿土伯,他制造了5枚流水币付给钱夫人,支出只有一笔,序号为[1]。
第二笔,流水号为2,这笔是钱夫人向孙小美支付2枚流水币的交易,首先钱夫人在“上笔收入”里交代了这笔钱的来处是流水号为1的交易里,支出序号为[1]的那一笔。这样我们可以直接追溯到那一笔交易,发现钱夫人当时得到了5枚流水币,而这里只是在“本笔支出”序号为[1]中付给了孙小美2枚,还有3枚必须交代清楚,于是钱夫人建了“本笔支出”序号为[2],再付给自己3枚,相当于找钱。(这里注解一下,在比特币里,这种机制让所有的地址可以只出现一次,每次交易可以把钱转到一个全新的地址上,实现一定程度的匿名性)
第三笔,流水号为3,这笔是孙小美要支付给约翰乔2枚流水币,于是在这笔交易的“上笔收入”中,孙小美指出这是来自于流水号为2,支出序号为[1]的那笔钱,我们可以追溯上去,找到了那笔交易并知道孙小美账上有2枚。在支出中因为也是转给约翰乔2枚,所以只需要一条支出,序号就是[1]。
第四笔,流水号为4,这笔是约翰乔要把从3[1]交易支出中得到的2枚流水币分别支付给钱夫人和孙小美,于是就有了两条支出,分别支付1枚给钱夫人和孙小美,支出序号也相应的有[1]和[2]。
第五笔,流水号为5,这笔钱夫人要付4枚给小丹尼,但是钱夫人这4枚来自于不同的交易,于是这里“上笔收入”中,钱夫人列了两条,一条来自于流水为2的支出序列为[2]的那条支出,我们查到是3枚;另外一条是流水号为4的支出序号为[1]的,约翰乔支付的1枚,这样钱夫人就证明自己是有4枚的,并一次支付给了小丹尼。
可能已经有人嫌弃我啰嗦了,不过我码那么多字,换不同姿势解读就是为了让大家能看懂。这样的记账对于发起交易和校验交易的人,都非常方便。尤其是对校验的人来说,能很容易找到对应的交易记录,不用从头追溯整个流水账本,只要从对应的收入交易记录开始查流水帐,查到眼前来校验这个地址有没有在这个期间花出过钱,就能有效避免双重支付问题了。
这种记账方式还解决了一个很多朋友迷惑的问题,就是比特币零钱问题。相当多的朋友以为比特币最小单位就是一枚比特币,现在大概价值8000多美金。现在大家看到交易的记账方式,完全可以自己决定写上什么数字,既可以从好多账号汇总来支付,也可以化整为零支付出去;既可以是整数,也可以有小数部分。在比特币网络里,最小可以写上0.00000001枚比特币,相当于一亿分之一,这才是比特币的最小单位,称为1聪(中本聪的聪)。那么现在1聪大约相当于0.008美分,大概0.05分人民币。
在这里要插播关于比特币的几个小细节知识,就是关于中本聪在设计比特币时藏了三个彩蛋(这是另一位技术天才Vitalik总结的,他发起了以太坊项目,将来我们一定谈到,因为漫谈区块链既绕不过比特币,也绕不过以太坊)。
第一个彩蛋,本来用公钥做比特币账号应该很方便,但是中本聪偏偏要用公钥的哈希值来做公钥,增加了复杂度和计算量。大家一直觉得多此一举。后来才发现这个设计为未来量子计算机出现做好了准备,因为量子计算机通过公钥计算私钥的能力强大可能会造成比特币账号不再安全,那么用哈希值做账号以后,量子计算机也没办法从哈希值推出公钥来。
第二个彩蛋,比特币的总数量限制在2100万枚,大概是2的50.899次方。许多人都把这个当作比特币一个缺点来看,说什么会造成通货紧缩。其实这个数字是中本聪考虑了现在所有的计算机语言所能处理最大整数后确定的,因为他/她要确保比特币的规则适合任何计算机语言来开发应用。否则如果极端情况下某一个账号超过2100万枚比特币,那么可能某种应用程序开发的比特币应用中就发现账号被清零了。所以未来无论什么数字货币,如果号称超过2100万枚,那么一定是有计算机语言兼容性隐患。
第三个彩蛋,比特币的公钥私钥采用的是椭圆曲线算法,这里面有很多曲线选择,而中本聪选了一个很偏的曲线,没有采用世界上应用最广泛的曲线。后来斯诺登爆料美国NSA在某个应用很广的曲线加密算法中有后门,密码界非常震惊,然而中本聪前瞻性的绕过了这个后门危机。
不知道各位朋友看完这个花絮怎么想?欢迎在我公众号留言交流。(为啥微信还不开通我的留言功能呢?)
四、区块链——按时间分布存储数据需求的产物
至此我们几乎已经把比特币里最最基础的交易是怎么记录的原理介绍清楚了,大家如果还不懂只能面对面聊了,或者来听我的讲座吧。可是如果这种转账记录通过流水或者哈希值链接的话,还无法实现在网络上的高效分享,因为交易流水是不断增加的,整个流水帐随着时间将越来越大,阿土伯如果每增加一笔就要发布一个完整版的流水帐显然太不现实。这个时候阿土伯想到了咱们的主角——区块链。(这一篇差一点没有上场演出机会呀)
区块链可以让阿土伯把已经记录上的交易流水按照数量也好、时间也好打包成数据区块,然后区块与区块之间用哈希指针链接上,形成一个只增不减不改的链条形状的流水帐。这样阿土伯每收集一堆交易流水记录,先校验、再打包成区块,把上一个区块的哈希值放到这个区块头上,最后对整个区块签名发布出去,如此以往循环往复快快乐乐做他的阿土伯去了。所以区块链的出现正如我小标题说的,是为了解决按时间分布存储数据而产生的。
不过会不会有人提出疑问,这个收集记录到再打包发布之间总要有时间差吧?在这个时间差里怎么解决有一些交易可能矛盾冲突,甚至恰好出现双重支付呢?阿土伯能力再强,也做不到完全实时的发布区块吧?
这个问题非常的好,不过其实还有更严重的问题,就是阿土伯万一犯错误怎么办?故意犯错误怎么办?可见目前我们说的是一个基于阿土伯这个中心机构或人物的加密数字货币系统。如果哪国央行要开始发行自己的加密数字货币了,所采用的技术框架估计大概就是这个样子,只是阿土伯的身份变成央行了。
然而,刚才关于阿土伯有可能会胡作非为的问题让中本聪们如鲠在喉,不解决这个问题事情就没完。如何把阿土伯给去掉呢?
(本篇首发于2018年3月25日微信公众号geekszone)