Plasma研究之旅:Part 2
在Part 1中,我们开启了Plasma的研究之旅,探索一种能够保留以太坊链安全性且仅需偶尔进行恒定大小链上交易的高吞吐量支付系统。我们以Plasma Cash结构作为结束,虽然它带来了我们所寻求的许多特性,但也存在两个主要缺点:Plasma Cash“代币”实际上是非同质化代币(限制了支付面额的灵活性),并且要求用户存储一个庞大且不断增长的数据集。
在这里,我们将探讨一些基于Plasma Cash(或重新思考它)的额外功能和机制,旨在规避或至少缓解这些缺点。
首先声明:事情会变得复杂。借用数学家Peter Saran的比喻,这类研究可能会让人感觉像是在试图铺平一张比房间稍大的地毯;踩下一个角落,另一部分就会意外地弹起来。此外,这将开始接近Plasma研究的事件视界;正如我们将看到的,一些问题仍然悬而未决,这里讨论的许多内容仍在探索中,进一步的进展和发现不断出现。
那么,让我们继续前进:
数据存储问题的缓解
在(我们称之为)Vanilla Plasma Cash中,我们看到每个客户端需要存储的数据量随时间线性增长;即,对于每个代币,每个Plasma块都需要一个Merkle证明,证明包含(代币被花费)或排除(代币未动)。整个历史记录是必要的,因为无法预测用户可能需要哪一部分来解决争议。存储所有这些数据是一个痛点,每次支付时将所有数据转移给下一个所有者更是如此。
为了缓解这种痛苦,想象一下,如果在某些固定间隔——比如每两周或每500个Plasma块——发生一些“链上事件”,正式确立某些(或所有)Plasma Cash代币的所有权。这个想法是,一旦这个“链上事件”最终确定,它将作为一个历史检查点:未来的所有权证明现在只需要追溯到这一点;不允许涉及任何先前历史的争议。因此,所有先前块的Merkle证明都可以安全地永久丢弃。这将为客户端数据的大小设定一个具体的上限。这是一个巨大的胜利。
首先,我们需要让这些检查点工作,Plasma操作员(或任何其他人,但为了简单起见,我们假设是操作员)需要有一种方式来证明在给定Plasma块时所有代币的完整状态。正如你可能已经猜到的那样,这将涉及Merkle树:操作员构建一个简单地将每个代币映射到其所有者地址的树,然后将Merkle根发送到主链;每个所有者接收其相应的Merkle分支;如果两周(或其他时间)后这一切都没有受到挑战,我们认为这个检查点状态是官方的。(这确实要求每个用户在线接收这些数据并监控链,但回想一下,对于Plasma,与任何第2层结构一样,这种活跃性是必需的。)
我们准备好了吗?唉,生活并不简单。不幸的是,上述检查点机制引入了一个相当棘手的边缘情况。假设一个恶意/被攻破/无聊的操作员广播了检查点的Merkle根,但随后没有与用户分享任何Merkle证明数据。现在该怎么办?任何让用户强制操作员提供这些数据的方法都会让我们进入说话者-听者故障等价领域,伴随着常见的烦恼向量和复杂性。我们可以指出,用户仍然可以选择安全地将他们的资金提取回主链,这在技术上是正确的。但问题是,现在每个用户都将不得不涌入主链,并且由于我们刚刚引入的检查点,他们必须在一个有界的两周窗口内这样做。我们在第1部分中聪明地按下的“大规模退出”地毯角落又弹了起来。
但一切并没有丢失;我们可以通过额外的“加密经济聚合签名”工作来挽救局面(比听起来不那么可怕,我保证)。本质上,我们稍微修改所有权证明,使得操作员需要检查点中每个代币所有者的签名;换句话说,操作员只能在获得所有者明确同意的情况下检查点代币。操作员还在链上发布一些额外的数据:证明哪些代币包含在检查点中(想象每个代币在二进制数字列表中表示,“1”表示同意/包含,“0”表示排除。)
尽管这可能看起来违反直觉,但这足以解决问题!这里的关键观察是,每个代币都有一些有效的所有者;所有者知道他们是谁,同样,他们知道他们是否同意给定的检查点。因此,他们唯一需要担心的情况是他们没有签署检查点他们的一个代币,但仍然在代币的槽中看到“1”。在这种情况下,他们只需挑战——一个他们知道会成功的挑战——并使检查点无效。避免了大规模退出,检查点安全无恙。
第2层的纯粹主义者会很快注意到,这里的链上要求并不是“严格Plasma”的方法;位图数据的大小与代币数量线性相关。然而,从实际角度来看,这个成本应该相当小,特别是在大多数情况下,数据可能会通过简单的位域压缩技术大幅减少。此外,检查点对所有它公证的代币都有好处,因此链上交易的成本理想情况下应该由所有代币的所有者分摊。加上检查点是自愿的这一事实,这最终(可以说)是一个相当具体的胜利。
另一种更先进的最小化存储需求的方法是将许多Plasma块证明有效地压缩为一个。再次回想,对于Vanilla Plasma Cash代币,每个块都需要一个包含或排除的Merkle证明。现在的想法是添加一个包含要求:我们不仅需要链上的Merkle根和链下的Merkle分支,还需要一个链上的“RSA累加器”(一种使用纯数论证明成员资格的次要方法)和一个链下的“知识证明”(细节稍后解释,现在只需接受它)。由于这两者都是证明包含所必需的,因此只需其中一个来证明排除;即,一个代币要么包含在一个块中,要么不包含;没有其他可能性,并且“A和B(用于包含)”的否定是“A或B(用于排除)”。
在高层次上,这种结构利用了排除本质上更简单的事实;如果一个代币被包含,我们需要一些更多的数据——至少是其新接收者的地址。而在排除的情况下,“这个代币没有被包含”就是全部需要说的。有理由认为,我们应该能够利用这种不对称性,为排除情况提供一个负担较轻的承诺方案。
(警告:数学来了)
简化后,它是这样工作的:像通常的Plasma Cash M.O.一样,每个代币将获得一个自然数形式的ID,但现在我们将施加一个额外的要求,即所有这些ID都是素数。每个Plasma块提交的RSA累加器(G)本身只是一个数字;它根据每个Plasma块中转移的代币进行更新。
本质上,G被提升为当前块中每个花费代币的ID的幂。例如,在块101中,ID为5、7、17、53和83的代币被转移(都是素数,#Don'tTrustVerify)。让我们称第100块提交的累加器值为G₁₀₀(某个大数字);块101的累加器值计算如下:
这个新的G₁₀₁值被提交到主链。
在链下的第2层世界中,对于Alice(假设她拥有“17”代币)来说,要确保她的代币被包含在累加器中,她只需要指数中的17的共因子——5*7*53*83(顺便说一下,这是153,965)。她获取主链上的G₁₀₁和G₁₀₁,并自行验证:
这确认了她的代币编号17被吸收到累加器中。她还获得通常的Merkle分支承诺;一旦她也确认了这一点,她就准备好了。
现在让我们考虑Bob,他拥有ID为11的代币,注意,这个代币在块101中没有被转移。为了获得他的排除证明,Bob需要证明他的数字11不是153,965的因子。为此,他只需要一个共因子来显示11是某个接近5 * 7 * 17 * 53的数字的因子,且小于11。再次,他基本上只需要一个数字。一旦他有了这个,他就完成了;再次,鉴于我们要求的“或者/或者”性质,排除证明不需要Bob担心任何Merkle分支的事情。
最后,这里是关键:鉴于指数和素数分解的性质,上述过程在任何数量的块之间都是关联的;也就是说,上述为Bob描述的过程可以用于不连续的块。换句话说,块100和101之间的非包含证明与块100和1,000,000之间的非包含证明看起来完全一样;两者都只需要Bob存储一个数字。
(数学结束)
如果你仔细想想,可以安全地假设在给定代币的生命周期中,它很可能只会偶尔被转移;在绝大多数Plasma块中,它可能会保持不动。通过我们刚刚介绍的机制,代币转移之间的间隔现在只需要恒定大小的数据(只需一个或两个数字);因此,现在客户端数据存储仅随每次代币转移而增加。这是一个大问题。
关于上述简化的一些注意事项:如上所述,G的值将迅速变得天文数字般巨大。我们忽略的一个细节是,该值在某些模数M处有一个上限;这个模数让我们可以限制累加器值的增长,同时仍然保留我们所需的所有素数因子信息。此外,即使有了这个上限,对于Alice和Bob来说,执行他们的验证步骤也需要进行一些相当繁重的算术。事实证明,这是可以克服的:有几种紧凑的证明方案可用,这意味着,简而言之,他们可以验证他们关心的结果,而不必进行完整、繁琐的计算。
然而,还有一个不幸的复杂问题需要解决,我遗憾地报告,这可能没有一个干净的解决方案。轻松、轻量级的证明验证确实值得庆祝,但我们不要忘记,有人(即操作员)必须首先生成所有这些证明。计算大量复合指数在计算上是相当昂贵的,当然对于消费级笔记本电脑来说,这太多了。
因此,至少,这将要求操作员拥有一些更强大的服务器端设备。我们希望我们能够找到一种方法来并行化操作,并将部分工作外包给多个操作员,甚至跨Plasma链的用户群。此外,在一个奇妙的宇宙巧合中,其他不相关的以太坊生态系统研究导致了对可验证延迟函数ASIC的兴趣,这些ASIC恰好也需要计算大指数堆栈,因此可能在这里有所帮助。最后,其他与RSA累加器结构类似但具有不同数学/密码学细节的方法——包括向量承诺和ZK-SNARK/STARK类型变体——仍在探索中。然而,这些研究途径最终是否会以经济方式克服计算瓶颈,还有待观察。
最后,我们将转向缓解Plasma Cash的更根本限制:其资产的不可替代性。创建一个5以太的Plasma Cash代币,它不能被拆分或合并;它在整个生命周期中仍然是一个5以太的代币。
为了开始思考如何克服这一点,我们可以首先重新表述我们思考Plasma Cash的方式,而无需实际改变其功能(目前!)。让我们想象一个Plasma Cash链,其中每个代币代表主链上可替代的单一资产(比如以太)的固定面额。之前,我们谈到将每个代币视为具有唯一ID的非同质化代币;Alice的代币#2342可能代表正好20以太。一个功能等效的思考方式是想象Plasma链上的所有以太都存在在一个数轴上;如果链上总共有5,000以太,该线从0延伸到5,000;Alice的20以太不是由某个唯一的(尽管其他方面是任意的)代币ID表示,而是作为数轴上的某个段,即“从520到540的以太”。为了保证每个人以太的适当所有权,合约只需强制执行,每当创建一个新的“范围”时,它存在于之前未被任何其他范围占据的区间中。只要这一点成立,我们就有了与旧模型同构的Plasma Cash模型。
到目前为止,一切都很好——现在,升级:假设Alice正在花费她的“代币”,现在这意味着将她的“范围”的所有权转移给另一方。如果在此过程中,她不仅为范围分配了一个新所有者,还改变了范围的端点呢?如果这成为可能,她将自由地支付Bob少于20的面额的以太,即“只有从520到523的以太”。
为了实现这一点,我们将Plasma Cash结构稍微转向:我们将保留“代币”的概念;每个代币将代表数轴上我们想要支持的最小单位以太的一部分(假设为0.00001以太)。但现在,这些“代币”仅作为抽象存在——它们在任何字面意义上都不构成我们Plasma块的内容;相反,每个块现在是一个交易树,每个交易花费给定范围内的所有代币。如果给定范围内的“代币”中有一个由花费者自己之外的方拥有,真正的所有者可以挑战,我们使用Vanilla Plasma Cash中熟悉的加密经济挑战游戏来解决事情。
所以现在,新的谜题是:Alice如何简洁地向Bob证明她正在交易的整个代币范围都合法地属于她,同样,没有其他交易的范围重叠并“渗入”他的范围?与之前每个交易都自包含于单个代币不同,我们现在需要我们的证明以某种方式传达块中其他交易的信息。
为了达到这个目的,我们引入了……另一个Merkle树变体!我们称这个新的数据结构为Merkle索引树。叶子是交易本身,每个代表代币范围的转移;Merkle索引树的新特点是,现在树中的每个节点也被分配了一个数字。两条规则是:
只要范围的接收者验证上述规则成立,Merkle证明就足以让他们确信没有范围与问题中的范围重叠。尝试打破它;你做不到!
因此,上述结构允许Alice发送她拥有的范围的子部分,这让她在某种意义上“拆分”她的以太。接下来,我们希望用户能够“合并”他们的以太;假设Bob总共有12以太,他从Alice那里收到的“520到523”以太,以及“1001到1010”范围内的以太。我们希望Bob能够将所有12以太作为单一的原子支付发送。
通过一些花哨的技巧,这是可以实现的:没有任何内在的东西阻止单个交易指定多个范围的支付,如果其中任何一个被证明是无效的,所有这些支付都会被取消。问题是,现在接收者需要跟踪两个范围的历史。当然,如果他们然后将所有这些发送给另一方,以及一些额外的范围,该方需要涉及所有范围的历史。因此,我们逐渐接近所有方需要再次验证整个链的终点;“证明大小”地毯角落又弹了起来。
为了应对这一点,当历史大小开始接近有问题的水平时,各方可以“碎片整理”他们的范围。他们通过简单地与其他方交换范围(等值)来做到这一点,以便范围尽可能多地合并;人们可以将其类比为支付通道网络中的通道重新平衡策略。操作员拥有整个网络的全局视图,显然是帮助促进这一点的明显候选人。已经讨论了几种加密经济机制和碎片整理算法来实现这一点,但很可能需要在野外进行测试,看看哪种方法效果最好。
(注意:另一类结构——即混合通道/Plasma模型——也可以为我们提供,除其他外,更大的支付可替代性。这些将在第3部分中探讨。)
结论
恭喜,你做到了!那么,Plasma方面的情况如何?Plasma难题是否已经破解?很难说;上述描述似乎都不是银弹解决方案,这让人感到不满足;同时,使用我们工具箱中的各种技术可能最终足以使Plasma链可行。时间会证明;无论如何,研发以惊人的速度推进,所以很可能,在你阅读这篇文章时,已经有更多的事情需要应对(抱歉)。下次见,祝你好运。