区块链这个东西是好,但区块越深,通过创建新链来替换它所需要的计算量就越大。链条越长,运行攻击的代价就越昂贵。这就是一个矛盾。那么,到底能不能把它做小呢?Google工程师这篇文章将对最小可行性区块链原理进行深入解析,希望对你有所帮助。

加密货币,特别是比特币,几乎从各个方面都得到了大量关注:规则、管理、税务、技术、产品创新等等,不胜枚举。“点对点(去中心化)电子现金系统”的概念颠覆了我们以前对货币和金融所持有的设想。

图1

即便如此,把数字货币方面搁到一边,还有一个可以说是更有趣更深远的创新,即底层的区块链技术。无论你对比特币或是它的山寨币衍生品有什么看法,作为一种货币和价值存储手段,它们背后的运作基础都来自于中本聪概括的区块链原理:

我们运用点对点网络提出了重复花费问题的解决方案。网络通过将交易散列到一个进行中的基于散列的工作量证明链,来对交易进行时间戳标记,并形成一个记录,这个记录只有在重做工作量证明的情况下才能被改变。最长的链不仅作为它所见证事件发生时序的证据,而且也证明它来自最大的CPU功率池……网络本身要求架构最小化。

区块链对任何“货币”都是不可知的。事实上,它可以适用于促成很多其他使用案例。因此,理解“最小可行区块链”背后的方法和原理是有好处的:

以下将从头开始解释为什么需要特定的部分(数字签名、工作量证明、交易区块),以及它们如何集合起来形成具有卓越性能的“最小可行区块链”。

用三式记账法保障交易安全

Alice和Bob是集邮爱好者,偶尔会做做交易。如果双方都看到喜欢的东西,可以当场协商完成交换。换言之,这是个简单的以物易物的系统。

有一天Bob拿来一枚邮票,Alice觉得她必须要收藏,但问题是Bob对Alice所提供的交换物不是特别感兴趣。Alice沮丧不已,她继续和Bob协商,最后达成一致:他们做个单方交易,Bob先把邮票给Alice,Alice承诺以后再偿还Bob。

Bob和Alice已经认识有一阵子了, 但是为了确保两个人都信守承诺(主要是Alice),他们同意让朋友Chuck来对交易“进行公证”。



图2

他们把图2这个可以表明Bob给了Alice一枚“红色邮票”的交易收据做了三个副本(三方各持一份)。Bob和Alice可以用收据来记录他们的交易, Chuck存储副本作为交易证据。这个设定很简单,但其中有一些很重要的属性:

1. Chuck可以鉴定Alice和Bob两个人的真实性,以确保不会有人在他们不知情的情况下蓄意伪造交易。

2. Chuck账簿中的收据证明了交易发生。如果Alice声称交易从未发生,那么Bob可以去找Chuck,用他的收据来证明Alice说谎。

3. 如果Chuck的账簿中没有收据,就证明交易未发生过。Alice和Bob都不能伪造交易。他们可以伪造交易收据,声称对方说谎,但同样的,他们可以去找Chuck,查看他的账簿。

4. Alice和Bob都不能篡改当前的交易。如果任意一方篡改了交易,他们可以去Chuck那儿,用储存在Chuck账簿中的副本核实他们的副本。

以上操作就是“三式记账法”,操作简便,对参与双方都能提供很好的保障。但你也看到了它的缺点,对吧?我们对中间人寄予了很大的信任。如果Chuck决定和另一方串通,那么整个系统就土崩瓦解了。

用公钥基础设施(PKI)保障交易安全

Bob不满于使用“可靠中间人”的不安全性,他决定研究一下,发现公钥密码可以免去使用中间人的需要!这里解释一下:

公钥密码,也叫做不对称密码,指的是一种密码算法,它需要两个单独的钥匙,一个是秘密的(私有的),另一个是公共的。尽管这个钥匙对应的两部分不同,但有数学联系。公钥用于对纯文本加密或者查验数字签名;私钥用于解密密码文本或者创建数字签名。

运用第三方(Chuck)的原本意图是要确认有三个属性:

1. 验证真实性: 不能有恶意的一方伪装成其他人。

2. 不可否认性: 事实发生后,参与方不能声称交易没有发生过。

3. 完整性:事实发生后,不能再修改交易收据。

结果是,公钥密码可以满足以上所有要求。简单地说,工作流程如图3所示。



图3

1. Alice和Bob分别生成一个固定的公钥-私钥对。

2. Alice和Bob公布出他们的公钥。

3. Alice以纯文本的形式写一个交易收据。

4. Alice用她的私钥对交易信息的纯文本进行加密。

5. Alice在密码文本上添加一个“由……签名”的纯文本备注。

6. Alice和Bob都储存相应的输出结果。

注意只有在多方参与的时候才需要第五步:如果你不知道是谁签署了信息,就不知道该用谁的公钥来解密,这个问题很快就会变得有关紧要。

这看起来像是没什么特别理由的大量工作,但我们还是来检验一下新收据的属性:

1. Bob不知道Alice的私钥,但问题不大,因为他可以查询她的公钥(公钥是全世界共享的),然后用公钥来解密交易的密码文本。

2. Alice并不是真的在给交易内容“加密”,而是通过使用她的私钥给她“签名”的交易编码:任何人都可以用她的公钥对密码文本进行解密,由于她是唯一拥有私钥的人,这个机制保证了只有她能生成交易的秘密文本。

Bob或针对这个问题的任何其他人,如何获得Alice的公钥?有很多种方法来分发私钥——例如,Alice公布在她的网站上。我们可以假定有这样的合适的机制。

因此,使用公钥基础设施(PKI)可以满足我们之前所有的要求:

1. Bob可以用Alice的公钥通过解密密码文本来证明签名交易的真实性。

2. 只有Alice知道她的私钥,因此Alice不能否认交易的发生——她已经签名了。

3. 没有Alice的私钥,Bob或任何其他人都不能伪造或修改交易。

4. 注意第二条,Alice可以否认她是那个有争议的公钥——私钥对的真正所有者。

5. Alice和Bob只储存了签名交易的副本,消除了对中间人的需要。“神奇”的公钥密码和双方以物易物系统完美匹配。

余额 = Σ(收据)

随着公钥基础设施到位,Bob和Alice又完成了一些交易:Alice从Bob处得到另一张邮票,Bob从Alice那儿也挑了一张邮票。它们都按照与之前相同的步骤,生成签名交易并将它们附加到各自的分类账簿中。



图4

记录是安全的,但有一个小问题:不清楚是否任何一方有未结余额。先前只有一个交易,很清楚是谁欠谁的(Alice欠Bob)以及欠了多少(一枚红色邮票),但是有多个交易以后,情况变得模糊起来。所有的邮票都是等值的吗?如果是,那么Alice有一个负余额。如果不是,那就谁也说不准了!为了解决这个问题,Alice和Bob达成一致如下:

1. 黄色邮票的价值是红色邮票的两倍。

2. 蓝色邮票和红色邮票等值。

最后为了确保他们新协议的安全性,他们用交易的相对值更新了每个交易,重新生成了分类账簿。新的账簿看起来像图5那样。



图5

这样,计算最终余额现在变成了一个简单的事,循环访问所有的交易,将适当的借贷记录应用于各方。最终结果是Alice欠Bob 2个“价值单位”。什么是“价值单位”? 它是由Alice和Bob都同意的任意交换媒介,另外,由于“价值单位”并不耳熟能详,Alice和Bob同意将1个价值单位称为1个chroma(复数形式:chroms)。

上面这些看起来都是小事,但每一个参与者的余额都是分类账簿中所有收据的一个函数这一事实有重要的意义:任何人都可以计算大家的余额。不需要任何可靠的中间人,也不必对系统进行审计。任何人都可以遍历整个分类账簿,核实交易,计算出每一方的未结余额。

多方转移和验证

接下来,Bob无意中发现John有一枚邮票,他实在很喜欢。他告诉John他和Alice在使用的安全分类账簿,并问他是否愿意做个交易,Bob把Alice欠他的余额作为支付手段转移给John——即Bob从John那儿获得邮票,Alice之前欠Bob的金额将变成她欠John的。John同意了,但现在他们有个问题:Bob如何能以安全和可验证的方式把他的余额“转移”给John?经过一番协商,他们想出一个巧妙的计划(如图6所示)。



图6

Bob按照与之前相同的步骤创建了一个新交易,不过他先计算出他想要转移的加密交易的SHA-256校验和(一个唯一的指纹),然后将校验和嵌入新收据中“是什么”一栏。事实上,他在将之前与Alice的交易与新的转移收据链接起来,这样就把它的价值转移给了John。

为了保持事物的简单性,我们假定所有的转移都会“消费掉”被转移交易的全部价值。要把这个系统扩展到使部分转移成为可能并不难,但此时没有必要考虑得那么复杂。

随着新交易到位,John为了安全起见,做了一个加密分类账簿的副本(现在有三个副本)并运行了一些检查来验证它的完整性:

1. John提取了Alice和Bob的公钥,验证前三个交易的真实性。

2. John证实了Bob转移的是一个“有效”交易:

2-1. 待转移交易的地址是Bob。

2-2. Bob此前没有把这个交易转移给任何其他人。

如果所有检查都通过了,他们就完成交易,我们可以通过遍历分类账簿来计算新的余额:Bob有一个净零数余额,Alice有2个chroma的借额,John有2个chroma的贷额(由Alice提供)。这样John现在就可以把他的新分类账簿拿给Alice并要求她支付,即使Alice没有出席交易,也没有问题:

1. Alice可以用Bob的公钥核实新转移交易的签名。

2. Alice可以核实转移的交易是对她和Bob一个有效交易的引用。

以上转移和验证过程是系统一个了不起的属性!注意要让它全部能工作,我们需要两个使能技术:一个是公钥基础设施的运用,使数字签名验证成为可能;另一个是收据账簿,使我们能够查看完整的交易记录以验证余额并链接先前的交易来进行转移。

John和Bob对这个巧妙的解决办法很满意,然后两人分头回家:Bob带着新邮票,John有了新的分类账簿。表面上看一切完美,但是他们刚刚把自己暴露在了一个极具挑战性的安全问题之下……你发现了吗?

重复消费和分布式一致性

在与John完成交易后不久,Bob意识到他们刚刚在他们的系统中引入了一个严重的漏洞,如果他迅速行动,就可以利用这个漏洞:Bob和John都更新了他们的分类账簿来包括新的交易,但是Alice和其他任何人都不知道交易已经发生。结果是,没有什么能阻止Bob接近网络中的其他人,给他们展示旧的账簿副本,而旧的账簿副本里没有他和John的交易!如果Bob说服他们进行交易,就像他和John做的那样,他就可以“重复消费”同一个交易,想进行多少次都可以!



图7

当然,一旦多人拿着新的分类帐簿要求Alice支付,欺诈行为将被检测到,但这已经无济于事了——Bob已经带着战利品跑掉了!

只有两个参与者的时候,不可能受到双重消费攻击,因为要完成交易,你要验证并同时更新两个分类账簿,因此所有分类账簿始终保持同步。然而当我们再添加另外一个参与者时,我们就引入了各参与者之间账簿不完全和不一致的可能性,这就使双重消费成为可能。

在计算机科学语言中,双方分类账簿具有“强一致性”,超过两方的分类账簿则需要某种形式的分布式一致性以解决双重消费的问题。

这个问题最简单的可能的解决方案是要求分类账簿中列出的各方都必须在每个新交易发生时都在场,以便每个人可以同时更新他们的账簿。这个策略对小型的群组有效,但不能扩展到有大量参与者的情况。

分布式一致性网络的要求

我们来设想一下,我们想要将分类账簿扩展到全世界所有集邮者,这样任何人都可以用一种安全的方式交易他们喜欢的邮票。显然,由于地理位置,时区和其他限制,要求每个参与者在每个交易登记的时候都在场是不可能实现的。我们能建立一个不需要每个人都在场批准的系统吗?

1. 地理位置算不上一个真正的问题:我们可以把交流转移到线上。

2. 时区问题可以通过软件解决,我们不需要每个人手动更新分类账簿。相反,我们可以建立一个软件,它能在每个参与者的计算机上运行并代表他们自动接收、批准以及向分类账簿添加交易。

事实上,我们可以建立一个点对点(P2P)网络,负责分发新的交易并获得每个人的批准! 但很可惜,说起来容易做起来难。例如,虽然P2P网络可以解决我们的地理位置和时区问题,但试想即便只有一个参与者离线,会出现什么情况? 我们是不是要阻止所有交易,直到他们再次上线?

注意,“如何”构建P2P网络本身就是一个庞大的课题,构建这样一个网络的底层机制也远超出我们讨论的范围……我们把它作为一个练习留给读者。



图8

原来分布式一致性的问题在计算机科学中已经被深入研究过,并且已经提出了一些有希望成功的解决方案。例如,两阶段提交(2PC)和Paxos都使这样一种机制成为可能,即我们只需要参与者的大多数法定人数(50%以上)接受就能安全地提交新的交易:只要大多数人已经接受交易,就能保证群组中剩下的人最终汇合在同一个交易历史。

即便如此,单单有2PC或Paxos是不够的。比如,在每天都有新参与者加入而其他人不预先通知就消失的情况下,2PC或Paxos如何知道我们P2P集邮者网络中的参与者总数?如果有一个先前的参与者离线,他们是临时还是永久离线? 相似地,还有另一个我们必须考虑的更具挑战性的“Sybil攻击”:没有办法阻止一个恶意参与者创建许多档案,以在我们的P2P网络中获取不公平的投票权份额。

如果系统中的参与者数量是固定的,并且已经验证他们的身份真实有效(也就是说,这是一个可信网络),那么2PC和Paxos都会工作得很好。但我们不断变化的集邮者P2P网络并不是这样的情况。我们走进死胡同了吗? 嗯,并不尽然……

这个问题有个明显的解决方案是从问题陈述中消除“分布的”部分。我们可以不建立一个P2P分布式系统,而是建立一个所有集邮者的全局注册表,记录他们的帐户信息,对他们进行验证并(尝试)确保没人能通过创建多个身份作弊,最重要的是,保证有一个共享的分类账簿副本!具体来说,我们可以建立一个网站,这些交易在网站上进行,网站将在它的集中式数据库里记录所有的交易,以此确保交易的完整性和正确排序。

以上是一个实用的解决方案,但我们得承认,它不尽如人意,因为它迫使我们失去了分类账簿系统点对点的性质。它将所有的信任置于一个单一的集中式系统,这就带来了一组全新的问题:什么是系统的正常运行时间,安全性和冗余;谁来维护系统,他们维护系统的动因是什么;谁有管理访问权限等等。集中式带来了它自己的一系列挑战。

让我们回顾一下在P2P设计中遇到的一些问题:

1. 确保每个参与者始终保持更新状态(强一致性系统)会产生很高的协调成本,影响可用性。如果单个点不可达,整个系统都无法提交新交易。

2. 在实践中,我们不知道P2P网络的全局状态:参与者人数,个体是暂时离线还是决定离开网络等。

3. 假设我们可以解决上述限制,系统仍然可能受到Sybil攻击,恶意用户可以伪造许多身份行使不公平的投票权。

不幸的是,解决上述所有限制是不可能的,除非我们放松一些要求: CAP定理告诉我们,我们的分布式系统不能有很强的一致性,可用性和分区容忍性。因此在实践中,我们的P2P系统必须在(更)弱一致性的假设下操作并克服它可能带来的影响:

1. 我们必须接受一些分类账簿不同步(至少是暂时不同步);

2. 系统最终必须收敛于所有交易的整体序(线性一致性);

3. 系统必须以可预测的方式解决分类账簿冲突;

4. 系统必须强制执行全局不变量——例如,没有重复消费;

5. 系统应该免受Sybil和类似的攻击。

保护网络免受Sybil攻击

在分布式系统中实现一致性,比如通过对每个参与者的投票计数,会出现很多关于各节点“投票权”的问题:允许谁参与,某些节点是否有更多的投票权,是否每个人都平等,以及我们如何强制执行这些规则?

为了保持简单,我们假定每个人的投票是平等的。第一步,我们可以要求每个参与者用私钥在他们的投票上签名,就像在他们的交易收据上签名一样,并将投票传播到他们的节点上——在投票上签名确保了别人不能代表他们投票。然后我们可以制定一个规则,只允许提交一票。如果同一个钥匙签名了多个投票,那么所有的投票都作废——已经下定决心!到目前为止还好,现在难的部分来了……

最开始我们怎么知道允许哪个特定的节点参与?如果只需要一个独特的私钥来签名投票,那么恶意用户可以简单地生成无限的新密钥充斥网络。根本问题是,当生成和使用伪造身份很便宜时,任何投票系统都很容易被颠覆。

为了解决这个问题,我们需要使提交投票的过程变得“昂贵”。提高生成新身份的成本,或者提交投票的过程必须产生足够高的成本。为了让问题更明确,我们来想几个现实世界的例子:

1. 你在当地政府选举中投票时,会要求你出示身份证件(例如护照),而伪造身份证件的成本很高(希望如此)。理论上,没什么能阻止你生成多个伪造的身份证件,但如果成本足够高(伪造的货币成本,被抓的风险等),那么运行Sybil攻击的成本将远大于其收益。

2. 或者,假设提交投票给你带来了一些其他成本(例如支付费用)。如果成本足够高,那么再次的,运行大规模Sybil攻击的障碍也增强了。

注意,上述例子都不能完全“解决”Sybil攻击,但它们也不需要被完全解决。只要我们将攻击的成本提高到大于成功破坏系统所能得到的值,那么系统就是安全的,会按照预期运行。

注意,我们所使用的“安全”的定义是很宽松的。系统仍然会受到操纵,确切的投票计数会受到影响,但关键是恶意参与者不能影响最终的结果。

参与所要求的工作量证明

任何用户都可以通过生成新的私钥—公钥对来轻易地(并且花很少的钱)在我们的P2P网络中生成新的“身份”。同样,任何用户都可以用他们的私钥签名投票并将其发送到P2P网络——这也很便宜,我们的收件箱中大量的垃圾邮件清楚地说明了这一点。 因此,提交新的投票很便宜,恶意用户可以轻易地用尽可能多的投票淹没网络。

但是,如果将以上其中一个步骤变得昂贵,使你不得不消耗更多的精力、时间或金钱,情况会怎样呢? 这就是工作量证明背后的核心思想:

1. 工作量证明步骤对于发送者来说应该是“昂贵的”。

2. 他人验证工作量证明的步骤应该是“便宜的”。

这样一种方法有很多种可能的执行方式,但是为了达到我们的目的,我们可以再次使用之前遇到的密码散列函数的属性(如图9所示)。



图9

1. 很容易计算任何给定消息的散列值。

2. 生成具有给定散列值的消息很昂贵。

我们可以在我们的系统中施加一个新规则,要求每个签名投票必须具有以特定子串开始的散列值,即需要部分散列冲突,比如两个零的前缀。如果这看起来完全是任意的,那是因为它确实是任意的。跟着我的思路,我们通过几个步骤来看看这是如何生效的:

1. 我们假定一个有效的投票陈述是个简单的字符串:"I vote for Bob" (“我投票给Bob”)。

2. 我们可以用同样的SHA-256算法来为我们的投票生成一个散列值。

sha256("I vote for Bob") → b28bfa35bcd071a321589fb3a95cac...

3. 生成的散列值无效因为它没有以我们要求的两个零子串开头。

4. 我们修改一下投票陈述,附加一个任意字符串再试一下:

sha256("I vote for Bob - hash attempt #2") → 7305f4c1b1e7...

5. 生成的散列值也不满足我们的条件,我们更新值,一次又一次地尝试…… 155次尝试之后我们最终得到了:

sha256("I vote for Bob - hash attempt #155") → 008d08b8fe...

上述工作流程的关键属性是,每次我们修改完输入,加密散列函数(在这种情况下是SHA-256)的输出是完全不同的:当我们增加计数时,前一次尝试的散列值并不能透露下一次尝试所得到的散列值的任何信息。因此,生成有效投票并不仅仅是个“难的问题”,我们可以把它比喻成彩票,每次新尝试都会给你一个随机的输出。同时我们也可以通过更改所需前缀的长度来调整彩票的赔率:

1. SHA-256校验和中的每个字符都有16个可能的值: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f.

2. 为了生成有两个零前缀的有效散列,发送者平均需要256 (16^2)次尝试。

3. 将要求变为5个零平均会需要1,000,000 (16^5) 多次尝试……关键是,我们可以轻易提高成本,让发送者找到一个有效散列需要耗费更多CPU周期。

我们可以在一个现代CPU上计算多少个SHA256校验和?它的成本取决于信息大小,CPU 架构和其他变量。如果你对此感到好奇,可以打开控制台,运行一个基准测试程序: $> openssl speed sha.

最终结果是,生成有效投票对于发送者来说是“昂贵的”,但对于接收者验证仍然是微不足道的。接收者散列交易(一次运算)并且核实校验和中包含所需的散列冲突前缀……太好了,那么这对我们的P2P系统有什么用呢?上述工作证明机制使我们能够调整提交投票的成本,从而使破坏系统的总成本(即假冒足够多的有效投票来确保特定结果)高于攻击系统能够获得的价值。

注意,“生成消息的高成本”在很多其他环境中是个有用的属性。例如,垃圾邮件能够运作恰恰是因为生成信息特别便宜。如果我们可以提高发送电子邮件的成本,例如要求工作量证明签名,那么我们可以通过使成本高于利润来打破垃圾邮件的商业模式。

建立最小可行区块链

我们已经谈到了很多基础内容。在讨论区块链如何帮助我们构建安全的分布式账簿之前,我们来快速地扼要概述一下我们的网络设定,属性和待解决的挑战(如图10所示):



图10

1. Alice和Bob完成交易并记录在各自的分类账簿中。 完成后,Bob有一个来自Alice的受公钥基础设施保障的借据。

2. Bob和John完成一个交易,他将Alice的收据转移给John。Bob和John都更新了账簿,但是Alice对交易尚不知情。

2-1. 皆大欢喜的情景:John要求Alice偿还他的新借据,然后Alice得到Bob的公钥,核实了他的交易,如果交易有效,她向John支付所需金额。

2-2. 不太欢乐的情景:Bob用没有记录他和John交易的旧账簿与Katy创建了一个重复消费交易,然后Katy和John同时出现在Alice家却发现只有一个人能得到报偿。

由于分布式账簿的“弱一致性”,重复消费是有可能的:Alice和Katy都不知道John和Bob之间的交易,这就使Bob利用了不一致性为自己谋利。有解决办法吗?如果网络很小,所有参与者都是已知的,那么我们可以要求每个交易在被认定为有效前必须被网络“接受”:

1. 全体一致:每当交易发生时,双方联系所有其他参与者,告知他们交易的有关内容,等所有参与者“同意”后才能提交交易。因此,所有分类账簿同时更新,不可能发生重复消费。

2. 法定人数一致:提高网络的处理速度和可用性(即如果有人离线,仍然可以处理交易),我们可以将上述全体一致的情况放宽到法定人数一致(整个网络的50%)。

对于参与者已知且已核实的小型网络,以上任何一个策略都能立即解决问题。然而,两种策略都不能扩展应用于更大型的动态网络,因为在任何时间点都无法得知参与者的总数和他们的身份:

1. 我们不知道要联系多少人来获得他们的同意。

2. 我们不知道要联系谁来获得他们的同意。

3. 我们不知道在与谁通话。

注意我们可以用任意通信手段来满足上述工作流程:当面,通过网络,信鸽通讯等等!

由于缺乏网络参与者的身份和对他们的全局认识,我们必须要放宽限制。虽然我们不能保证任意特定交易都有效,那并不能阻止我们对接受交易有效的可能性做出陈述:

1. 零确认交易:我们可以在不联系任何其他参与者的情况下接受交易。这是对交易付款方诚信的完全信任——相信他们不会重复消费。

2. N确认交易:我们可以联系网络中(已知)参与者的一部分子集,让他们验证我们的交易。 我们联系的节点越多,抓住企图欺诈我们的恶意方的可能性越大。

“N”的值多大为好?答案取决于要转移的金额以及你与对方的信任度和关系。如果金额很小,你可能愿意接受更高的风险级别,或者你会根据对另一方的了解程度来调整风险容忍度。或者,你会做些额外的工作,联系其他参与者验证你的交易。在任一情况下,处理交易速度(零确认是瞬时发生的),额外工作和交易无效的风险之间都存在一个折衷。

图11

到目前为止一切顺利。不过,有个额外的并发问题我们必须考虑:我们的系统依赖于来自其他节点的交易确认,但是没有什么能阻止恶意用户按照所需生成尽可能多的伪造身份(回想一下,我们系统中的“身份”仅仅是个公钥—私钥对,随便就能生成)来满足 Katy的验收标准。

Bob是否要进行攻击是一个简单的经济学问题:如果收益高于成本,他就会考虑实行攻击。相反,如果Katy可以使运行攻击的成本高于交易的价值,那么她应该是安全的(除非Bob和她有私仇或者愿意在交易上赔钱。但这不在考虑范围内)。为了让问题更明确,我们做出如下假设:

1. Bob转移10个chroma给Katy。

2. 生成伪造身份和交易响应的成本是0.001chroma:维持电脑运行的能源成本,支付网络连接等。

如果Katy要求1001次确认,对于Bob来说实行攻击就没有(经济)意义了。反之,我们可以为每次确认增加一个工作量证明要求,将每次有效响应的成本从0.001chroma增加到1chroma,即找到一个有效散列会占用CPU时间,转化为更高的能源费用。因此,Katy只要求11次确认就可以达到同样效果的安全保障。

注意,Katy每次请求确认也会导致一些成本:她必须耗费努力来发出请求,然后验证响应。此外,如果生成确认和验证的成本是一对一的,那么Katy将承担与交易价值相等的总成本来验证交易……当然,这没有任何经济意义。这就是为什么工作量证明的不对称很关键。

很好,问题解决了,对吧?在这个过程中,我们似乎……造成了另一个经济困境。我们的网络现在验证每个交易产生的成本与交易本身的价值相等甚至更高。虽然这是对恶意参与者的经济威慑,但合法参与者怎么会愿意为他人承担成本?理性的参与者根本不会,这毫无意义。

添加“区块”和交易费用激励

如果网络中的参与者必须承担成本来验证彼此的交易,那我们必须为他们提供经济激励。事实上,我们至少要抵消他们的成本,否则一个“空闲”参与者(任何没有提交自己交易的人)将会代表网络继续累积成本——这样是行不通的。还有一些我们需要解决的其他问题:

1. 如果验证交易的成本等于或高于交易价值本身(为了制止恶意参与者),那么总交易价值是净零,或负数!例如,Bob把10个chroma转移给Katy, Katy又花了10个chroma来补偿其他节点来验证交易,Katy很伤心。

2. Katy如何为确认进行支付?如果那是它自己的交易,就会有一个递归问题。

让我们从显而易见的问题开始:交易费用不能和交易本身的价值一样高。当然,Katy不必原封不动地把所有价值都用于确认交易(比如,她可以分配一半的价值用于确认),但这样又变成了一个利润问题:如果剩余利润(交易价值减去验证费)足够高,欺诈的动机仍然存在。相反,理想情况下,我们希望承担最低的交易费用,并仍然对恶意参与者有强大的威慑,有解决方案吗?

我们可以通过允许网络中的参与者一次性汇集和确认多个交易来激励他们,也就是对一个交易“区块”进行确认。这样做能让他们汇总交易费用,从而降低每个单独交易的验证成本。



图12

一个区块仅仅是(一个或多个)有效交易的集合——把它想象成等同于物理分类账簿中的一个页面。反过来,每个区块包含对前一交易区块(上一页)的引用,整个分类账簿是区块的链接序列,也就是,区块链。想想上面的案例:

1. Alice和Bob生成新交易并公布到网络上。

2. Chris正在等着听新交易通知,每个交易通知包含发送方愿意支付于网络验证和确认交易的交易费用:

2-1. 直到有直接的经济激励(交易费用总额大于他的成本)来完成必要工作来验证未决交易,Chris对未确认的交易进行汇总。

2-2. 一旦过了这个门槛,Chris首先验证每个未决交易,方法是核实所有的输入都不是重复消费。

2-3. 所有交易都被核实后,Chris在未决列表上再添加一个交易(上图中用绿色标识),将所发布交易的费用额转移给他自己。

2-4. Chris生成一个包含未决交易列表的区块,引用前一区块(使我们可以遍历区块并看到整个分类账簿),并执行工作量证明挑战,来生成符合网络既定规则的区块散列值,例如N个前导零的部分散列冲突。

2-5. 最后一旦Chris发现有效区块,他就分发给所有的其他参与者。

3. Alice和Bob在等着监听新的区块公告,寻找他们在列表中的交易:

3-1. Alice和Bob验证区块的完整性,也就是验证工作量证明和区块所包含的交易。

3-2. 如果区块有效,他们的交易在列表中,那么交易就被确认了!

我们在这里前进了一大步。以前我们的网络中只记录了一种类型——签名的交易。现在我们签名了交易和区块。前者由参与交易的个人生成,后者由有意通过验证和确认交易收费的各方生成。

另外请注意,上述方案需要系统中的最小交易量来维持个人创建区块的动机:交易越多,单个交易所需的费用越低。

Alice宣布了一个新的交易,并收到一个Chris确认它的有效区块。有了一个确认,那其余的呢? 而且Chris(但愿)不是唯一一个受到激励来生成区块的参与者。如果其他人同时生成了另外一个区块,这两个区块哪个“有效”?

竞争以赢取交易费用

通过验证交易区块来引入汇总费用的能力,它了不起的部分在于,为网络中的新参与者创造了一个角色,他们有直接的经济激励来保障网络。你现在可以通过验证交易赚取利润,可以盈利的地方,竞争就随之而来,这只会加强网络——一个良性循环和聪明的社会工程!

即便如此,验证交易的竞争动机又产生了另一个有趣的困境:我们如何在分布式网络中协调区块生成工作?简短的回答,你可能已经猜到了,我们不会去协调。我们在系统中再额外添加一些规则,看看它们如何解决这个问题:

1. 允许任意数量的参与者参加(“竞赛”)创建有效区块。不需要协调,感兴趣的参与者反而会去找新的交易,决定是否想要以及何时想要尝试生成有效区块,领取交易费用。

2. 生成有效区块时,立即广播到网络中。

2-1. 其他节点检验区块的有效性(检查每个交易和区块本身的有效性),如果有效,就将其添加到他们的分类账簿中,然后最终重新广播到网络中的其他节点。

2-2. 添加以后,新的区块成为分类账簿的“最高档”。如果同一个节点也在生成区块,那么他们需要中止之前的工作重新开始:他们现在需要更新对最新区块的引用,并且从最新区块中包含的未确认列表里删除所有交易。

2-3. 完成以上步骤后,开始创建新区块,希望他们第一个发现下一有效区块,这样他们能够领取交易费。

3. 重复以上步骤直到宇宙热寂。

生成区块的所有参与者之间缺乏协调意味着网络中会有重复的工作,这也OK!虽然不能保证单个参与者获得特定区块,只要参与网络的预期价值(获得区块的概率乘以预期支出,减去成本)是正的,系统就可以自我维持。

注意,接下来要验证交易的节点之间没有一致性。每个参与者汇总自己的列表,运用不同策略来使预期收益最大化。此外,由于我们工作量证明函数(为区块SHA-256校验和找到一个部分散列冲突)的属性,增加获得区块概率的唯一方法是耗费更多的CPU周期。



图13

还有一个需要应对的警告:两个节点可能会几乎同时发现一个有效区块,并开始在网络中传播——例如上表中的Kent和Chris。因此,一部分网络最终可能会接收Kent的区块作为最高区块,其余的会接受Chris的区块。现在怎么办?

解决链冲突

再次的,我们将采取一种不干涉的手段,让区块生成过程中的任意属性来解决冲突,虽然还有另外一个规则:如果检测到多个链,参与者应立即切换到最长的链,并在其顶部创建。我们来看看这在实践中如何工作:



图14

1. 一些节点会开始在Kent的区块上建立新区块,其他人在Chris的区块上建立。

2. 在某一时刻,有人会发现新的区块,开始在网络中传播。

2-1. 其他节点接受新的区块时,与一个不同的最高区块合作的那部分网络将检测到现在有一个更长的链可替换,这意味着它们需要切换到更长的链上面。

2-2. 作为被丢弃区块的一部分但尚未被确认的任何交易都被放在未决列表中,重新开始这个过程。

2-3. 可能的情况是,竞争状况会持续多个区块,但最终某个分支会超过另一个,网络的其余部分将收敛到同一个最长的链上。

很好,我们现在有了一个策略来解决网络中不同链之间的冲突。具体来说,网络通过将交易记录在链接的区块列表中来允诺交易的线性化。但至关重要的是,它没有允诺个别区块可以“保证”任意一个交易的状态。想想上面的案例:

1. Alice将她的交易发送到网络。

2. Chris生成一个确认她交易的有效区块。

但是链中有一个分叉,当稍后网络收敛在Kent的分支链上时,Chris的区块会被“移除”。因此,即使当Alice接收到一个有她交易的区块,她也不能确定这个区块将来不会被撤消!

没有哪个区块是“最后一个”

没有哪个区块是“最后一个”,永远不会有。 如果检测到更长的链,任何区块都可以被“撤消”。实际上,检测分叉相当快速,但总是存在出现替代链的可能。但是,我们唯一能说的是,特定区块在链中的位置“更深”,它被撤销的可能性就更小。因此,也没有哪个交易可以被视为“最终一个”,我们只能陈述它被撤销的概率。

1. 0确认交易:不必等待任何包含交易的区块就可以进行交换。

2. 1确认交易:最新的有效区块包含交易。

3. N确认交易:有一个包含交易的有效区块,以及N-1个区块建立在那个有效区块上。

如果愿意接受风险,你可以总是选择采用0确认交易:没有交易费用,也不必等待确认,不过你要对对方抱有极大的信任。

但如果你想降低风险,就要等待一个或多个区块建立在你交易所在的区块上。你等的时间越长,在包含你交易的区块上建立的区块越多,出现一个撤销你交易的替代链的可能性越低。

“撤消”指的是参与者使网络接受一个替代交易,将资金转移到除你以外的其他帐户上的情形——例如,你完成交易,移交组件,获得收据,但攻击者接着会注入一个交易,把同样的资金“双重消费”到另一帐户。

为什么区块链的长度可以很好地代表交易“安全性”?如果攻击者想要撤消一个特定交易,那么他需要建立一个链,链开始于列出交易区块的前一区块,然后建立一个由其他区块组成的、比网络当前所用链更长的链。因此,区块越深,通过创建新链来替换它所需要的计算量就越大。链条越长,运行攻击的代价就越昂贵。

在接受交易之前,你要等待多少个区块?它没有一个明确的数字,答案取决于网络的特性(生成每个区块的时间,交易和区块的传播延时,网络大小等)以及交易本身:它的价值,你对另一方的了解,你的风险预测等。

(最小可行)区块链的属性

【个体交易的安全受公钥基础设施保障】

验证交易真实性:恶意方不能伪装成他人,代表他人签名交易。

交易真实性认证只与公钥—私钥对有关。不需要将密钥对与参与者其他数据链接的“强认证”。事实上,单个参与者可以生成和使用多个密钥对!从这一层面上看,网络允许匿名交易。

不可否认性:事实发生后,参与方不能声称交易没有发生过。

完整性:事实发生后,交易不能被修改。

【交易一旦被创建,就被广播到点对点网络中】

交易一旦被创建,就被广播到点对点网络中

【一个或多个交易聚集在“区块”上】

一个区块可以验证一个或多个交易并领取交易费用。

这使得交易费用与每个交易的价值相比仍然是很低的。

有效区块必须有有效的工作量证明解决方案。

有效的工作量输出很难生成,但验证起来很便宜。

工作量证明用于提高生成有效区块的成本,使运行对网络的攻击成本更高。

任意节点都能用于生成有效区块,一旦有效区块生成,就被广播到网络中。

任意节点都能用于生成有效区块,一旦有效区块生成,就被广播到网络中。

每个区块有一个与前一有效区块之间的链接,使我们能够遍历网络中所有交易记录的完整历史。

【节点们寻找新的交易通知,将它们并入分类账簿中】

在区块中包含交易,作为交易“确认”,但这一事实本身不会将交易“最终化”。相反,我们以链的长度代表交易的“安全性”。每个参与者可以选择自己的风险承受水平,从0确认交易到等待任意数量的区块。

所有上述规则和基础设施的组合提供了一个去中心化、点对点的区块链,用于实现签名交易排序的分布式一致性。说得有点多,我知道,但它也为一个大难题提供了巧妙的解决方法。区块链的单个部分(会计,密码技术,网络,工作量证明)并不新颖,但所有这些部分结合起来形成的新属性很值得关注。

原文链接:https://www.igvita.com/2014/05/05/minimum-viable-block-chain/

感谢llya授权《程序员》翻译本文

作者简介:Ilya Grigorik,Google网络性能工程师,W3C网络性能工作组联合主席,《高性能浏览器网络(O’Reilly)》作者。

译者简介:汪晓明,朝夕网络创始人,前Beltal CTO。

声明:本文来自区块链大本营,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。