预留区块空间让 OP Stack 链能为符合条件的交易在每个区块中预留可配置的份额,从而让对延迟敏感的交易在拥堵时获得可预测的包含。当预留需求较少时,未使用的空间会让给常规流量,因此不会浪费任何区块空间。
在区块空间需求激增时,对延迟敏感的交易原本只能受制于优先费市场:付够了就能进,付少了就得等。某些用例(例如基于质押的排序实验)需要可预测的包含,而不是尽力而为。
为什么需要预留区块空间?
它填补了基于质押的排序实验暴露出的一个缺口:符合条件的交易若超过预留上限,会被完全从当前区块中丢弃,即使区块的大部分空间对其开放。预留区块空间让剩余空间依然可用,而不是闲置浪费。
在 op-sepolia 上的基于质押的交易排序实验中,发送者可以质押 OP 以获得区块顶部的访问权,这证明了需求是真实的。但超出限制的合格交易直接被丢弃:它们只能进入下一个区块,而不是当前区块剩余的 80% 部分。当区块的 80% 对其不可用时,很难说这些交易具有高优先级。
预留区块空间如何工作?
每个区块被划分为两层。预留层位于顶部,可获得区块 gas 的 R%,仅对满足当前资格规则(eligibility rule)的交易开放。下面的通用层对所有交易开放,按优先费小费排序。R 是操作者调整预留区域大小的单一杠杆。

决定哪些交易有资格进入预留层的谓词(例如发送者已质押)是一个独立的可配置接口,下文会介绍。在达到上限时的行为取决于需求和一个开关——溢出(spillover):
| 情况 |
行为 |
| 预留需求低于上限 |
未使用的预留 gas 让给通用层。不会有区块空间浪费在空的特权区域上。 |
| 预留需求超过上限,溢出开启 |
超出交易仅凭优先费小费在通用层竞争。它们失去预留特权,但如果出价高于通用层竞争者,仍能进入区块。 |
| 预留需求超过上限,溢出关闭 |
超出交易等待下一个区块的预留层。 |
| 合格交易因剩余预留空间不足而无法容纳 |
如果溢出开启,该交易会溢出,其后较小的合格交易仍可能被容纳。与普通区块构建行为相同。 |
值得保留的特性是:无论预留需求落在何处,区块空间都保持最大可用性。低需求不会浪费区块空间,高需求也不会丢弃原本可以被包含的交易。
预留区块空间是一个功能还是一个框架?
它是一个框架。两层结构是固定的,但决定哪些交易有资格进入预留层的规则是一个可插拔的接口。新的用例可以接入其中,而无需改动区块构建路径。
目前内置两种资格规则:
- 基于质押: 如果发送者在指定合约中质押了 OP,则交易合格。这是支撑基于质押的排序实验的规则。
- 发送地址白名单: 一组预留发送者地址,可以扩展为限制目标地址和/或函数选择器。
区块构建机制不关心使用的是哪种规则。希望优先处理其他类型流量的链操作者可以定义新规则,并配置构建器使用该规则。复杂部分——双层排序、溢出管理、nonce 处理以及测试工具——都是一次构建、可复用的。
为什么预留区块空间构建起来很困难?
两个问题占据了大部分复杂性:溢出和测试。
为什么溢出很困难?
溢出困难是因为两层按不同标准排序(预留层按资格,通用层按小费),但内存池交给我们的是一条按优先级排序的单一流,并且我们在读取时它还在变化。

两个微妙之处让它变得棘手。第一,排序:内存池流不是静态的。我们在构建时新交易会到达,按优先级插入,而读取一笔交易会解锁同一发送者的下一个 nonce 交易。流从两个方向都在变化。第二,溢出:流是单次读取的,从头到尾读取,不能回退。当一笔合格交易超出预留上限时,我们不能简单地把它放回去等后续竞争。
解决方案是一个按小费排序的并行溢出队列。当一笔合格交易超出上限时,我们按小费重新排序并将其放入该队列。在构建通用层时,每一步我们比较内存池迭代器顶部和溢出队列顶部,取两者中更优的一个,同时处理 nonce 排序的边界情况,例如已包含交易的后续解锁交易。这保证了:如果你的符合预留资格的交易在不设预留区块空间时本可以进入区块,那么在开启预留区块空间后它仍然能进入,同时不破坏预留层内的资格排序。
为什么测试很困难?
测试困难是因为构建器是有状态且并发的:内存池流是实时的,交易在构建过程中到达,正确性由以微妙方式相互作用的排序不变性定义。确定性测试能捕获简单错误;有趣的问题只在真实负载下才会浮现。
我们用常规的确定性单元测试、集成测试和验收测试覆盖了核心逻辑。有意义的验证在实时开发网上进行:我们搭建了完整栈,资助账户以提交真实混合的预留合格交易和通用交易,并以每秒数百笔交易的随机流量来饱和区块。我们手动并以编程方式检查生成的区块,以验证排序不变性是否成立。
一个微妙之处:有些不变性看似被违反,实则没有。一笔在构建过程中进入内存池的交易,相对于构建开始前的静态快照,可能合法地出现在看起来失序的位置。验证逻辑必须考虑实时流,而不仅仅是构建前的状态,否则会将正确行为标记为错误。
预留区块空间在拥堵下表现如何?
在持续拥堵下,合格交易获得可预测的包含(p99 约 1.6 秒),而非合格交易则超过 10 秒。预留区块空间用一条可预测的通道取代了小费市场的争夺,满足需要这种通道的流量。

设置:我们使用 Contender 在私有测试网上以 20 个发送者、每秒 300 笔交易的速度进行洪泛,足以饱和区块空间。每笔交易使用约 20 万 gas,与典型 OPM 交易的中位 gas 用量相匹配。我们开启了预留区块空间(R = 20,基于质押的资格),只有一个发送者符合条件。Flashblocks 以 250 毫秒间隔启用,每个区块目标 gas 为 6000 万,选择该值是为了持续填充区块空间并引发持续拥堵。
|
p50 |
p95 |
p99 |
| 合格 |
733ms |
1,629ms |
1,634ms |
| 非合格(平均) |
6,364ms |
9,609ms |
10,355ms |
拥堵下的延迟。
预留区块空间的现状如何?
预留区块空间已随基于质押的排序实验在 OP 主网上线。 我们将观察其在真实流量下的表现,并在此基础上迭代实现和资格规则。
常见问题
什么是预留区块空间?
预留区块空间是一个区块构建框架,它可为满足资格规则的交易在每个区块中预留最多可配置的 R% 空间,使其在拥堵时获得可预测的包含,同时将任何未使用的空间让给正常流量。
预留区块空间面向谁?
它面向需要可预测包含而非尽力而为的对延迟敏感的用例,例如基于质押的排序实验,其中发送者质押 OP 以获得区块顶部访问权。
未使用的预留空间会发生什么?
当预留需求低于上限时,未使用的 gas 会让给通用层,因此不会有区块空间浪费在空的特权区域上。
什么是溢出?
溢出是一个可配置的开关。开启时,超出预留上限的合格交易凭借优先费小费在通用层竞争。关闭时,它们等待下一个区块的预留层。
预留区块空间会浪费容量吗?
不会。低预留需求不会浪费区块空间,高需求也不会丢弃本可以被包含的交易,因此区块空间保持最大可用性。
预留区块空间已经上线了吗?
是的。它已随基于质押的排序实验在 OP 主网上线,实现和资格规则将根据真实流量进行迭代。
术语表
- 预留层: 区块的顶部部分,最多占 gas 的
R%,仅对满足当前资格规则的交易开放。
- 通用层: 区块的其余部分,对所有交易开放,按优先费小费排序。
- 资格规则(谓词): 决定哪些交易有资格进入预留层的可插拔条件,例如发送者已质押或发送地址在白名单中。
- 溢出: 一个开关,决定超出上限的合格交易是按小费在通用层竞争(开启)还是等待下一个区块(关闭)。
R: 操作者设置的一个杠杆,用于将预留区域大小定为区块 gas 的百分比。
原文链接:optimism.io/blog/reserved-blockspace
本文技术内容由云栈社区整理编译,欢迎交流更多分布式架构设计。