引言
我们提出了一套用于安全集成替代数据可用性(AltDA)方案的技术框架与形式化定义。当前许多 AltDA 协议在系统设计中对此环节缺乏明确规范,导致 L2 链容易遭受安全性(safety)和活性(liveness)方面的故障。我们的目标是提供一个广泛适用于以太坊 L2 生态的框架,使得 AltDA 能够在对现有架构几乎无需修改或仅需极小改动的前提下实现安全集成。
本框架建立在 L2Beat 文章《Alt-DA L2 与数据可用性验证器的安全集成》(Secure Integration of Alt-DA L2s with Data Availability Verifiers)所提出的核心前提之上:任何安全的集成方案都必须假设排序器(sequencer)可能表现出恶意行为。虽然 L2Beat 的文章概述了高层级的要求和攻击场景,但我们的方法通过引入明确的领域定义和全函数(total functions),对这些思想进行了形式化。这为指定集成需求以及将这些需求组合成完整的验证流程提供了更精确的手段。
从高层视角看,我们将 AltDA 集成视为在三个数据结构之间进行的一系列确定性数据转换。每一步转换都必须是确定性的、明确定义的,并且对所有可能的输入均保持正确。
背景
从宏观角度看,一个以太坊 Rollup 系统包含以下组件:
L1 收件箱(L1 inbox):接收由 L2 排序器提交的数据可用性承诺(DA commitment)。每个 DA 承诺包含足够信息,可从数据可用性(DA)网络中唯一检索出对应的 blob。L1 收件箱中 DA 承诺的顺序定义了 L2 共识的规范账本(canonical ledger)。
数据可用性(DA):存储 blobs,并保证在指定时间段内可被检索。每个 blob 都有一个对应的 DA 承诺,该承诺与 blob 绑定,使得找到另一个映射到相同 DA 承诺的 blob 在计算上不可行。
L2 共识层:包含派生逻辑(derivation logic),用于消费 DA 承诺并从 blobs 中生成 Rollup 载荷(rollup payload)。Rollup 载荷是 L2 共识原生的数据结构,而 blob 则是 DA 网络原生的数据结构。
我们使用 sequencer(排序器)指代向 L1 提交 AltDA 承诺并向 DA 网络提交 blobs 的实体;使用 proposer(提议者)指代在以太坊上发布 L2 状态根的实体。为了实现安全集成,L2 的 proposer 和 sequencer 都不应被信任以保障 L2 共识的安全性与活性。
在接下来的部分中,我们将展示:若某些约束条件未被满足,将如何破坏安全性或活性。
安全性故障通常会导致 L2 分叉:既可能发生在链下共识节点之间,也可能发生在以太坊上的 L2 轻客户端之间——而这些轻客户端最终负责保护锁定在 L1 桥中的资金。
活性故障则会导致 L2 链停滞,阻止用户提款或进行其他操作。在某些情况下,活性故障甚至会为跨链桥盗窃创造条件。

L2 node deriving rollup payload from AltDA Commitment
AltDA 安全集成作为数据转换
L2 共识按顺序处理 DA 承诺。对于每个承诺,它从 DA 网络中获取对应的 blob,并将其解码为 Rollup 载荷(rollup payload)。我们定义如下关键概念:
AltDA 承诺(AltDA Commitment):提交至 L1 的字节数组。与以太坊原生的版本化 KZG 承诺不同,AltDA 承诺可能包含基于其他曲线的 Merkle 承诺或 KZG 承诺。此外,AltDA 承诺还可包含额外元数据,例如 DA 运营方的证明(attestations),用以表明该 blob 已被成功存储。
Blob:存储在 AltDA 网络中的二进制数据结构,其承诺出现在 AltDA 承诺中。
Rollup 载荷(Rollup Payload):可从 blob 派生出的、L2 原生的数据结构。
为便于分析,我们首先假设排序器(sequencer)是诚实的——即始终向 L1 提交有效的 AltDA 承诺,并在 DA 网络中存储格式正确的 blobs。这一假设简化了讨论,使我们能聚焦于恶意提议者(proposer)和恶意 blob 提供者所发起的攻击。在此前提下,以下两个约束可确保攻击者无法在 L2 节点之间(无论是链下还是链上)引发分叉:
如果底层的承诺方案(Merkle 或 KZG)存在漏洞或实现不当,攻击者可能构造出第二原像(second preimage)。
换句话说,给定一个数据承诺 ( g = H(X) )(其中 ( X ) 是原始数据),恶意 blob 提供者可能找到另一个不同的数据 ( Y \neq X ),使得 ( g = H(Y) )。通过向不同的 L2 节点分发不同的有效 blob,攻击者即可诱导出 L2 分叉。
更严重的是,恶意提议者可以向以太坊上的 L2 轻客户端出示任意一个 blob,并令人信服地证明其有效性,从而在 L1 层面制造 L2 分叉。
因此,DA 网络必须使用具有绑定性(binding),并且每个 L2 节点都必须验证其所检索到的 blob 是否确实与 AltDA 承诺中包含的承诺相匹配。
解码过程必须是确定性的:任意两个诚实节点在接收到相同的 blob 时,必须始终派生出完全相同的 Rollup 载荷。
设想一种有缺陷的集成方案:L2 节点跳过承诺验证和解码步骤,直接信任某个第三方提供的 Rollup 载荷。这种做法会重新引入 L2 分叉风险——原因与前述例子相同:Rollup 载荷、blob 和 AltDA 承诺之间缺乏强制性的关联。没有这种关联,诚实的挑战者就无法提供可靠证据来证明哪个载荷才是合法的。
要使系统真正安全,我们必须假设排序器可能表现出任意恶意行为。恶意排序器可以:
向 L1 收件箱提交损坏的数据;
在存储对应 blob 之前,错误地编码 Rollup 载荷。
若缺乏恰当的 AltDA 集成机制,排序器便可利用上述行为,向派生流程注入未定义或无效的输入,从而导致 L2 链停滞。这类攻击大多造成活性故障(liveness failures),但在某些情况下,还可能升级为更严重的攻击——例如数据扣留攻击(data withholding attack)——进而耗尽 L1 跨链桥中的资金。

Unlike last diagram malicious sequencer can put anything in L1 inbox, the red arrow represents discarding of the corrupted data
将字节反序列化为 AltDA 承诺
当排序器(sequencer)不可信时,L1 收件箱中的条目可能包含任意字节串。第一步是检查这些字节是否能被反序列化为一个有效的 AltDA 承诺。如果反序列化失败,则必须丢弃这些字节,共识流程继续处理收件箱中的下一项。
然而,仅靠反序列化是不够的。恶意排序器可以构造一个语法上有效(例如通过填入随机值)但语义上伪造的 AltDA 承诺。因此,还需要额外的验证机制来识别此类承诺。
数据可用性验证器(DAV)用于验证某个 AltDA 承诺是否对应于 DA 网络中已存储的 blob。L2Beat 的文章强调了它在防范数据扣留攻击(Data Withholding Attack)中的关键作用。在此,我们将其形式化纳入数据转换框架中。
假设从 L1 收件箱中取出一段任意字节 ( X ),其可能取值空间为 ( {0,1}^{1048576} )(假设最大交易大小为 128 KiB;尽管理论上交易可能更大,因为协议限制的是 gas 而非字节数)。
其中,只有部分字节能被成功反序列化为有效的 AltDA 承诺数据结构,我们将这一子集记为 ( S )。
DAV 是定义在集合 ( S ) 上的一个函数:若对应的 blob 已被 DA 网络存储,则返回 1;否则返回 0。这将 ( S ) 划分为两个子集:( D )(DAV 返回 1)和 ( D' )(DAV 返回 0)。

不同 AltDA 网络采用不同的承诺格式和验证逻辑,但所有实现均可从全函数性(totality)和正确性(correctness)两个维度进行刻画:
全函数实现(Total):对 ( S ) 中所有输入都能产生输出。
偏函数实现(Partial):对某些输入无法求值。例如,若 DAV 仅对 ( D ) 中的输入进行处理,而恶意排序器提交了 ( q \in D' ),则 DAV 会遇到未定义情况,可能导致 L2 共识停滞,从而冻结所有资金。
不正确的 DAV:对 AltDA 承诺进行错误分类。
若对未存储 blob 的承诺返回 1,则会导致数据扣留攻击。
若对已存储 blob 的承诺返回 0,则构成一种较弱的活性攻击(liveness attack)。虽然该排序器的数据会被忽略,但大多数 Rollup 设计允许用户通过强制包含(force-inclusion)机制退出,因此 L2 共识不会完全停滞。
要使轻客户端(light client)能在不引入攻击面的前提下断言 L2 状态,必须使用全函数且正确的 DAV 实现。
如果 DAV 原生部署在以太坊上,轻客户端可直接调用合约;
否则,轻客户端必须依赖密码学证明(如 ZK 证明或交互式挑战)来确认 DAV 被正确执行。
注意:停机类故障(halting failures)可能导致依赖挑战游戏(challenge games)的 Rollup 损失 L1 资金。例如:
数据扣留攻击是一种停机故障,会阻止诚实挑战者获取数据以赢得挑战;
若挑战游戏要求提交有效的状态转换,而 L2 共识因停机无法派生正确状态,挑战者也可能因此输掉挑战。
即使某个 AltDA 承诺通过了 DAV 验证,仍可能因时效性/时序攻击(Recency / Timing Attack)而不可用:排序器可能故意延迟提交 AltDA 承诺,直到 DA 网络已将对应的 blob 清理(prune)。
为此,需引入时效性检查——这是一个函数,仅当承诺足够“新”(即在 blob 保留期内提交)时才返回 1。该检查进一步划分集合 ( D ),并可自然地与其他验证步骤组合。由于 AltDA 承诺只有在所有检查均通过时才被接受,因此各检查的执行顺序无关紧要。
在确认 AltDA 承诺对应一个可用 blob 后,下一步是从 DA 网络检索该 blob,并将其解码为 Rollup 载荷。
Rollup 载荷是一个抽象概念,指 Rollup 栈原生的数据结构。任何载荷中的数据损坏都应由 Rollup 栈自身处理。例如,在原生以太坊 DA 中,恶意排序器可在 blob 中填入乱码,但 Rollup 栈能检测并丢弃无效载荷。因此,我们可聚焦于 Rollup 载荷与 blob 之间的编码/解码过程。
对于 Merkle 承诺:blob 由一系列 Merkle 叶子节点组成,每个叶子包含 2 的幂次字节数。由于 Merkle 树中可能包含其他无关叶子,因此需要元数据说明哪些叶子属于该 blob 以及数量。
编码时,将 Rollup 载荷切分为若干叶子。
对于 KZG 承诺:blob 由域元素(field elements)构成,每个域元素是固定小尺寸单元(约 254 位)。以太坊固定使用 4096 个单元,但 AltDA 系统可支持变长,并需在元数据中明确指定实际长度。
Rollup 载荷通常无法自然对齐域元素边界,因此需填充(padding)以转换为合法的域元素列表。
无论采用何种承诺方案,Rollup 载荷的大小几乎总不能整除基本数据单元(无论是 Merkle 叶子还是域元素)。因此,编码前必须进行填充;而为在解码时正确移除填充,原始载荷长度必须作为元数据传递——该元数据可内嵌于 blob 内容中,或包含在 AltDA 承诺中。
正如恶意排序器可向 L1 收件箱提交无意义数据,它也可基于有效 Rollup 载荷构造 blob,但在编码过程中引入错误。例如:
在元数据中声称载荷比实际 blob 更大;
修改控制数据布局或解码算法的版本字节。
上述任一情况都可能导致解码失败。
当 blob 无法被解码时,任何 L2 共识的 AltDA 集成方案都必须直接跳过该 blob。否则,L2 共识可能停滞甚至崩溃。
与完整 L2 共识节点不同,轻客户端无法下载或执行上述所有昂贵的验证步骤。但只要数据转换流程被明确定义,轻客户端便可依赖交互式挑战游戏或零知识证明,来确保所声明的 L2 状态已通过所有必要检查。
正如 L2Beat 文章所强调的,集成 AltDA 的 L2 链的派生逻辑可以被极其精确地规范。本文提出了一种通用框架,将 AltDA 集成视为一系列数据转换步骤。这一视角有助于厘清安全集成所必需的核心验证环节,并易于扩展以支持新需求。该框架适用于所有通过 L1 收件箱处理 DA 承诺的 L2 架构。

EigenLabs 提供了一个安全的 OP Stack 集成方案,完整实现了本框架所述的所有组件。其核心库 hokulea 和 eigenda-proxy 已分别由 Veridise 和 SigmaPrime 审计,遵循本文所述原则。如需了解符合此框架的完整端到端架构,请参阅 EigenDA 集成规范。
原文:https://ethresear.ch/t/framework-for-altda-secure-integration-on-ethereum/23591
免责声明:本文为c2e Labs的第三方内容,仅供信息分享与传播之目的,不代表我们的立场或观点且不构成任何投资及应用建议。版权归原作者或来源方所有,如内容或素材有所争议请和我们取得联系。