去年在这里写了“关于比特币的5个想法”,貌似是这里的第一篇关于比特币的文章,今天在这里介绍一下比特币的协议。
本文是翻译Michael Nielsen关于比特币协议的文章,这篇文章是译者觉得写的最清楚的关于比特币的文章。Michael Nielsen是个研究量子计算的先驱科学家、作家和程序员,详细内容请看他自己的介绍。翻译这篇文章是因为译者认为关于比特币的文章和讨论很多,很多支持的很多反对的。但大多数都停留在概念、价格和主观的思考上,我想抛开比特币现有价格和表面显现,通过这篇文章,细致的给大家介绍一下比特币的协议工作原理。我相信弄明白一个事物背后的工作原理对于理解一个事物是非常重要的。我和大多数人一样,一开始看到的时候觉得它就是疯狂的,不是骗局就是传销。但是后来很多的线索和迹象提示我应该认真的研究比特币本身,就像是我们小时候会喜欢拆开玩具看里面是什么东西一样,了解它怎么工作的才能客观的看一个事物本身,才能有自己的观点,而不是总看着媒体发布的新闻和某些自己都一知半解的“专家”们的观点去理解这个东西。去年看到这篇Michael的这篇文章并且后来深入看了其他的关于协议本身的文章,醍醐灌顶,因此先将这片翻译下来留做记录,这里省略了作者提出的一些疑问,如有不足之处,错误在我,好的地方都在Michael Nielsen。之后我会陆续发布一系列曾帮助我理解关于比特币的材料,这些材料都是暗示(hint),我不会去尝试去销售(sale),而是尽可能的解释(explain),我不会负责说服你这个东西是好还是坏,理解之后,你可以有你自己的想法。
中本聪本人从来没有去说服别人,而是将文章发表到网上,让别人自己去判断。他本人说的 “It would help to condense the article and make it less promotional sounding as soon as possible. Just letting people know what it is, where it fits into the electronic money space, not trying to convince them that it’s good. ” 他的另一个原话是“If you don’t believe me or don’t get it, I don’t have time to try to convince you, sorry.”
以下是正文
成千上万的文章试图去解释比特币,一个在线的、点对点(Peer-to-Peer)的货币。大多数文章对其底层的协议一笔带过,省略了许多细节。就算是那些很深入的文章也在关键的地方搪塞过去。这篇文章的目的是用尽可能清晰的、易理解的方式解释比特币协议背后的要点。我们从第一原则开始,建立一个广义的理论上理解比特币协议,然后深入到细节去,检查比特币交易里的元数据。
深入的理解这个协议是困难的,因为很容易就将比特币视为给定的,并且去想如何利用它投机发财、想其是不是泡沫、想比特币是否意味着对税收的终结等等。想这些很有趣,但是这些想法严重的限制了你的理解。而理解比特币的协议本身将会打开其他渠道不可达到的视角。比如说这个协议是比特币内置的脚本语言的基础,这个脚本语言让你可以用比特币创造新的金融工具,比如智能合同(smart contracts)。新的金融工具反过来可以创造新的市场和新的人和人之间的合作行为,说到乐趣,这才是真正的乐趣所在!
我会在以后的文章中解释比特币脚本和智能合同。这篇文章我会集中在比特币协议的具体细节。理解这篇文章你需要大概熟悉一下公钥密码 和 与其相关的数字签名,(请了解一下两个概念)。同时还大概熟悉一下(哈希)Hash函数 (把任意长度的输入变换成固定长度的输出)。这些概念都很棒,如果你不了解,建议你花一些时间熟悉一下他们。
比特币的基础是密码学,这点可能会让你吃惊,不是说比特币是一种货币吗?难道它是一个发送秘密信息的方式吗?实际上,比特币想要解决的问题绝大部分是关于保护交易的——保证人们不能偷别人的东西或冒充别人等等。在原子组成的物质世界里,我们通过锁,签名,银行保险箱等等来保证安全。在信息世界里我们通过密码学来保证安全性。这就是为什么比特币的核心是密码学的协议。
这篇文章的策略是一层一层的建立起比特币。我们会从一个非常简单的数字货币开始,我们暂时叫他“Infocoin”,用来区分于Bitcoin。当然我们第一版本的Infocoin会有很多的缺点,所以我们会经过几次迭代,每次迭代会新介绍一到两个新的概念。经过若干次之后,我们就会得到一个完整的比特币协议了。我们会一起重新发明比特币。
这种办法比一开始就直接解释比特币要慢一些。但是即使你可以一下了解比特币的原理,你也很难理解为什么比特币要设计成这个样子。而慢慢的一步一步迭代式的解释,其优点就在于它可以让你对比特币的每个元素有更清晰的理解。
最后我应该说的是我在比特币世界相对来讲是新人。我2011年有粗略的关注,但是真正认真研究其细节,是2013年初。欢迎任何人对我错误的部分进行纠正。
第一步:签了名的意向书
怎么设计一个货币呢?
从表面判断,一个数字货币听起来不可能。假设一个人——我们叫她Alice——有一些想要花掉的数字货币。如果Alice可以用一串字符作为钱的话,我们怎么能阻止她用同样的那串字符反复的使用呢?如果我们能解决这个问题,我们有怎样能防止其他人伪造一串字符,从Alice那边偷走呢?
这只是用信息做货币要解决的众多问题中的两个。在第一版的Infocoin中,我们想办法让Alice供一个字符串来作为钱,并且想个办法保护它不被伪造。假设Alice要把一个infocoin给另一个人Bob。Alice需要写下一个消息:“我Alice要给Bob一个infocoin”。 她然后用数字签名的办法将这个信息和一个私钥(这个私钥是随机生成的一个64位数)一起签下名产生一个结果。并且将这个签了名的结果字符公布给整个世界。
这个办法并不怎么出众,但还是有一些优点的。世界上任何人都可以用Alice的公钥去验证Alice确实是那个签了名的人。其他任何人都不可能产生那个签名的结果(这个签名只可能从Alice拥有的私钥产生,原理请看上文提到的数字签名),所以Alice不能反悔说“不,我没有给Bob那个infocoin”。这样,这个协议提供了Alice确实有意向给Bob一个infocoin的证明。同样,其他任何人都不能产生那样一个签了名的信息,这样防止了其他人伪造Alice的信息。当然,当Alice已经发布了她的消息之后,其他人是有可能复制这个消息的,但是发布之前不可能伪造。所以,证明意向和防止消息发布之前被伪造这两个功能是这个协议里真正值得注意的特性。
我还没有说这个协议里的钱到底是什么呢。明确的说:钱其实就是这个消息本身。也就是说那一串代签了名的代表着“我Alice要给Bob一个infocoin”的字符。后面协议将会在这一点上类似,也就是所有的数字货币只是越来越详细的消息字符。
用序列号来给货币一个唯一的标识
我们第一版的Infocoin的问题是Alice可以重复地给Bob发送同一个签了名的消息。假设Bob收到了10份这样的消息“我,Alice,要给Bob一个infocoin”。这是说Alice给Bob了10个不同的infocoin呢?还是Alice给Bob一个infocoin,只是不小心消息重复了?或者是她想要欺骗Bob让给他相信她给了他10个infocoin,而实际上给外面世界发出的消息只证明了她只给了一个infocoin。
我们想要的是让infocoin有个唯一的标识。它需要一个标签或者序列号。Alice可以在消息“我Alice要给Bob一个序列号为8740348的infocoin”上签名。之后Alice如果在另一个消息里签名 “我Alice要给Bob一个序列号为8770431的 infocoin”,这样,Bob和其他人就会知道这里两个是不同的infocoin。
为了让这个方案可行,我们就必须要一个可信的序列号来源。一种产生序列号的办法是建立一个机构比如银行。这个银行将会为infocoin产生序列号,记录谁拥有着哪个infocoin,并且验证交易的真实性。
更详细的说,我们假设Alice去一个银行,说“我要从我的账户里取一个infocoin”。这个银行从她的账户里减掉一个infocoin,然后给她一个新的从没用过的序列号,假设是“1234567”。然后,当Alice想要给Bob发一个infocoin的时候,她给这个新的消息签名“我Alice要给Bob一个序列号为1234567的infocoin”。但是Bob不只接受这个infocoin,而且他去联系银行,确认两件事,第一,序列号为1234567的infocoin确实是属于Alice的。第二,Alice还没有花掉那个infocoin。然后银行更新它的记录来显示那个infocoin现在是属于Bob而不是Alice。
让每个人都成为银行
上面的这个解决方法看起来很有潜力。但是,我们可以做到更有野心的事。我们可以从这个协议里剔除掉银行。这样大幅的改变了这个货币的本身属性。这意味着将不会有一个单独的组织负责这个货币。当你想中央银行拥有着多么大权利的时候(控制货币发行)——这意味着巨大的改变。
方法是让每个人共同合作成为银行。尤其是,我们假设每个用infocoin的人保存一份完整的记录,这个记录包括哪个infocoin属于哪个人。你可以把它想象成一个共享的公开的账本,这个账本记录着所有的infocoin的交易记录。我们就将它叫做“区块链 blockchain”,因为比特币里面就是这么叫的。
现在,我们假设Alice要将一个infocoin给Bob。她在消息“我Alice要给Bob一个序列号为1234567的infocoin”上签名。并且将签了名的消息输出结果给Bob,Bob可以用他自己的那份block chain去检验,“OK,确实那个infocoin是Alice给我的”。如果他检查没问题,他就将Alice的消息和自己接受这个infocoin的消息公布给全网络。然后所有的人更新他们的blockchain。
我们仍然存在“序列号从哪里来”的问题,但是这件事其实很容易解决,所以我推后再解释。更加难的问题是这个协议允许Alice重复的花费她的infocoin。她可以发布一个签了名的消息“我Alice要给Bob一个序列号为1234567的infocoin” ,同时她也可以发布一个签名的消息说“我Alice要给Charlie一个序列号为1234567的infocoin”。Bob和Charlie两个人都用他们自己的blockchain去检验那个infocoin确实是Alice发过来的。假设他们在同一时间进行的检验(在他们两个互相知道另一个的消息之前),他们两个都会发现,是的,我的blockchain证明那个币是属于Alice。所以他们都接受了那个交易,并且公布他们的接受信息给整个网络。现在就有问题了。网络上其他的人应该怎样更新他们的blockchain呢?这样看来貌似不能简单的达到统一交易账本。而且即使每个人都同意用一样的办法更新他们的blockchain,Bob和Charlie两个人之间有一个是肯定被骗了。
我们把这个问题叫做“双重花费 double spending”(后文称“双花”), 一眼看来,这样的双花似乎很难成功。毕竟,如果Alice先将消息发给Bob,然后Bob将消息发送给其他所有人(包括Charlie),其他人更新了他们的blockchain。这时候,Charlie就不会被Alice骗了。所以似乎双重花费只有在短暂的一段时间内可能。然而,即使这个时间很短,有这个问题也是不可取的。更糟的是,Alice可以用一些技巧让这一段时间按延长。比如说她可以用网络分析软件找到Bob和Charlie之间的交流的延迟时间很长的时候。或者可以做一些事情故意打扰他们之间的网络连接。如果她可以减慢这个交流一点点,就可以使得她的双花成功变得容易许多。
那怎么解决这个问题呢?最简单的办法是当Alice给Bob发送infocoin的时候,Bob不应该独自的检验这个交易。而他应该将这个可待定的交易公布到整个infocoin网络里,让其他人帮忙判断这个交易是否合理。如果他们共同决定这个交易是合理的,那么Bob可以去接受这个infocoin,然后所有人更新他们的blockchain。这种类协议可以防止双花,因为如果Alice想要同时给Bob和Charlie发送同样的infocoin时,网络上的其他人会注意到,并且告诉Bob和Charlie这个交易有问题,然后这个交易就不允许通过。
更具体的来说,假设Alice想要给Bob一个infocoin。和之前一样,她给一个消息签名,“我Alice要给Bob一个序列号为1234567的infocoin”,并将签好名的消息给Bob。也和之前一样,Bob用他自己的blockchain做一个检查,这个币确实属于Alice。但是协议不一样了,Bob并不直接接受这个,而是公布Alice的消息给整个网络。网络上的其他成员检查Alice是否拥有这个infocoin,如果是,那么他们公布消息说“没错,Alice确实有infocoin 1234567, 现在可以将其转给Bob了”。一旦有足够的人公布这个消息,每个人更新他的blockchain来显示infocoin 1234567现在属于Bob,交易完成。
这个协议现在还有很多不确定的因素。比如,“一旦有足够的人公布这个消息”到底是什么意思,多少个人算是足够?不可能是整个infocoin网络,因为我们事先不知道谁在infocoin网络上。同样,也不能是固定的一部分用户。我们现在先不着急将这些问题弄清楚。在这里,我将要指出一个这交易个方案的严重的问题,解决那个问题将会同时帮助上面的问题弄清楚。
工作证明 Proof-of-work
假设Alice想要在上述的协议中双花,他需要掌管整个的infocoin网络。假设她用一个自动的系统在infocoin网络上建立很多个不同身份的账户,假设有10亿个。和之前一样,她试图进行双花,将同样的infocoin给Bob和Charlie,但是当Bob和Charlie询问infocoin网络的来检验这个交易时,Alice的马甲们淹没整个网络,告诉Bob和Charlie他们可以通过这个交易,并且可能欺骗他们其中一个或者两个人都接受这个交易。
有一个聪明的办法,用一个叫做“工作证明Proof-of-work”的方法。方法并不直观,需要结合两个概念,1)人工的让检验交易的过程花费较大的计算开销;2)奖赏他们帮忙检验这个交易。用奖赏的办法激励在该网络上的人去验证交易。加大交易验证开销的优点是验证不会再被那些拥有很多账户的人控制,而是只会被他能提供的总共计算能力控制。我们将会看到,通过一些聪明的设计,我们可以让欺骗者必须花费非常大的计算资源来达到欺骗的目的,让它变的不切实际。
这就是工作证明的要点。但是要真正弄明白工作证明,我们需要深入更加具体的细节。
假设Alice给整个网络公布消息“我Alice要给Bob一个序列号为1234567的infocoin”。当网络上的其他人听到这个消息后,每个人将其加入到一列待定的交易之中,这些交易都还没有被整个网络通过。比如说网络上一个叫做David的人可能有下面这一列待定的交易:
我Tom要给Sue一个序列号为1201174的infocoin。 我Sydney要给Cynthia一个序列号为1295618的infocoin。
我Alice要给Bob一个序列号为1234567的infocoin。
David检查他自己的blockchain,看到上述这些交易是合理的。他要帮助将这个验证消息公布到整个网络中去。但是,在这之前,检验交易协议需要David去解决一个计算难题——也就是工作证明。若他没有得到难题的解,网络上的其他成员不会接受他的验证。
那么David到底要解决一个什么的难题呢?要解释这个,我们用一个网络上面每个人都知道的固定的哈希函数hash function——将其包括在协议本身。比特币用一个众所周知的SHA-256哈希函数,但是任何密码学的哈希函数在这里都可以用。我们给David的这一组待定的交易一个标记,”L”吧,为了之后可以引用。这一组待定的交易也就相当于blockchain里面的block(区块)(-理解这个Block很重要,block也就是一组交易信息组成的集合,一个block包括很多个交易)。假设David在这个区块”L”后添加一个数字x(叫做nonce,暂时的随机数)然后hash他们的结合。比方说,我们用L=“Hello, world!” 作为一些交易的标记。然后加上一个暂时的随机数,我们从“x=0”开始吧。
h("hello", world! 0) =1312af178c253f84028d480a6adc1e25e81caa44c749ec81976192e2ec934c64
David将要解决的问题(工作证明)是找到一个随机数x,当我们将这个x添加到L后面并且hash这个组合的时候,得到的结果开始为几个0开头。这个难题的难度可以通过调整开头零的个数来调节。一个简单的”工作证明”只需要3或4个零开头的hash,一个难的“工作证明”则可能需要更多的零开头,比如说15个连续的零。在上述情况下,x=0的到的hash结果不成功,因为结果不是由0开始的。那么我们就尝试x=1,
可以看到x=1的时候也不成立
h("Hello, world!1") = e9afc424b79e4f6ab42d99c81156d3a17228d6e1eef4139be78e948a9332a7d8
然后尝试x=2, 然后x=3 ,4,5…. 知道最后,发现x=4350的时候,我们得到了
h("Hello, world!4250") = 0000c3af42fc31103f1fdc0151fa747ff87349a4714df7cc52ea464e12dcd4e9
这个随机数x给了我们一个结果是四个零开头的hash。这个就足够解决一个简单的“工作证明”的难题了。
让这个难题不容易解决的是其密码哈希函数结果永远是随机的,对输入值做任何细小的改变将会完全该别整个哈希函数的输出结果,以至于很难去预测。所以如果我们需要输出结果必须是开始于10个0,那么David将平均需要 1610 ≈ 1012 个不同的x才能找到那个合适的值。这是一个非常有挑战性的任务,需要很多的计算能力。
显然,我们可以通过规定需要零的多少来控制工作证明难题的难易程度。事实上,比特币协议通过对上述的工作证明稍加修改,可以对难题的难易程度有更良好的控制。不再是规定需要多少个开始的零,而是规定block的hash输出结果要小于或等于一个目标值,这个目标值是自动调节的,用来保证比特币的每一个区块(block)平均要花10分钟来解。
好了,我们假设David很幸运,找到了一个合适的x(nonce),恭喜他!(他将会得到找到这个答案的奖赏)。他会公布他已经证明了这个区块里面的交易是合理的,并且与之同时公布她找到的x值,其他infocoin里的参与者可以证明x那个工作证明的有效解。然后他们就更新自己的blockchain,来包括David所公布的这些交易。
为了让工作证明这个方案的运作,网络的参与者应该需要一个激励机制来帮助验证交易。没有激励机制的话,没有人会愿意花费自己的计算机算力来帮助检验交易。如果网络参与者不愿意花费算力,那么整个系统就不会运转。因此,我们可以通过给他们一些infocoin的方式来奖励任何成功验证了交易的人。若给他们提供的infocoin奖励足够的多,可以激励他们来参与验证。
在比特币的协议里,这个验证的过程被称作“mining” (挖矿)。每一个交易区块的验证成功者都会获得比特币作为奖励。最开始的时候,是50个比特币的奖励。但是每格21万个验证的区块(也就是大概每4年左右),奖励会减半。现在为止只发生了一次,也就是说现在验证一个block获得的奖励是25个比特币。 减半的过程会持续发生,直到大概2140年。那时候,挖矿的奖励的将会降低到10-8个比特币。而10-8个比特币是比特币最小的单位(被称作一个Satoshi),因此到2140年,总共的比特币将会停止增长。然而,这并不会消除验证交易的激励机制,比特币可以允许参与者加入验证交易的费用,用来奖赏验证交易的人。早期的比特币,交易费几乎为零,但是随着比特币的普及,交易费会逐渐升高,现在已经成为除了25个比特币奖励之外的额外激励了。
你可以将工作证明(proof-of-work)看做一个竞相验证交易的过程。每个参与者会花费一部分的计算机算力。一个挖矿者获胜的机会大概等于他们控制的计算计算力的大小和整个网络的算力的比例。比如说,一个挖矿者控制着整个网络算力量百分之一的计算能力,那么他的获胜的概率也大概是百分之一。所以提供大量计算能力是支撑竞争能力的因素,一个不诚实的挖矿者只有很小的机会去破坏验证过程,除非他们花费巨大的计算机资源。
当然,就算是不诚实的挖矿者仅有很小的机会破坏整个blockchain,我们也没有足够的信心拿它来当成货币。特别是,我们还没有最终解决双花的问题。
我会马上分析双花的问题,但是在那之前,我想在Infocoin的概念里补充一个重要的细节。理想情况下,我们希望Infocoin网络能够统一交易发生的顺序。如果我们没有统一的顺序,那么谁在哪个特定的时候有哪个infocoin就不是很清楚了。为了帮着解决这一点。我们要求新的区块(block)必须要包含指向上一个区块的指针,这个指针也其实就是上一个block的哈希(hash)结果。因此,基本上说,区块链 (block chain)本身也就是一个线性的一串包含着交易信息的区块(blocks),一个接着一个,每一个block都包含着指向上一个block的指针。
偶然情况下,一个blockchain上会产生分支。这种情况是因为,有时候两个挖矿者几乎同时验证出来一个区块的交易。他们同时公布到网络里,有些人用一个方法更新他们的blockchain,另一些人用另外一个方法更新他们的blockchain。
这就造成了我们想要避免的情况 ——这种情况,交易的顺序就不清楚了,而且谁有哪个infocoin也就不清楚了。幸运的是,有一个简单的办法可以用来挪去分支。规则是这样的:如果分支情况出现,那么网络上的人们继续保持两个分支,任何情况下,挖矿者只在最长的那个blockchain上工作。
假设我们有一个分支,有一些挖矿者先收到block A,另一些挖矿者先收到的是block B。那些收到block A的挖矿者将要继续沿着他们的分支挖矿,而其他人沿着Block B的分支挖矿。我们假设在B分支上的挖矿者先成功挖到下一个block:
当他们收到这个消息后,在A分支的人会注意到现在B分支是最长的,于是就会转换到B的分支。在A分支上的工作就会迅速的停止,这样每个人就会都在同一个顺序的blockchain上工作了。然后block A就会被忽略。当然,所有在block A里面的待定交易将会继续保持待定状态,随后会在B分支上被放到新的block里,这样,所有的交易最终还是会被验证的。
同理,如果在分支A上的挖矿者先挖到下一个block,那么在B分支上工作的人就是停止,转到A分支上。
不论结果是什么,这个过程保证了blockchain有统一的顺序。在比特币中,一个交易能不算作确认直到 1)它存在于最长的分支中的block里,2)至少有5个验证过的block在其后面得到验证。这种情况,我们说这个交易有了“6个确认”。这给了整个网络时间去统一block的顺序。我们在Infocoin里,也用同样的方案。
现在我们理解了时间顺序,那我们回去想想如果一个不诚实的人想要双重花费的话会怎么样。假设Alice要同时给Bob和Charlie同样的交易。一个可能性就是让她去验证同时带有两个交易的一个block。假设她拥有百分之一的计算能力,那么她有可能比较幸运的验证出了这一个block。不幸的是,这个双重花费将会马上被其他人发现并且拒绝,尽管她解决了工作证明里的难题。所以这个可能性我们不用担心。
但是另一种可能性是,她试图分别公布两个交易。她可能给一部分挖矿者公布一个交易,给另一部分挖矿者公布另一个交易,她希望让两个交易都得到验证。幸运的是,这种情况下,如我们刚才所说,网络最终只会确认其中一个交易。所以,这个也不是问题。
还有一种可能是,Alice = Bob,也就是说Alice试图将一个币给Charlie,同时她又将那个币给她自己,因为她自己可以有多个账户。这种情况下,Alice的策略是等到Charlie接受了这个Infocoin,也就是大概在交易在最长的blockchain中被确认6次之后。她再试图去解决另外一个拥有她发给自己的交易的那个block分支。
可惜的是,这个时候Alice已经比最长的blockchain晚了6步。她很难在跟得上最长的分支了。其他的挖矿者不会帮助她,因为他们都需要在最长的分支上工作才能得到奖赏。除非Alice在解决工作证明的时候能够比网络上其他人结合起来还快(也就是说她大概有多于整个网络50%的计算能力)。当然,她可能会偶然幸运,在百分之一的算力的情况下能解决一个block,但是同时赶上6个的花相当于是 1/1006 = 10-12 。这种情况可以说是想到于零。
当然这不是非常严格的说Alice肯定不能双花了。这只是一个合理的推论。比特币的白皮书原文并没有进行一个严格的安全分析,只是和我这里类似的非正式推论。安全团体任然在分析比特币的安全性和潜在的缺陷,具体可以看这个列表。
译者记,这是上半个部分,下半部分作者Michael 撇开了Infocoin的概念,通过比特币交易的视力更详细的讲解比特币的协议。如果你看到这里了,你可以关注我的微博,和博客 。
另外:如果觉得有帮助,建议你Tip给这篇文章的原作者Michael Nielsen, 他的地址是17ukkKt1bNLAqdJ1QQv8v9Askr6vy3MzTZ , 你也可以follow他的Twitter 。 或者关注他的将要出版的关于neural networks and deep learning新书的第一章.