区块链圈子里有一种常见的观点是这样的:区块链应该尽可能简单,因为它们是基础设施的一部分,难以变更,而且一旦出了问题就会导致巨大的损失
区块链圈子里有一种常见的观点是这样的:区块链应该尽可能简单,因为它们是基础设施的一部分,难以变更,而且一旦出了问题就会导致巨大的损失,更复杂的功能应该以二层协议的形式,如状态通道,等离子体,汇总,等等,建立在基础层之上。也就是说,想创新,就应该在第二层上做文章,99金银而第一层应该尽可能稳定,以维护为主,除非事态紧急,不应引入大的变更(例如,为了保护基础协议的密码元件免受量子计算攻击,一次性引入一组破坏性的更新,是可以接受的)。
这种分层构想很妙,从长远角度来看,我表示强烈支持。然而,这一构想忽视了很重要的一点:第一层不能过于强大,否则会增强复杂性和脆弱性,但是第一层又必须强大到足以支持人们在其基础上搭建2层协议。一旦图层1协议实现了一定程度上的功能性——我称之为“功能性逃逸速度(功能逃逸速度)”,那么你就能在不改变基础层的情况下随心所欲地搭建任何东西。但如果图层1不够强大的话,你再怎么设想用2层系统来弥补,你都不得不引入一系列信任假设(以构建出那些层2系统),这就与第一层一直以来都在追求的免信任性冲突了(译者注:亦即本该由第一层用免信任的方式提供的服务变成由需要信任的方案来提供了)。在本文中,我会谈一谈构成“功能性逃逸速度”的最低限度功能性是哪些。
一种编程语言
必须要能够在链上执行用户自定义的脚本。这种编程语言可以是很简单的,实际上也不需要很高的性能,但是至少要具备一定程度的功能性,能够满足任意数据的验证需求。这一点非常重要,因为搭建在图层1之上的层2协议需要具备某种验证逻辑,而且这种验证逻辑必须能由区块链执行。
你可能听说过图灵完备性。用大白话来解释就是,如果某种编程语言是图灵完备的,就可以通过它来让计算机执行理论上可以执行的一切操作。任何使用图灵完备的语言编写的程序都可以被翻译成使用其他任意一种图灵完备的语言编写的相同程序。
不过,事实证明,我们只需要稍微轻便一些的解决方案:哪怕只能写出没有循环的程序,或者写出的程序在一定步骤之内必定会终止(译者注:即非图灵完备),都是没问题的。
丰富的有状态性(“富状态性”)
除了要有编程语言之外,如何将这种编程语言集成到区块链中也很重要。一种局限性较大的集成方法,是将这种编程语言用于纯粹的交易验证:当你要把密码学货币发到某个地址上时,该地址就化身成一个计算机程序P,该程序日后将被用于验证从那个地址发出的交易。也就是说,如果你发送了一个哈希值为h的交易,然后提供一个签名,区块链就会运行程序P (h, S),如果输出为真,该交易即为有效的。通常来说,P是密码学签名方案的验证程序,但它可以执行更为复杂的操作。特别要注意的是,在这种模式中P无法访问交易的目标地址。
但是,这种“纯函数”解决方案还不够。这是因为这种基于纯函数的解决方案还不够强大,无法实现人们想要的多种层2协议。它可以实现状态通道(以及像闪电网络那样基于状态通道的系统),但是无法实现更强大的扩容技术,也不能用来引导具有更复杂的状态概念的系统,等等。
下面举一个简单的例子来解释纯函数范式的局限性。想象一个储蓄账户,还有一个可以发起提款的密钥k。如果发起了提款,可以在24小时之内使用同一个密钥k取消提款。如果在24小时内仍未取消提款的话,任何人都可以“戳戳”一下账户来完成提款。其目的是,如果密钥被偷了,
金银行情账户持有者可以防止小偷提取钱包内的资金。小偷当然可以阻止账户所有者提取资金,但是这种攻击是无利可图的,因此小偷不会自找麻烦(关于该技术的说明,可以阅读这篇原始论文)。
遗憾的是,这个技术无法仅通过纯函数来实现。问题在于:需要某种办法将密码学货币从“常规”状态转换到“等待提款”状态。但是,程序P无法访问目标地址!因此,凡是可以授权将这些币转换到“等待提款”状态的交易也可以授权盗取这些密码学货币每分钟无法分辨其中的差异。对于包括层2协议在内的许多应用程序来说,重要的是要能够改变密码学货币的状态,但又不会彻底释放这些密码学货币.Plasma本身就符合这种“授权,最终确定,取消“范式,必须得到许可才能从等离子体上退出,而且还会开启7天的挑战期。在挑战期内,只要提供了正确的证据,就可以取消退出.Rollup也需要这一功能:汇总内的资金必须由一个持续追踪状态根R的程序来控制,如果某个验证程序P (R, R的数据),返回“真实”,这个状态根就会从R更改为R”——仅在这种情况下,状态才会改为R,并且不会完全释放这些资金。
能够在不完全释放账户内资金的情况下授权状态变更就是我所说的“富状态性”。富状态性可以通过多种方式实现,其中一些方式是基于UTXO的。但是,如果不具备富状态性的话,区块链必须引入信任假设(例如,需要信任一组参与者来执行富状态性程序),否则无法支持大多数层2协议的实现。
注:我知道如果P可以访问h的话,你就可以将目标地址作为一部分包括在年代里,并对h照进行检查,从而限制状态变更。但是有可能出现一些问题,即,编程语言在资源或者其他因素上太过受限,以至于无法做到这一点。令人惊讶的是,区块链脚本语言经常会出现这些情况。
充分数据可扩展性及低时延
已然清楚的是,像等离子体状态通道或者其他完全放在链下的层2协议,都有一些根本性的弱点,这使得它们无法完全取代2层的功能。我在这篇文章里细究过其中的缘由;总的来说,问题在于,当恶意参与方没能拿出他们承诺要提供的数据时,协议必须有能力评断是非,但是,因为数据公开的行为并不是全局可验证的(你真不知道数据是什么时候公开的,除非你已经下载到了),所以这些挑战游戏是没有博弈理论均衡的(不是game-throretically稳定)。状态通道和等离子体都通过加入额外的安全假设来解决这个问题,尤其是假设:对于任一部分状态,皆有某个与之有利益相关的行动者(通常来说就是那部分状态代表了该行动者的资产)保存有未被非法修改的状态,因此我们可以相信他们会为了自己的利益站出来。但是,这个假设并不是普遍为真的,举个例子,像Uniswap这样的应用就包含一个很大的,不属于任何人的“中心化”合约,既然它不属于任何人,这种诉诸自利的模式也就没法起到保护作用。
有一种办法可以解决这个问题,就是利用2层协议仅在链上发布极少量数据,但是把计算完全放到链下。只要能保证数据是可以用的,那么把计算放到链下就没问题,因为评断谁有没有做出正确计算的挑战游戏在博弈理论上是存在均衡的(稳定)(或者也可以完全替换成蛇鲨或者斯塔克斯(编者注:中译本见文末))。这就是ZK汇总和乐观汇总背后的理念,只要一条区块链支持发布合理大小的数据,并能保证其可用性,那么即便其计算能力很有限,该区块链一样能支持这些2层协议,并实现高可扩展性和功能性。
那么区块链到底需要处理和保护多大的数据量呢?这取决于你想要系统表现出多高的性能。使用汇总技术,你可以将绝大多数活动的交易数据压缩到约10 ~ 20字节/笔,所以1 kb /秒的数据吞吐量可以实现50 ~ 100 TPS,而1 mb /秒的数据吞吐量就万是5至10万TPS,以此类推。好消息是,互联网的带宽增长得越来越快,而且似乎没有像计算领域的摩尔定律一样减慢速度,所以提升数据吞吐量同时不改变计算负担,极有可能是区块链可以采取的一条路径!
同样值得注意的是,不仅数据的容量很重要,数据的时延也很重要(就是要降低出块时间)。像汇总(在这里等离子体也是)这样的2层协议,只是给出了数据将会发布到链上的安全性保证,因此,爱丽丝和鲍勃的支付体验,就取决于爱丽丝发出交易,鲍勃确信自己已经收到钱两个事件之间的间隔,就等于数据被可靠地打包到链上(理想一点来说就是“finaliized”)所花去的时间。基础层的出块时间决定了任何基于数据上链来确认的事项的时延。此外,虽然可以通过链上安全保证金(也就是“债券”)来缓解这种问题(译者注:类似安全保证金和挑战期的方案),但代价就是低下的资金流转效率,而且因为恶意者可以通过牺牲一份保证金来蒙骗无数人,所以这种办法也是有内在缺陷的。