Unstoppable Sequencing 是与 Spire 合作开发的,充分利用了他们在 Blob 共享方面的专业知识。感谢@norswap 、 @donnoh 、 ETH 、 Ilia Shirobokov 、 Julie以及 Spire 团队的反馈。
介绍
Rollup排序器拥有巨大的权力。它们决定哪些交易被打包、以什么顺序打包以及何时打包。它们是 Layer-2 的守门人。当这些守门人出现故障或审查用户时会发生什么?
通常,用户依赖于“强制包含”,这是一种通过创建 L1 交易来创建 L2 交易的机制。然而,虽然强制包含保留了逃生舱口,但由于 L1 交易需要单独提交而不是批量提交,因此不足以支持Rollup的持续运行。
解决方案:让批量操作无需许可,且经济实惠,任何人都可以接受。只要 Layer1 正常运行,即使出现故障或恶意排序器, Rollup也能保持接近正常的吞吐量。这就是“永不停歇的排序”。
为什么强制包容如今会失败
强制纳入如何运作?
以OP Stack为例,流程如下:
用户调用
OptimismPortal2合约上的depositTransaction函数并指定他们想要进行的 L2 交易的详细信息。门户合约发出一个事件,诚实的OP Stack 节点知道读取该事件,将其转换为实际的 EVM 交易,并在序列器关闭时插入到 L2 块中。
关键在于,每个 L2 交易都需要一个对应的 L1 交易。即使在最简单的情况下,这些 L1 交易也至少需要 10 万个 Gas 单位。
现在考虑由Rollup排序器发布的批量交易。批量处理功能使排序器能够将数百或数千个 L2 交易合并到单个 L1 交易中。例如,在这笔 L1 交易中, Base 发布了价值 384kb 的Rollup交易。一笔简单的转账交易大约 100 字节,一笔 DEX 交换交易接近 1kb,这意味着批量处理带来的容量增益至少是 100 比 1。
Base 为这 100 倍的容量提升支付了多少 L1 Gas?价格和单笔强制打包交易一样,因为现在由于拥堵情况良好,blob 基本上可以免费发布!
随着Rollup需求的增长,blobspace 的价格无疑会上涨,但它总是比 calldata 或合约交互便宜得多,因为它是Rollup数据可用性的预期载体。
如果序列器发生故障怎么办?
当排序器离线时,强制打包成为唯一的选择。没有了批量打包带来的效率提升,交易打包成本将成倍增加。用户别无选择,只能退出。
强制加入可能会导致大规模退出,但代价高昂。每位用户必须:
- 为在 L2 上发起提现的强制交易支付 10 万 L1 gas
- 再支付 200k+ L1 gas 来完成 L1。
成本会随着用户需要退出的资产数量以及发起提现所需的交易数量(例如,在提现之前先结清贷款)的增加而上升。最终,当所有人都试图同时提现时,L1 Gas 成本将飙升。
假设每个用户提取 L1 gas 需要 25 万,用户数量为 1000 万,gas 激增定价为 100 gwei, ETH价格为 4000 美元,那么我们退出的总成本为:
250k gas per user * 10M users * 100 gwei gas price / 1e18 * $4k ETH price = $1B USD
虽然成本巨大,但该模型仍然过于乐观,因为它假设所有有价值的资产都可以退出到 L1。对于已在 L1 上表示的桥接资产来说,这或许是正确的,但对于在Rollup上原生发行的资产,目前尚不清楚是否会围绕“等价”的 L1 资产形成社会共识。
最后,一旦所有费用都支付完毕,所有用户资产都安全地转移到 Layer-1 上,接下来该怎么办?用户无法继续留在 Layer-1 上,成本太高了!这就是他们最初使用Rollup的原因。但是,在经历了大规模退出造成的巨大价值损失之后,我们能指望他们重新存入另一个具有相同漏洞的Rollup吗?
要点很明确:为了使以太坊Rollup生态系统能够生存,rollup 必须通过使链能够在没有中心化测序仪的情况下运行来消除因测序仪故障而导致大规模退出的需要。
解决方案:实现Rollup经济学民主化
为了使Rollup能够在没有集中式排序器的情况下运行,我们必须让普通用户能够使用相同的经济工具,从而使集中式排序本身变得可行。
排序器拥有三个关键优势,可以实现Rollup经济学:
批处理:将多个 L2 交易合并为单个 L1 提交。这是 rollups 的根本效率提升。
Blob 访问:使用 Blob 存储代替合约事件发送。Blob 专为Rollup数据可用性而设计,并将始终是以太坊最高效的 DA 载体。然而,如果 calldata 更便宜,用户应该可以选择使用它,就像现在的Rollup序列器一样。
规模经济:根据以太坊协议规则,blob 的购买是“全有或全无”的——你不能只购买 10KB 的 blob 空间。中心化排序器需要积累足够的交易才能高效地使用 blob。而个人用户则无法做到这一点,因此我们需要一种排序方法,让用户能够共享 blob,从而避免为未使用的空间付费。
推出 Unstoppable Sequencing
不可阻挡的排序是一种分散式批处理的框架,当主排序器出现故障时,需要保留Rollup容量和审查阻力。
术语
- Sequencer :构建批量有序 L2 交易的实体。
- 批处理器 (Batcher) :将已构建的 L2 交易批次发布到 L1 的实体。排序器 (sequencer) 和批处理器可以是同一个实体,但预期的安排是让批处理器成为处理 blob 共享的专门角色。
- Rollup节点:使用 L1 历史记录确定性地得出Rollup状态的软件。“确定性”是指所有诚实的Rollup节点在给定相同的 L1 历史记录的情况下,都将得出相同的状态。
- Rollup共识客户端:从 Layer-1 数据中提取批次,并将交易和元数据列表发送到执行客户端以构建和执行区块的软件。示例:
op-node - Rollup执行客户端:执行区块并存储Rollup状态的软件。例如:
op-geth
这里我们假设Rollup将执行和共识分离,就像在OP Stack 和 L1 本身中一样,但这对于解释来说并不是必需的。
角色和权限
不可阻挡的排序并不需要消除需要许可/中心化的排序器。中心化的排序器可以提供高级服务(高可用性、预先确认,以及最终与其他 Rollup 的同步可组合性),这些服务需要保证区块空间和费用。
在 Unstoppable Sequencing 模型中,有两个排序器角色:
优先级排序器:每个 L1 区块最多只有一个优先级排序器。该排序器的批次始终位于 L2 区块的起始位置,并且保证该排序器占用 L2 区块空间的百分比,该百分比可通过 rollup 配置。
无需许可的排序器:其他所有人。它们的批次在二级区块中排在优先级排序器的批次之后,并且它们的区块空间无法保证——它们会使用优先级排序器未消耗的所有 Gas。
不可阻挡排序方法与如何选择优先级排序器以及保证多少百分比的 L2 区块气体无关。
一个“纯粹”的Rollup可能不需要优先级排序器。另一个 Rollup 可能有一个优先级排序器,但只保证 50% 的区块空间,使其与普通用户处于平等地位,等等。
设置这些参数没有“一刀切”的方法。Unstoppable Sequencing 确保在参数选择方面具有最大的弹性,而且至关重要的是,无论选择哪种参数,Unstoppable Sequencing 在优先级排序器缺失的情况下都能提供相同级别的保护。
在呼叫情况下,Batcher 的角色完全无需许可;任何人都可以发布由优先级排序器或无需许可的排序器创建的批次。
批处理格式(可在 L1 数据中的任何位置扫描)
在不可阻挡的排序中,批次是可以嵌入以太坊调用数据或 blob 有效负载中任何位置的字节字符串,并且可以通过单独扫描每个以太坊 L1 交易来发现,而无需通过(例如)特权发布地址进行过滤。
为什么如此自由?对符合条件的 DA 交易的限制限制了 blob 的可共享性。例如,如果两个 rollup 要求将消息发布给不同的接收者,则它们无法共享 blob。Unstoppable Sequencing 旨在最大限度地兼容所有批处理协议,并承担到处查找批处理的开销,以提高用户的效率。
不可停止的批次由 36 字节的标头和后跟 RLP 编码的交易(以及优先批次的 65 字节签名)组成:
[PROTOCOL_ID] [CHAIN_ID] [VERSION] [ROLE] [LENGTH] [RLP_TX_LIST] [SIG if ROLE=1]协议 ID (22 字节: 0x756e73746f707061626c652073657175656e63696e67 ):十六进制编码的字符串“unstoppable sequence”。此标识符使Rollup节点能够通过扫描这个“神奇”的字节字符串来检测位于 blob 或 calldata 中任何位置的批次。
链 ID (8 个字节):标识批次目标链。
版本(1 个字节):今天的版本 1。
角色(1 个字节):区分批次类型。0 表示无0 , 1表示优先级。
长度(4 个字节):指定后面跟着多少个字节的 RLP 交易数据。
RLP_TX_LIST :实际交易,编码为标准以太坊 RLP 列表。
签名(65 字节,仅用于优先级):ECDSA 签名,涵盖[CHAIN_ID][VERSION][ROLE][RLP_TX_LIST] 。这证明该批次来自优先级排序器。
部分区块(“区块碎片”)
Unstoppable Sequencing 将每个批次视为一个 L2 块的部分。同一 L1 块中的多个批次将合并为一个 L2 块,因此:
- 小参与者不需要独自填满整个街区,并且
- 我们避免了“完全无政府状态”的浪费工作,即只有一个完整区块提议者“获胜”。
费用如何计算?
直观地说,每个排序器都应该从其发布的批次交易中获得费用。对于优先级排序器来说,这是可能的,但对于无需许可的排序器则不行,因为 L1 区块提议者总是可以用自己批次的副本抢先执行排序器。
这种安排激励了 L1 区块提议者投入精力对Rollup进行排序,以便在优先级排序器发生灾难性故障时提供所需的吞吐量。但是,如果你不是L1 提议者,发布无需许可的批次的动机又是什么呢?
即使没有协议费用,无需许可的排序器仍然可能受到以下因素的激励:
- 与用户达成的私下交易/预付款安排
- 操作需要包含自己的交易的大型Rollup应用程序
- MEV 或交易排序带来的其他间接收益
该协议的最后一个选项和“未来功能”是让用户指定他们喜欢的排序器,该排序器将是唯一一个(除了他们自己之外)能够对他们的交易进行排序并收取费用的人。
从批次中确定性地获取 L2 状态
现在让我们端到端地看一下这个过程,从无需许可的测序器的角度开始,以确定性 L2 块的生成结束。
步骤 1:批量创建、提交和 Blob 共享
无权限排序器通过标准 RPC 调用( eth_sendRawTransaction )收集用户交易。当排序器收集到足够多的交易并发布后,它会:
- 将它们包装在 Unstoppable Sequencing 批处理格式中
- 使用viem 的 toBlobs方法对批次进行编码以实现 blob 兼容性(处理 BLS 字段模数约束)
此时,排序器已准备好将包含交易批次的 Blob 交易提交到 Layer-1。然而,如果这样做,它们将与大型中心化排序 Rollup 竞争相同的六个 Blob 插槽。这在经济上是不可行的,因此 Unstoppable Sequencing 在设计时就考虑到了 Blob 共享。
由于 blob 共享需要多个序列器之间的协调,因此将其作为单独的服务自然是有意义的。
我们与Spire合作,使用其DA Builder 产品开发了该协议的 blob 共享功能。我们相信他们的产品最为成熟,并将在 Facet Chain 上的 Unstoppable Sequencing 实现中使用它。然而,整体方案与提供商无关;任何兼容的聚合器都可以使用。
要使用像 Spire 这样的共享服务,用户需要将原本提交给 L1 的 Blob 交易发送到 Spire 的 RPC 端点。Spire 随后会解码该 Blob,将其数据与其他排序器的数据合并成一个新的 Blob,并将其提交给 L1。
Spire 甚至支持 Flashbots 的 RPC 方法,例如eth_sendBundle这样排序器就可以在收到单个用户交易后立即向 Spire 提交批次,并针对每个收到的新用户交易重新提交一个指向同一 L1 区块的新批次。这消除了各个排序器在最佳时机方面的负担。
注意:如果即使使用Blob 聚合服务,Blob 经济仍然不可行,则排序器始终可以将批次作为调用数据发布到 L1。
步骤 2:发现和验证(节点扫描所有内容)
对于每个 L1 区块,节点按顺序迭代每个 L1 交易并检查:
- 然后是交易的调用数据
- 每个 blob 都附加到该 tx(按 blob 索引升序排列)。
它扫描每个字节流以查找 Unstoppable PROTOCOL_ID ,并在匹配时解析固定长度的标头并验证:
-
CHAIN_ID与Rollup匹配, -
VERSION受支持, -
RLP_TXS解码正确 - 对于优先批次(
ROLE=1),SIG会根据特定于汇总的授权集进行验证 - 确保所有优先级批次中所有交易的 gas 限额总和不超过特定于汇总的保证 gas 分配。
格式错误或不匹配的批次将被忽略。有效批次将进入下一步。
步骤 3:聚合和排序
节点从 L1 块收集所有有效批次并使用以下排序键对其进行排序:
- 优先级?0:1
- L1 交易索引
- 呼叫数据中的字节偏移量
- 斑点索引
- blob 中的字节偏移量
也就是说,优先批次优先,并且如果事务在 calldata 和 blob 中都有批次,则所有 calldata 批次都会在 blob 批次之前。
每个批次都会被“解包”成其组成交易,保留其在批次中的顺序,并附加传统的单笔交易强制包含交易。总而言之:
- 所有优先批量交易
- 所有无需许可的批量交易
- 存款/传统强制交易
结果是 L2 交易的确定性有序列表,但Rollup执行客户端可能无法从该列表构建 L2 块,因为某些交易可能无效。
在以太坊中,交易“失败”分为两类:
失败的交易(区块有效) :当合约功能恢复或交易耗尽 gas 时,交易仍然可以包含在有效区块中。
无效交易(区块无效) :某些交易错误会导致整个区块无效,从而导致执行客户端拒绝该区块。例如:
- 账户资金不足以支付燃气费用
- 无效的随机数值
- 合约部署超出规模限制
在传统的单方区块创建中,The Block生产者可以在提交之前删除所有无效交易。然而,在“不可阻挡排序”系统中,当合并来自多方的批次时,这种方法并不可行。
步骤 4:执行和过滤
解决方案是从上一步中节点创建的 L2 交易的有序列表中“过滤掉”使区块无效的交易。
然而,识别无效交易并不是可以在Rollup共识客户端中“静态”完成的事情,因为交易的有效性可能取决于执行The Block中先前交易的结果。
因此,Unstoppable Sequencing 需要修改执行客户端才能启用此过滤功能。具体流程如下:
共识客户端在正常的
engine_forkchoiceUpdated调用中将交易发送到执行客户端。执行客户端开始使用这些交易构建 L2 块,按顺序一次执行一个。
当执行客户端遇到无效交易时,它不会因错误而停止进程,而是跳过该交易并转到列表中的下一个交易。
局限性和权衡
无需许可的测序器面临不确定性
优先级排序器具有可预测的排序顺序和有保证的 Gas 分配。无需许可的排序器不知道其最终的执行顺序。如果在无需许可的批次交易尝试购买 Gas 时,L2 区块已满,则这些交易将被过滤掉。
攻击者可以利用此机制,在某个无需许可的排序器之前提交多个批次,试图将其排除在The Block之外。然而,持续的垃圾邮件攻击将给攻击者带来巨大的成本,因为 Layer-2 的区块基础费用会随之增加。
如果一批交易的部分或全部未进入 L2 区块,那么从协议的角度来看,这些交易将会丢失。也就是说,如果排序器想要将这些交易打包到不同的 L2 区块中,他们必须通过新的交易将该批交易再次提交到 L1 区块。
一个更具成本效益但更复杂的“未来功能”是让Rollup节点维护一个已过滤交易的“内存池”,并自动将其包含在内,而无需在未来的 L2 区块上重新提交。
预先确认和同步可组合性
某些高级功能需要能够可靠地模拟交易结果:
- 预先确认:用户希望在 Layer 1 纳入之前获得交易执行的保证
- 同步可组合性:跨链调用需要确定性模拟
这些服务只能由发布第一批服务的人可靠地提供——当优先级排序器处于活动状态时,或者当优先级排序器不存在时,由 L1 提议者提供。
这就形成了一种自然的分工:优先级排序器提供优质服务和保障,而无需许可的批处理则确保链在任何条件下都具有抗审查性和可操作性。
垃圾邮件怎么办?
无权限系统容易滋生垃圾邮件。攻击者可以在多个区块中发布数千笔无效交易,迫使节点处理垃圾数据。Unstoppable Sequencing 能解决这个问题吗?
目前每个区块 6 个 blob 的限制意味着每 12 秒区块最多有 ~7,500 个垃圾交易,这对于当今的硬件来说是可以处理的。
随着 blobspace 的增长,这可能成为一个挑战,但解决这一挑战需要付出无需许可和弹性的代价。
结论
L2 建立在批处理的基础上。传统的强制包含机制会将交易还原为单个交易,从而破坏了这一模型,导致在排序器发生故障时无法维持正常运行。
Unstoppable Sequencing 通过使批处理无需权限即可解决这个问题——任何人都可以创建和发布批处理,并将其嵌入到 L1 数据的任何位置,并通过 Blob 共享分担成本。这种方法会带来额外的复杂性,但它确保了 L2 能够抵御审查、故障和攻击。只要有人可以在 L1 的某个位置发布批处理,链就能持续运行。




