本文介绍了Espresso Sequencer与Rollup之间的衍生管道架构,并探讨了通过该管道实现交易的跨链原子性,以及如何增加Rollup特性。文章深入分析了衍生管道的功能,如何实现共识验证、命名空间过滤和Rollup特定变换,同时讨论了原子交易捆绑的实施方案及其应用。
在 之前的帖子 中,我们描述了Espresso Sequencer如何在保留中心化排序器的众多用户体验(UX)优势的同时,去中心化rollup,并改善rollup之间的互操作性,帮助在有许多不同L2的世界中去碎片化流动性。随着我们 Cortado 测试网上线 的最新公测,我们已在同一个去中心化的排序器上运行了两个来自不同技术栈(OP Stack和Polygon zkEVM)的不同rollup,向实现这一愿景迈出了又一步。
在掌握了这两种不同技术栈集成后,我们将开始分享关于rollup与Espresso Sequencer之间典型集成架构的更多细节。本文将重点讨论架构中的一个关键且少有讨论的部分:派生管道,它连接rollup执行层与排序器。
我们将定义派生管道并分享rollup如何轻松地在Espresso Sequencer上部署,并自定义自己的派生管道。然后我们将描述如何使用派生管道在Espresso Sequencer原生提供的功能之上,添加rollup特性,远比修改rollup的执行层要容易。作为一个例子,我们将描述rollup如何通过修改其派生管道并利用Espresso Sequencer的原子包含特性,支持强大的跨链原子交易捆绑。
让我们比较下在Espresso Sequencer上运行的rollup的架构与今天rollup典型的中心化排序器架构,后者通常如下所示:
排序器,通常是由构建rollup的基金会或公司运营的中心化服务器,生成一串rollup区块:交易和其他元数据的列表。执行管道通过将rollup的状态转移功能应用于区块流,以计算和更新一些状态,从而执行这些区块。然后,这个状态会被发送至另一条区块链,即第一层(L1)。由于执行管道在链下运行,所以L1需要某种形式的证明,以证明rollup状态被正确计算。这通常是通过要求运行执行管道的节点向L1发送简洁证明来做到的,以展示它正确地运行了管道,或者通过乐观地将状态视为正确,直到某个其他节点发送证明证明执行没有做到正确。
在这种架构中,排序器拥有很大的权力。根据具体的rollup设计,它可能会对交易顺序产生对抗性影响(例如,三明治攻击)、审查某些交易以及阻碍活跃性。排序器通常无法影响rollup状态的正确性,因为状态的计算由L1进行验证。然而,在实践中,许多用户还信任排序器承担额外的责任:确定性。用户经常在交易仅被排序器发出时,就认为其交易已最终确认。然而,交易在真正得到L1接收之前实际上并没有最终确认。这意味着排序器可以谎称某个交易已最终确认,然后向L1发送不同的顺序,排除该交易。类似于传统区块链中的分叉,这可能会导致双重支出和资金的损失。
为了解决这一安全风险,我们用在数千个节点上运行的共识协议替代了中心化排序器。任何人都可以向L1合约提交状态更新,只要它与该共识协议的输出一致,在Espresso Sequencer中称为Hotshot。这不仅去中心化了rollup,还消除了任何少于⅓的Espresso Sequencer质押能力的节点联合体在rollup交易顺序上的模棱两可能力。Hotshot具有高度可用性和拜占庭容错性,这基本上意味着除非有大量经济抵押品被恶意方控制,否则它将保持活跃并不会对最终性产生模棱两可的行为。rollup也可以对交易订单施加额外约束。例如,这允许rollup选择性地强制执行先来先服务的订单,或从多种方法中选择来防止三明治攻击等。
我们需要rollup本身来强制执行状态约束,即它执行的区块序列由Hotshot的输出决定,最终这意味着L1需要检查这个约束。因此,我们增加了第二个管道,作为执行管道的输入,其工作是从Espresso Sequencer的输出中派生rollup区块流,并生成某种类型的证明,以表明这一派生是正确的。这就是派生管道。
注意:派生管道已经是今天rollup的一个功能,并且是在OP堆栈中使用的一个术语。今天它用于“授权”排序器,即检查发布到L1的状态更新是否由指定的排序器节点签名。
让我们看一下Espresso区块流在通过特定rollup的派生管道时发生了什么。
派生管道必须做的第一件事情是证明输入中的区块是Espresso Sequencer的顺序输出。幸运的是,支撑Espresso Sequencer的HotShot共识协议会产生可验证的伪证据,以证明每个输出区块的最终性。这些伪证据称为法定人数证书(quorum certificates,QC)。
QC实质上是共识协议参与者的阈值签名,证明某个区块的最终性。因此,证明某个区块是排序器的下一个输出的最直接方法就是将适当QC的正确签名证明纳入发送至L1的正确派生证明中。然而,还有一种更简单的方法。
由于Espresso区块流并不是特定于某一个rollup,因此验证它所需的工作在所有rollup之间共享。因此,Espresso Sequencer将提供一个 L1智能合约 作为公共资源,其唯一工作是验证QC并在L1存储中提供对Espresso区块流的认证承诺。由于正确的派生证明在L1上已经得到了验证,因此rollup的L1合约可以直接从该认证承诺中读取。派生管道因此只需要证明其输入区块流与该承诺一致,而这是可以通过Merkle证明来做到的。
派生管道的下一个工作是将Espresso区块流(其中包含使用Espresso Sequencer的所有rollup的交易)转换为特定于rollup的区块流,其中仅包含此特定rollup的交易。这是通过 名称空间过滤 来实现的:每个rollup都有一个名称空间标识符,类似于链ID,用来识别其交易。Espresso区块中的交易按名称空间分组,因此rollup可以通过从Espresso Sequencer查询服务请求交易,轻松下载仅属于它的交易。
当然,rollup必须能够验证查询服务是否提供了正确的交易,反过来,派生管道必须作为正确派生证明的一部分向L1合约证明这一事实。为了便利这一点,查询服务会同时提供所请求的交易和一个名称空间证明。该证明会将在Espresso区块承诺中,证明所提供的交易列表包括来自请求名称空间的所有交易,并仅包括那些交易,并且按Espresso排序器确定的顺序排列。这个证明在硬件中高效验证,并且对于用于ZK证明的验证在算术电路上也很友好。
派生管道以及最终的rollup合约将根据Espresso区块承诺验证此证明,而该承诺在前一步被验证为来自Espresso排序器的有效输出。名称空间证明的具体设计比较复杂,且与Espresso 的 Savoiardi DA协议 中使用的错误编码方案密切相关。我们将在未来的博客文章中分享更多关于名称空间证明协议的细节。
如前所述,派生管道允许每个独立的rollup在Espresso Sequencer处理中识别和验证其唯一的区块流。并且由于派生管道在逻辑上与执行管道及rollup内部功能的其他方面分隔开来,因此它们可以选择以任何方式解释Espresso区块流。
例如,在 OP stack集成 中,OP stack rollup遵循固定区块时间,因为这是内置于OP stack本身的一个约束。在派生管道中,OP stack可以通过在每个固定大小时间窗口内组合Espresso区块,轻松派生出固定区块时间链。这不需要对OP Stack执行层进行任何更改;仅需要修改如何从Espresso区块流派生OP区块流。
与此同时, Polygon zkEVM stack集成 不进行任何转换,按原样解释区块流。因此rollup还可以直接将区块流取出,并一对一地输入到其执行管道中。
派生管道还支持加密的内存池、公平的订单服务,如 Timeboost、指定构造者以及可能特定于各个rollup的其他设计约束,同时仍然能够轻松支持Espresso Sequencer。
虽然派生管道用于将Espresso Sequencer的区块流拆分为每个独立rollup的较小区块流,但排序器仍然在同一个区块中包含来自多个rollup的交易。
我们可以利用该管道为来自多个rollup的交易提供原子性。原子跨链捆绑是一组交易,仅在同一区块中的所有rollup都包含时有效,否则无效。例如,这可以是两个不同rollup上的两个转账。这类捆绑实现了在不同rollup之间的原子交换。真正的强大之处在于,当原子捆绑与共享构造者或某种桥接机制结合时。这些可以实现全新的应用类别,例如原子桥接或跨链闪电贷( 有关更多细节,请看此讲座)。
原子捆绑的关键特性在于它们是不可分割的,即捆绑中的任何交易本身都是无效的。实现这一点的简单方式是,如果交易捆绑的发行者整体签署它,而且排序器管道确保交易签名的有效性。签名验证是交易执行的一部分,即在rollup内部进行验证。这带来了一个挑战,因为每个rollup只看到与其相关的筛选交易。原子的x-rollup捆绑的简单实现将会破坏与单个rollup的向后兼容性。考虑一下 James Prestwich 提出的以下草案:
有一种适用于捆绑交易的新交易格式,用户整体签署整个rollup捆绑。现在rollup节点可以通过计算捆绑的哈希并检查该捆绑哈希上的签名来验证捆绑交易的有效性。此外,用户需要从捆绑内的交易中剥离签名。这一点很重要,否则恶意构建者可以拆解捆绑并单独提交交易,从而破坏我们试图实现的原子性保证。
这破坏了与当前实现的rollup的向后兼容性,因为rollup需要修改其执行管道以处理剥离了单独签名的捆绑交易。
我们最近在这篇 帖子 中描述了一个类似的方案,该方案实现了相同的原子捆绑,但保持了向后兼容性,即不需要rollup的选项。同样的想法是将一个暂时性的捆绑公钥添加到单个交易中。这个捆绑公钥是作为正常交易签名的一部分进行签署的。具体而言,我们通过在交易的调用数据中附加公钥,以保证不改变交易的含义。然后该公钥可以用于认证捆绑。
具体而言,协议的工作方式如下:
派生管道修改如下:
捆绑交易的包装格式如下:
namespace A
namespace B
signature(namespace A, namespace B, txA', txB') under pk
txA' (with pk appended)
txB' (with pk appended)
生成交易的工作流程可以最清晰地通过一个中心协调者(例如,一个构造者)来可视化。然而,这个协调者可以被简单的点对点协议所替代:
该方案的一个关键属性是交易捆绑是原子的,不能分割并单独提交。这是通过捆绑公钥和签名确保的,这种签名兼具交易以及捆绑该交易的rollup的有效性。该方案达到的另一个重要属性是向后兼容性。通过将公钥附加到调用数据中达到。普通智能合约将简单地忽略这额外的调用数据,因为方法参数的解码在长度扩展时是不可变的,使用 标准ABI编码。
我们在之前的 这篇 博客中列出了跨链原子性应用。跨链原子交易具有一些直接应用,例如原子交换,即在一个rollup上交换一种资产与另一个rollup上的另一种资产。跨链原子性的最强大用例在于,它使构建者能够构建具有原子捆绑的区块。这些捆绑甚至连恶意提议者也无法分割。
构建者可以利用原子捆绑提供保证,用户的交易只有在满足某些预定的执行条件时才会被包含在Espresso Sequencer中。共享排序器正是允许构建者提供这种保证的原因,因为构建者可以完全控制他们正在包括交易的所有rollup的状态。这意味着诚实的构建者不会偏离他们的承诺。我们甚至可以建立新的应用类别,例如依赖于构建者提供的原子性保证的跨链 闪电贷。
这与具有多个排序器的世界相对立,构建者可以向用户提供保证,但未能让他们的区块得到各个排序器的包含。此外,在这种情况下没有办法知道构建者是恶意的,还是仅仅未能说服每个排序器包含他们的区块。这意味着利用经济惩罚的原子性保证与孤立的排序器不兼容,因为诚实的构建者仍然可能随意未能履行他们的承诺。此外,跨链原子性的成功率将不可预测,从而导致更糟糕的经济结果。
- 原文链接: hackmd.io/@EspressoSyste...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!