导读
这篇文章的目的是用尽可能清晰的、易理解的方式解释比特币协议背后的要点,而理解比特币的协议本身将会打开其他渠道不可达到的视角。
作者:Michael Nielsen
译者:杨硕
译者言:
本文是翻译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肯定不能双花了。这只是一个合理的推论。比特币的白皮书原文并没有进行一个严格的安全分析,只是和我这里类似的非正式推论。安全团体任然在分析比特币的安全性和潜在的缺陷。
比特币
现在,让我们离开Infocoin,转向的真正的比特币协议。比特币和我们刚才一步步建立起来的Infocoin没有多大的差别,除了一个明显的改变。
要使用比特币,首先你得在电脑里安装一个钱包。为了让你更好的理解,下图是一个叫做Multibit的钱包的截图。你可以在左上角看到比特币的余额——0.06555555 个比特币,按截图的当时的交易价格来算将近70美元。截图右边显示了两个最近的交易,他们是存入这0.06555555个比特币。
假设你是一个商家,你已经准备好了一个在线商店,你决定允许客户用比特币支付。你需要做的是,用你的钱包程序新生成一个比特币地址。它会自动生成一对公钥和私钥,然后hash你的公钥来形成你的比特币地址。
然后你将你的比特币地址发给要付给你钱的人。你可以用邮箱,或者直接放到你的网页上。这是安全的,因为你的地址只不过是hash了的公钥,你可以放心的公布给任何人(没人能通过它来得到你的私钥)。 我会在后面解释为什么比特币地址用的是公钥的hash值而不是公钥本身。
现在那个准备付钱的人需要创建一个新的交易。让我们看一个真实的转入0.319个比特币的交易数据。下面这个就将近是原始数据了,这里有三个地方的改变:1)数据没有连续化;2)加了行编号,为了更好理解;3)省略了hash数据的一长串数字,只保留了前6位。
1. {“hash”:”7c4025…”,
2. “ver”:1,
3. “vin_sz”:1,
4. “vout_sz”:1,
5. “lock_time”:0,
6. “size”:224,
7. “in”:[
8. {“prev_out”:
9. {“hash”:”2007ae…”,
10. “n”:0},
11. “scriptSig”:”304502… 042b2d…”}],
12. “out”:[
13. {“value”:”0.31900000″,
14. “scriptPubKey”:”OP_DUP OP_HASH160 a7db6f OP_EQUALVERIFY OP_CHECKSIG”}]}
让我们一行一行解释。
第1行,交易hash值(16进制),他是用来代表这个交易的唯一标记。
第2行,告诉我们这个交易用的是第一版本的比特币协议。
第3、4行,告诉我们这个交易有一个输入和一个输出。(一个交易可以有多个输入和多个输出)
第5行,是一个锁定时间(lock_time),可以用它来控制这个交易什么时候完成。现在大多数的比特币交易锁定时间都是0,也就是马上完成交易。
第6行,告诉我们这个交易的大小有多少个字节(bytes),注意,这个不是交易的钱。
第7到11行,这一段定义了这个交易的输入部分,确切的说,8到10行告诉我们要转走钱的这个输入值的钱是从上一个交易输出值里得来的。那个2007ae…就是上一个交易的16进制的hash值,用来指向上一个交易。n=0说的是它是上一个交易里面的第一个输出,我们过一会儿会看到多个输入和输出是什么样子,所以现在先不用担心。11行是那个发送钱的人的数字签名:304502… 空格之后是他的公钥:04b2d… 同样这两个都是16进制。
这里输入部分值得注意的是,它并没有说前一个交易中的比特币,有多少会转给后一个。实际上,在前一个交易里面n=0的输出内所有的比特币都被转移了。比如说,如果前一个交易里的第一个输出(n=0)里面有2个比特币,那么这两个比特币在新的这个交易中都会被花掉。这看起来很不方便,就好像用20美元的现金去买一个面包一样。解决办法是提供一个找零钱的机制,这一点可以通过多个输入和输出的方式解决,下一部分就会讲到。
第12到14行,这段定义了交易的输出。具体说,13行告诉我们输出的钱的数量,这里是0.319个比特币。14行比较复杂,值得注意的是字符串a7db6f…是收取比特币的地址。这一行其实是一段比特币的脚本语言,在这里不细讲脚本语言的细节。你只需要知道a7db6f…是收取的地址就行了。
现在,你可以看到比特币是如何解决我们之前提到的“序列号从哪里来”的问题了。第一,比特币并不是分开的一个个单独的“币”,而是一长串存在于blockchain里的交易。通过保存一个交易账本来实现比特币是一个很聪明的想法。第二,通过这种方式,我们不需要一个中央机构来发布序列号。序列号可以通过hash交易本身来得到。
我们可以一直顺着交易链一直往回看。最终到头的时候,有两种可能,第一,你可能会走到第一个比特币交易,这个交易存在一个block里,我们把这个block叫做“Genesis block (初始区块)”。这是一个特殊的交易,它没有输入,只有50个比特币的输出。换句话说,它是最最早的比特币供应。Genesis block被比特币客户端区别对待,这里不去细讲。
第二个顺着交易链一直往回看得到的结果可能是你到达了一个被称作“coinbase”的交易。除了Genesis block之外,每个block里都开始于一个特殊的coinbase交易。这个交易是用来奖赏验证这个block里交易的挖矿者的。它用了和上述类似的数据形式,具体也不细讲了,对coinbase交易感兴趣的话可以看这里。
上面的描述不是很清楚的是,在11行里面被数字签名的东西到底是什么。最显然的是办法是让支付者把整个交易进行数字签名。现在来说它不是这样做的,一些交易被忽略了。这使得交易的一部有了可塑性,也就是说,它们可以在以后进行修改。然而,这个可塑的内容里并不包括交易的数量,付款人和收款人。可塑性的问题在比特币社区内有很多讨论,有人希望去取消它,这里不细谈。
有多个输入和输出的交易
上一段里面我们讲了一个只有单个输入和单个输出的交易数据。实际上,大多比特币交易都是有多个输入或者多个输出的。我们先看看这个交易的原始数据:
1. {“hash”:”993830…”,
2. “ver”:1,
3. “vin_sz”:3,
4. “vout_sz”:2,
5. “lock_time”:0,
6. “size”:552,
7. “in”:[
8. {“prev_out”:{
9. “hash”:”3beabc…”,
10. “n”:0},
11. “scriptSig”:”304402… 04c7d2…”},
12. {“prev_out”:{
13. “hash”:”fdae9b…”,
14. “n”:0},
15. “scriptSig”:”304502… 026e15…”},
16. {“prev_out”:{
17. “hash”:”20c86b…”,
18. “n”:1},
19. “scriptSig”:”304402… 038a52…”}],
20. “out”:[
21. {“value”:”0.01068000″,
22. “scriptPubKey”:”OP_DUP OP_HASH160 e8c306… OP_EQUALVERIFY OP_CHECKSIG”},
23. {“value”:”4.00000000″,
24. “scriptPubKey”:”OP_DUP OP_HASH160 d644e3… OP_EQUALVERIFY OP_CHECKSIG”}]}
像之前一样,我们一行行解释,大部分和刚才的是一样的。
第1行,交易的hash值,用来作为这个交易的唯一标记。
第2行,比特币协议的版本,第一版。
第3、4行,是说这个交易里有3个输入,2个输出。
第5行,锁定时间(和之前的一样)。
第6行,交易的字节大小。
第7到19行,定义了所有的输入,每一个都对应这前一个交易的输出。第一个输入是8到11行。其内容形式和之前的一样。 第二个输入是12到15行,第三个是16到19行。
第20到24行,定义了所有的输出,第一个输出是21和22行,和之前一样,21行说的是里面有0.01068个比特币。22行是一段比特币的脚本语言。字符串e8c30622…是收款人的地址。 第二个输出是23和24行,格式同上。
看起来有些奇怪的是,虽然每个输出都有记录着比特币的数量,但是输入却没有。当然每个输入有多少比特币可以从它的上一个交易中得到。在一个普通的比特币交易中,所有的输入价值之和要大于多有的输出(除了刚才说的Genesis block和coinbase交易之外),如果输入之和大于输出,那么多余的比特币就会作为交易费提供给这个交易所在的block的挖矿者。
多个输入和输出的作用是找零。假设我想要给你0.15个比特币。我可以花掉我之前收到的0.2个比特币。当然,我不想给你全部0.2个,所以解决办法就是,我给你发0.15个比特币,然后再给我自己的另外一个比特币地址发0.05个比特币。这样,那0.05就是给我的找零。这个概念和你在现实商店里的找零不太一样,这个更像是你给你自己付钱。但是大致意思是一样的。
结语
比特币背后的基本概念就算是描述完了。当然,我也忽略了许多细节——这毕竟不是一个正式的说明书。但是我想描述的是通常使用的比特币背后的概念。
虽然比特币后面的规则是简单和容易理解的,这并不意味着这些规则将产生的所有可能结果也容易理解。对于比特币可以说的还有很多,我会在以后的文章中阐述一些。但是现在,我姑且做一些零碎的总结。
比特币有多么匿名?许多人说比特币可以匿名使用。这个说法形成于类似Silk Road之类的黑市。然而这个说法是虚构的。Blockchain是公开的,也就意味着任何人都可以看所有的比特币交易。虽然比特币地址并没有直接和真实世界里人物的身份相对应,但计算机科学家们已经做了很多工作去解密“匿名”的社交网络。Blockchain是他们一个极好的目标。在不远的将来,如果大多数比特币用户身份还都不能相对有信心的识别出来,那我感到会非常惊奇。这个识别不一定会完全确认,但是足够提供有着很大可能性的目标。此外,身份将会是可追溯的,这意味着那些2011年在Silk Road上卖毒品的人,仍然可以在2020年在blockchain上找到。这些反匿名技术对计算机科学家来说是众所周知的,甚至可以说包括NSA(美国国家安全局)也知道。如果说NSA或者其他机构已经反匿名了很多用户的话,我并不会觉得奇怪。比特币被吹捧成匿名的这个说法是有点滑稽的。它不是匿名的,相反,比特币可能是迄今为止世界上最为公开和透明的金融工具。
你能通过比特币发财吗?也许吧,Tim O’Reilly 曾经说过 “钱就像是汽车里面的油——你需要注意,否则就会困在路边上——但是生活不是围绕着加油站转圈!” 大多数对比特币的兴趣似乎来自于那些人生目标仅仅是找到一个大的加油站的人。我必须承认,这个让人困惑。我相信更有趣的、更享受的是把比特币或者其他数码货币看做一个塑造新的人类合作行为的工具。那是理性上的迷人,提供了巨大的创新的可能,它是有社会价值的,同样也可能会赚到一些钱。但是如果赚钱是你的主要目的,那我相信有其他更容易成功的办法。
我所忽略的细节:虽然这篇文章描述了比特币背后的主要概念,但有很多细节我并没有提到。其中之一是协议里面的很棒的节省空间的技巧,基于一个叫做Merkle tree的数据结构。这是细节,但它是一个极其精彩的细节,如果你喜欢数据结构的话,很值得去看看。你可以通过比特币白皮书了解大概情况。第二,我几乎没有提到比特币网络——其中一些问题比如,这个网络如何处理拒绝了的服务器攻击,节点是如何加入和离开网络的,等等。这是个很有意思的话题,但同时也是包含很多细节的话题,所以我在这里忽略了。你可以通过上面的一些链接来阅读更多与之相关的东西。
比特币脚本:在这篇文章里,我解释了比特币作为一个在线的电子货币。但是这只是更大更有趣的故事之中的一小部分。正如我们所见,每个比特币交易里都有一段比特币脚本语言。这个脚本在这篇文章里被简化成了类似于这样的话 “我Alice要给Bob 10个比特币”。 但是这个脚本语言可以同时被用来表述更复杂的交易。换句话说,比特币是一个可编程的货币。在以后的文章里,我会解释这个脚本系统和如何将比特币脚本作为一个平台来支持各种各样的令人惊叹的金融产品。
(完)