声明:本文是要点笔记,介绍和系列笔记均收录在专题:区块链技术与应用
1、智能合约的反思——智能合约真的智能吗?(Is smart contract really smart?)
首先我们必须了解智能合约里面并没有用到任何人工智能的技术,所以有人认为应该把它叫做自动合约,按照事先写好的代码,自动执行某些操作,现实世界当中,有什么自动合约的例子吗?ATM 取款机可以看作物理世界上的一个自动合约,按照事先规定好的逻辑去做某些事情。所以智能合约其实并不智能,而且挺笨的,一旦写好了之后就改不了了,就是作为代码合同。(Smart contract is anything but smart.)
2、不可篡改性是把双刃剑(Irrevocability is a double edged sword.)
一般来说我们提到区块链的不可篡改性都认为这个是区块链的一个优点,很多区块链的应用都利用了不可篡改的特性,比如防伪、溯源。但是从“The DAO”事件当中,可以看出不可篡改性其实是一个双刃剑。一方面,不可篡改性增加了合约的公信力,但另一方面,不可篡改性也意味着如果规则中有漏洞,我们想要修补这个漏洞,想软件升级都是很困难的。
The DAO的盗币事件有传闻说,The DAO的开发团队在发生盗币事件前几天已经收到了有关智能合约中存在安全漏洞的消息,但是没有来的及发布更新后的软件。这个如果是对于一个中心化的系统,大家可能会觉得是很难想象的,如果你发现你的软件中的安全漏洞,你干嘛不及时发布一个安全补丁呢。但是问题在于在区块链的世界里,你怎么发布补丁,软件更新需要硬分叉来实现,还需要得到大部分矿工的支持。无论是比特币还是以太坊,硬分叉都不是随便搞的,这次以太坊搞的硬分叉,最后就造成了两条平行的链,而且要搞硬分叉要说明理由,否则别的矿工为什么要升级你的软件,而你一旦说明理由的话,那就会把安全漏洞的信息泄露出去,那么有恶意的攻击者,在还没有来得及升级软件之前抢先发动攻击,这些都是区块链上不可篡改性带来的一些问题。
不可篡改性还导致另一个问题,即使我们发现了这个安全漏洞,已经有人进行恶意攻击了,我们想要冻结账户,终止交易都是很困难的。
这个和我们如常生活的体验不太一样的地方,比如说你的银行卡的信息被泄露了,第一反应是通知银行,冻结账户,修改密码。很多人在刚接触区块链的时候也是同样的反应,发现比特币账户的私钥泄露出去了,怎么办,赶紧通知谁把账户给冻结了,没有办法冻结,要冻结的话只能软分叉。实质上要发布一个软件更新,有关要冻结的账户的交易都不予执行,这才可以冻结,对于个人来说,你的私钥泄露出去了,搞一个软分叉,这是不可能的,对于普通人只能尽快将剩下的资金转到安全账户。
与之相关的一个问题,智能合约发布到区块链上就无法阻止别人对它的调用,比如说这次的盗币事件,黑客偷走了差不多1/3的以太币,还有2/3的以太币还在 The DAO 相关的子基金里,同样存在着安全的风险。我们传统直观的认为,智能合约出问题了,那就不能让别人去调用它了。但在区块链上你没办法组织别人对它的调用,你要阻止的话又得要软分叉,增加一条新的规则,凡是调用这个智能合约的交易都不予执行。
所以还剩的2/3的资金应该也及时转走,怎么转走?利用黑客的这个漏洞把钱转走。当时就有人建议这么做的,比如说你是个好人,你创建一个新的智能合约,把这个事情公布给大家,说现在要利用黑客的漏洞把剩下的钱转移到安全的智能合约,手段和重入攻击是一样的,只不过你的目的是好的,这个新的合约的目的是将来把钱退给大家。
3、没有什么是真的不可篡改的(Nothing is irrevocability.)
理论上,没有什么什么是绝对不可篡改的,比如分叉攻击可以回滚交易。“The DAO”事件中,以太坊开发团队通过软件升级方式强行改变了某些账户的状态,所以不能迷信不可篡改的特性。毕竟代码是死的人是活的,没有什么是绝对改不了的,连宪法都可以修宪,比如美国的宪法修正案,修宪是很难的,但是有必要的时候还是可以改的。区块链上是一样的,想要篡改是比较难的,但是遇到重大事件,要是想改还是改的了的。
4、合约语言设计的反思(Is solidity the right programming language?)
为什么会出现重入攻击这样的事情,从某种意义上来说,solidity 语言上有一些反自然的特性,我们一般的理解是我给你转账,你是一个被动的接收者,你不可能再回来调用我。但solidity语言的特性是,我给你转账等于调用了你的fallback()函数,虽然表面上我没有调用任何的函数,结果你还可以倒过来调用我。这个和平时的生活体验不一样,所以容易忽视这样的安全漏洞。
有人提议应该改进为函数式编程语言,这样比较安全,不容易出现漏洞。而且从长远来看,要实现理论上证明智能合约的正确性。如果能够用形式化验证(formal verification)的方式,证明一段程序的正确性,那么将能够解决智能合约的漏洞问题,这个有些人曾经认为是智能合约的一个终极目标。但是形式化验证距离实用仍有很大的距离,一般只能证明一些逻辑简单的正确性,而且在证明过程要屏蔽掉很多实现上的细节,这样导致的结果就是即使这个程序从理论上可以证明的正确的,实际跑起来可能仍然有问题。从语言设计上来说,solidity有很多值得改进的地方,但是不是说我们就该用函数式编程语言,就应该用formal proof的方法证明程序的正确性,这个还有待探讨。
语言设计上的第二个反思是,编写智能合约的语言应该有什么表达能力。我们前面讲过比特币和以太坊的区别,比特币的脚本语言就是很简单的,表达能力很差,而以太坊的编程语言叫图灵完备的,凡是计算机能完成的任务,语言都能实现起来,但是图灵完备的表达能力是不是一个好事情。出现智能合约的漏洞后,有些人认为,应该选取一个表达能力适中的语言,它可以实现智能合约的功能,又不容易出现漏洞。但是难以设计出适当的语言,因为设计语言的时候很难预料将来所有可能出现的事情,也很难预料将来可能出现的所有安全攻击。
我们说比特币脚本是很简单的,但在实际应用中大部分矿工也只是接收几个常用的脚本,有一个安全脚本的白名单,如果交易的脚本不在白名单里面,很多矿工缺省情况下是不接受的。联想到现实中的合同,也会出现由于不严谨出现一些纠纷,所以通常使用模板写合同来规避这些问题。智能合约可以参考这种在模板基础上书写合约的方法,以后应该也会出现类似写智能合约的专门机构。所以大家不要对智能合约出现了各种各样的问题就对它丧失信心,智能合约的历史相对来说比较短的,最终还是会走向成熟。
5、开源软件漏洞的反思(Many eyeball fallacy.)
去中心化的系统一般都是开源的,因为需要所有节点执行同样的操作,才能达成共识。开源的一个好处就是增加合约的公信力,接受群众的监督;有人认为另一个好处是不容易出现安全漏洞,因为全世界有这么多双眼睛在看着这个代码,但实际情况并不如此,我们也看到了智能合约的代码出现了各种各样的漏洞,而且这个问题不是智能合约所特有的,其他开源的软件也有类似的问题。那为什么全世界有这么多双眼睛看着还出现了这么多漏洞?
理论上代码是开源的,但实际上去研究代码的人是很少的,例如像“The DAO”这样涉及到财产安全的项目,你要把你的钱投进去,投钱之前是不是需要检查下这个智能合约靠不靠谱,但是很多人都没有仔细看,看的人可能也没有足够的安全知识去检测里面的安全漏洞。有很多手机上的区块链钱包也是开源的,也是涉及到财产安全的,那么有多少人是去看了钱包的源代码的,有多少是看的懂的,大家都认为别人一定看过了,实际上可能没有谁认真看过,所以不要认为开源软件一定比不开源的软件安全,有很多人用的软件也不一定没有安全漏洞,历史上有很多开源软件的安全漏洞是很多年后发现的。所以这些关键性应用我们还是要小心仔细,需要自己去检查下智能合约是否有安全问题。
6、去中心化的反思(What does decentralization mean?)
区块链技术的追随者一般都是去中心理念的拥护者,这些人呢对于现实生活中中心化的管理方式不满意,所以在区块链的世界中去寻找一种全新的管理方式。这也是为什么以太坊开发团队在推出了硬分叉的解决方案后引发了这么大的争议,有很多人认为又回到了中心化的老路上面,你开发团队凭什么用一个软件升级就把一个人账上的钱转走,这个岂不是比中心化更中心化,在中心化的社会里要没收一个人的财产还需要通过法律各种各样的程序,28天以内还不一定能完成。
但是回想一下这个硬分叉的过程,是不是就是以太坊的开发团队说的算的。首先他们搞了一个投票,最后是大部分人投票支持硬分叉,但是更重要的是以太坊的团队是没有办法强迫大家支持这个投票结果,最后硬分叉能够成功是因为什么,是因为90%以上的矿工升级了软件,用行动支持了硬分叉,即使是这样还有少部分的矿工不支持硬分叉的方案,继续留在旧链上挖矿,那也是他们的自由,以太坊的团队没有什么办法强制他们转过来。所以说去中心化并不是说全自动化,让机器决定一切,不能有人为的干预,去中心化也不是说已经制定的规则就不能修改,而是说对规则的修改需要用去中心化的方式完成。我们平时说是用脚投票,区块链的世界里是用挖矿来投票的。这次硬分叉为什么成功,是因为绝大多数矿工认为以太坊的开发团队所做的决定是符合大部分人的利益的,大家不要低估了广大部分矿工的思想觉悟。如果以太坊开发团队为了一己私利做了什么决定,那广大工人阶级是不会跟着他们这样干的,这是关于去中心化的反思。
关于分叉的事情,我们一般认为分叉是件坏事,但是你仔细想一下分叉恰恰是去中心化的体现。在一个中心化的系统里,你是没有办法分叉的,你可以选择放弃,但是你不能选择分叉。比如以太坊创始人V神的故事,19岁的他非常喜欢打魔兽世界,直到有一天暴雪公司把他最喜欢的技能去掉了,他非常生气,多次找暴雪公司的人反馈,没有得到任何满意的结果,他一气之下就不玩了,后来他就想为什么会出现这种情况, 本质上是因为这个游戏是一个去中心化的游戏,决定权在公司,普通用户没有任何办法,所以他决定要去创建一个去中心的平台,用户不满意就有选择分叉的权利。所以存在分叉的选项恰恰是民主的体现。
7、去中心化与分布式的反思(decentralized ≠ distributed)
一个去中心化系统必然是分布式的,但是分布式系统不一定是去中心化的,即使这个系统运行在成千上万的计算机上,如果这些计算机都是由同一个组织所管辖的,那么也不能叫做去中心化的。在分布式的平台上可以运行一个中心化的应用,也可以运行一个去中心化的应用。
比特币和以太坊都是交易驱动的状态机(state machine),他的特点是让系统中几千台计算机做同一个操作,付出很大的代价来维护状态的一致性,而这个并不是分布式系统常用的工作模式,大多数的分布系统是让不同机器做不同的事情。然后再把各台机器的结果汇总起来,得到最后的结果,这样做的目的是为了比单机的速度要快。比如说1台计算机要完成的任务,可能需要一个星期,用10台计算机的分布式集群,可能一天就完成了,最理想的状况是得到线性加速,就是10台计算机的速度比1台计算机的速度要快10倍,但是实际应用当中,线性加速是很难达到的,因为存在任务切分,任务通讯,结果汇总都是有overlap,所以实际应用当中10台计算的速度可能相当于1台计算机的6、7倍,但是任然要比1台计算机要强,这样分布式系统才有意义。
状态机的模式不是这样的,状态机的目的不是比1台计算的处理速度快,而是为了容错。状态机最早的应用场景是什么,是一些mission critical applications(关键运算应用),比如像airtraffic control, stock exchange, space shuttle,这些是一些状态机常见的应用场景,这些场景的特点是什么?这些应用程序必须无间断的向外提供服务,所以需要好几台计算机重复同一种操作,这样即使1台计算机宕机,这样还能向外提供服务,这是状态机模式的原理。这样付出的代价是什么,效率很低,几台机器合在一起比一台机器还要慢,因为它要同步状态,而且集群里的机器越多速度越慢,所以传统利用状态机的模型里面机器的数量是比较少的,有很多就是个位数的。像比特币、以太坊这样上千台机器重复同一组操作,在以前是从来没有过的。所以不要以为比特币和以太坊是分布式系统的常态,我们理解了这点就能理解智能合约比较适用的场景是什么,不要把智能合约EVM平台当成大规模计算或者大规模存储等服务,如果你这么做的话,不光是速度很慢,而且也是非常贵的,因为要耗很多汽油费、智能合约是用来编写控制逻辑的,只有那些需要在互不信任的实体之间建立共识的操作,才需要写在智能合约里。如果你需要大规模计算服务的话,可以用亚马逊的云服务平台。