导语:把区块链拆成可以单独替换的零件
比特币和以太坊早期都是单体链(monolithic blockchain):一个节点同时负责执行交易、达成共识、保存状态、广播数据。这带来极简的安全模型,也带来了难以调和的扩容矛盾——想让吞吐翻十倍,就得让每个全节点多下载十倍数据、多验证十倍计算。模块化(modular)的思路是把这个整体拆成四层:执行(Execution)、结算(Settlement)、共识(Consensus)、数据可用性(Data Availability,DA),每层独立演进、独立扩容,彼此通过明确的接口连接。Rollup 就是最早的模块化实践:执行搬到链下,结算与共识留在以太坊。而拆层之后,最先撞到天花板的不是执行,而是数据可用性——如果没人能拿到交易数据,执行再快也无法验证状态,桥也无法安全提款。
一句话总结:模块化的价值在于把「不可能三角」拆成三个各自独立的三角;而 DA 层是模块化架构的信任基石,它决定了 Rollup 的安全下限到底由谁承担。
1. 从单体链到模块化:四层解耦
1.1 单体链的困境
单体链把四件事绑在一台机器上。它的优势非常明确:原子性。一笔交易从执行到最终确认只涉及一条链,不需要跨系统通信,不需要额外的信任假设。这也是为什么比特币与以太坊的安全模型如此干净——你运行一个全节点,就独立验证了一切。代价同样明确:
- 执行扩容受限于最慢的全节点。要提高 TPS 只能提高区块 gas 上限,而 gas 上限越高,全节点的状态与带宽压力越大。
- 无法局部优化。共识层想换一个更快的 BFT 算法,会牵动执行层的最终性语义;DA 想用纠删码降低存储,又会被共识层的区块传播逻辑限制。
- 同质化竞争。所有单体链都在做同一件事:把通用计算塞进一个全局状态机,然后在「更去中心化」与「更快」之间反复取舍。
1.2 执行、结算、共识、数据可用性四层
模块化把职责切开,每层只回答一个问题:
| 层次 | 回答的问题 | 典型实现 |
|---|---|---|
| 执行层 | 交易如何改变状态 | EVM、zkVM、SVM、Move VM |
| 结算层 | 状态承诺的最终性与争议裁决 | 以太坊 L1、Rollup 结算合约、Sovereign Rollup 自结算 |
| 共识层 | 交易顺序由谁决定 | Tendermint、以太坊 PoS、Celestia 的 CometBFT |
| 数据可用性层 | 数据是否发布且人人可取 | calldata、EIP-4844 blob、Celestia、EigenDA、Avail |
关键在于接口而非实现。结算层只需要一个「状态根 + 数据承诺」的输入,至于这个状态根来自 EVM 还是 zkVM,来自单一排序器还是去中心化排序网络,结算层并不关心。
1.3 单体与模块化的对比
单体链(Monolithic):共识 + 执行 + 结算 + DA 全在一个节点
优点:原子性、简单、安全假设少
缺点:扩容只能靠堆硬件,无法局部替换
模块化(Modular):
执行层 A ┐
执行层 B ┼─ 状态根 + 数据承诺 ─▶ 结算层(争议裁决 / 有效性证明验证)
执行层 C ┘ │ 区块 + 数据承诺
▼
共识层 + DA 层(排序 + 发布 + 可采样)
优点:各层独立扩容、可替换、可组合
缺点:跨层信任假设、DA 成为新瓶颈、故障域变多
一句话总结:单体链用「一台机器做所有事」换取最简信任模型;模块化用「多套系统协作」换取可扩展性——代价是每一层的接口都变成新的攻击面。
2. 数据可用性:模块化架构的真正瓶颈
2.1 DA 到底承诺了什么
数据可用性包含两个不可分割的部分:
- 数据发布(Data Publishing):交易数据确实被写进了某个共识系统,且任何人都能读到。
- 数据可检索(Data Retrieval):在足够长的时间窗口内,任何诚实的参与者都能完整下载这些数据。
只满足第一条是不够的。如果排序器把数据的哈希发到链上,但把原始数据藏在自己手里,那么状态根无法被任何人独立重算、欺诈证明无法被构造、用户无法从 Rollup 合约中自行提取资金。这就是数据可用性问题,也是模块化架构中最隐蔽的风险:链上一切看起来正常,区块在出,哈希在更新,但数据已经丢失。
2.2 数据可用性攻击
一个典型的 DA 攻击流程:
1. 恶意排序器打包一批交易,计算出正确的状态根 R
2. 把状态根 R 提交到 L1 结算合约,但数据只发给少数共谋节点
3. 其他验证者看到 R 是合法的(哈希正确、签名正确)
4. 但没有人能重算 R,因为拿不到输入数据
后果:
- 用户无法证明自己的余额(无法构造提款证明)
- Optimistic Rollup 的挑战者无法构造欺诈证明
- 数据在共识层「名义存在」,但事实上不可得
注意攻击的关键:数据缺失在链上是不可见的。L1 合约只能看到「某个承诺被提交了」,它无法判断这个承诺背后的数据是否真的可达。这正是为什么需要 DA 层,也是为什么 DA 层必须提供可验证的可用性证明,而不是仅仅提供一个存储服务。
三类 DA 方案的光谱:按信任假设从强到弱排列:
| 方案 | 可用性由谁保证 | 信任假设 | 成本量级 |
|---|---|---|---|
| 链上 calldata | 以太坊全节点 | 无需额外假设 | 最高 |
| EIP-4844 blob | 以太坊共识层(约 18 天保留) | 无需额外假设,但有时间窗 | 低 |
| 数据可用性委员会 DAC | 委员会多数诚实 | 需要信任 N 个节点 | 极低 |
| DA 层(Celestia/EigenDA/Avail) | 密码学采样 + 轻节点 | 采样安全性 + 少数诚实节点 | 低 |
DAC(Data Availability Committee)是最便宜也最脆弱的方案:它把「数据是否发布」变成了「委员会是否诚实」的人为判断。相比之下,Celestia 这类 DA 层试图用纠删码 + 采样把这个判断变成数学问题。
一句话总结:DA 层的核心任务是把「数据是否真的发布了」这个链上不可见的问题,转化为一个可以被轻节点用极少带宽概率验证的问题——这就是纠删码与数据可用性采样的全部意义。
3. Celestia:Reed-Solomon 编码与数据可用性采样
3.1 Celestia 的定位
Celestia 是一条只做共识与数据可用性的链:它不执行智能合约,不维护通用状态,只负责把交易按字节排序、发布,并让轻节点能够以极低成本验证「数据确实发布了」。执行交给 Rollup,结算可以由 Rollup 自己在以太坊上完成。这种极简定位让它能做一件单体链做不到的事:让区块大小随轻节点数量而不是全节点数量扩展——因为轻节点只需要下载极少量的随机采样,不需要下载整个区块。
3.2 1D Reed-Solomon 编码
Reed-Solomon(RS)是一种纠删码:把 k 个原始数据分片编码成 n 个分片(n > k),只要拿到其中任意 k 个就能还原原始数据。
1D Reed-Solomon 编码(扩展因子 2),原始数据 k = 4:
把数据看作多项式 f(x) 在 x=0..3 处的取值:
f(0)=d0, f(1)=d1, f(2)=d2, f(3)=d3
在额外的 x=4..7 处求值,得到校验分片:
扩展后 [d0, d1, d2, d3, p0, p1, p2, p3] n = 8
性质:
- 任意 4 个分片即可还原全部 8 个(含原始 4 个)
- 需要隐藏超过 4 个分片,才能阻止还原
- 冗余率 = n / k = 2,存储放大 2 倍
RS 编码的数学基础是有限域上的多项式插值:k 个点唯一确定一个次数 < k 的多项式,而任意 k 个点都能插值还原它。这是所有纠删码方案(包括 EigenDA、Avail、Celestia)的共同基石。
3.3 2D Reed-Solomon 与数据方块
一维编码有一个致命弱点:攻击者只需要隐藏 k 个特定分片(例如后半段)就能阻止还原,而采样节点如果恰好只采样到前半段,就无法察觉。二维编码解决了这个问题。
2D Reed-Solomon(扩展因子 2,k=4 示例)
步骤 1:原始数据排列成 k×k 方块
d00 d01 d02 d03
d10 d11 d12 d13
d20 d21 d22 d23
d30 d31 d32 d33
步骤 2:对每一行做 RS 扩展(横向补 4 列 r)
步骤 3:对每一列做 RS 扩展(纵向补 4 行)
得到 2k×2k = 8×8 的扩展方块(右下角由行列共同决定)
关键性质:
只要扩展方块中有 1/4 以上的分片可用,
就能通过行列插值还原出整个方块。
这个「1/4 阈值」是整个 DAS 安全性论证的支点。攻击者想要阻止数据还原,必须隐藏超过 3/4 的扩展方块——而这会让任何随机采样以 3/4 的概率命中缺失分片。
3.4 数据可用性采样 DAS
DAS(Data Availability Sampling)让轻节点用 O(1) 的带宽获得 O(n) 级别的安全性保证:
轻节点(Light Node)的采样流程:
1. 从网络获取区块头,读取数据方块的根承诺(data root)
2. 随机挑选 s 个 (行, 列) 坐标
3. 对每个坐标,向网络请求该分片
- 若拿到分片,用 Merkle/NMT 证明校验它确实属于该根
- 若在超时时间内拿不到,立即判定「数据不可用」,拒绝该区块
4. 若 s 个分片全部成功获取,则接受该区块
5. 采样结果通过 gossip 网络广播给其他轻节点
带宽成本:
每个分片约 512 字节,s = 15 → 单次采样约 7.5 KB
对比:下载整个 1 MB 的区块,成本高两个数量级
关键点在于轻节点不做任何全局判断:它只知道自己采样的那几个分片是否可得,然后把「我拿到了」这个事实广播出去。全网的轻节点各自独立随机采样,只要有一个轻节点采样失败并广播,网络就会拒绝这个区块。
3.5 采样安全性论证
把上面的直觉写成概率:
假设攻击者隐藏了扩展方块中比例为 h 的分片。
若要阻止数据还原(1/4 阈值),必须 h > 3/4。
因此每个随机采样「命中缺失分片」的概率 p ≥ 3/4。
单个轻节点采样 s 次全部命中可用分片(被欺骗)的概率:
P(被欺骗) ≤ (1 - p)^s ≤ (1/4)^s
采样次数 s 与安全级别:
s = 10 → (1/4)^10 ≈ 2^-20 ≈ 百万分之一
s = 15 → (1/4)^15 ≈ 2^-30 ≈ 十亿分之一
s = 20 → (1/4)^20 ≈ 2^-40 ≈ 万亿分之一
网络级安全:只要全网有 N 个诚实轻节点独立采样,
攻击者要欺骗全网络的概率 ≤ (1/4)^(s·N)(独立采样假设下)
这套论证有两个必须强调的假设:网络同步假设——轻节点必须在超时窗口内完成采样,如果网络分区或对手能阻断特定轻节点的连接,采样会退化为「无法判断」,Celestia 的策略是无法判断时拒绝区块(fail-closed),这保证了安全性但会牺牲活性;以及诚实轻节点数量——DAS 的安全性依赖「至少存在一个诚实轻节点在执行采样并广播失败结果」,如果全网只有攻击者自己的节点在采样,安全性论证就失效了。
一句话总结:DAS 把「数据是否可用」这个全局问题,转化成「随机采样是否命中」这个局部问题——(1/4)^s 的概率下界让 7.5 KB 的带宽换来数十亿分之一的安全级别,代价是引入了网络同步与诚实节点存在性两个新假设。
4. EigenDA:KZG 承诺、纠删码与再质押安全
4.1 从 EigenLayer 说起
EigenLayer 的核心创新是再质押(Restaking):让已经质押在以太坊上的 ETH(或其流动性质押代币)再次被用于为其他协议提供经济安全。这些协议被称为 AVS(Actively Validated Services),EigenDA 就是 EigenLayer 生态中最重要的 AVS 之一。这带来一个与 Celestia 截然不同的安全模型:Celestia 是独立的一条链,有自己的验证者集合与代币,安全性来自自身共识;而 EigenDA 没有自己的链,安全性租用自以太坊的质押 ETH——作恶会被罚没(slashing)真实的 ETH。
4.2 EigenDA 的数据流
Rollup 排序器
│ (1) 提交 blob(最大 16 MB)
▼
Disperser(分发器)
│ (2) 纠删码编码:把 blob 切分并 RS 扩展
│ (3) 为每个分片生成 KZG 承诺 / 证明
├──(4) 把分片分发给 EigenLayer 运营商(Operators)
│ 每个运营商只存储自己负责的那部分分片
├──(5) 把 blob 头(KZG 承诺 + 长度 + 编码率)发布到链上
▼
验证者 / 任意节点
(6) 向运营商请求分片,用 KZG 证明验证分片与承诺一致
(7) 若运营商签名不足或分片不可得 → 判定 DA 失败
与 Celestia 的对比是本质性的:Celestia 的轻节点采样,EigenDA 的验证者向运营商请求并验证承诺。前者靠概率,后者靠密码学 + 经济质押。
4.3 KZG 承诺如何让分片可验证
KZG(Kate-Zaverucha-Goldberg)承诺是一个多项式承诺方案:它允许承诺者把多项式 f 压缩成一个 48 字节的承诺 C,然后对任意点 z 给出一个简短的证明 π,证明「f(z) = y」。
在 EigenDA 中,这个性质被用来证明编码的正确性:
EigenDA 的 KZG 用法:
1. Disperser 把 blob 数据解释为多项式 f 的系数
2. 计算承诺 C = commit(f),发布到链上(48 字节)
3. 对第 i 个分片,Disperser 计算:
证明 π_i = prove(f, x_i) // 证明 f(x_i) = chunk_i
4. 运营商只存储 (chunk_i, π_i),不存储整个 blob
5. 任意验证者拿到 (chunk_i, π_i) 后:
verify(C, x_i, chunk_i, π_i) → true/false
效果:
- 验证者不需要下载整个 blob 就能验证分片是否属于承诺
- Disperser 无法「承诺 A 却分发 B」——KZG 的绑定性阻止了这一点
- 分片验证是 O(1) 的常数时间操作
// EigenDA 风格的 KZG 分片验证(伪代码,示意验证流程)
package da
import (
"fmt"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
)
// Chunk 是运营商持有的数据分片及其 KZG 证明
type Chunk struct {
Index uint64 // 分片在编码矩阵中的位置
Data []byte // 分片数据
Proof kzg4844.Proof // KZG 求值证明(48 字节)
}
// VerifyChunk 验证分片确实属于某个 blob 承诺
// 这是验证者对抗「承诺与分发不一致」的核心检查
func VerifyChunk(commitment kzg4844.Commitment, c Chunk) error {
// 把分片数据映射到有限域上的求值点 y = f(x_index)
point := kzg4844.Point(domainPoint(c.Index))
var value kzg4844.Scalar
copy(value[:], c.Data[:32])
// KZG 求值验证:e(C - y*G1, G2) == e(π, x*G2 - H)
// 一次 pairing 检查即可完成,无需下载整个 blob
ok, err := kzg4844.VerifyProof(commitment, point, value, c.Proof)
if err != nil {
return fmt.Errorf("kzg verify error: %w", err)
}
if !ok {
return fmt.Errorf("chunk %d 不属于该承诺,Disperser 存在欺诈", c.Index)
}
return nil
}
// VerifySampled 抽查一部分分片而非全量下载,与采样安全性同构
func VerifySampled(commitment kzg4844.Commitment, chunks []Chunk, n int) error {
if n > len(chunks) {
n = len(chunks)
}
// 注意:生产实现须使用密码学安全的随机源
for _, c := range sampleRandom(chunks, n) {
if err := VerifyChunk(commitment, c); err != nil {
return err
}
}
return nil
}
EigenDA 的安全边界:EigenDA 的信任假设与 Celestia 完全不同,理解这一点比记住参数更重要:分片可验证不等于数据可用——KZG 只能保证运营商拿到的分片与承诺一致,不能保证运营商真的保存了分片,可用性最终由「运营商签名集合的质押规模」保证,如果持有 2/3 以上质押的运营商串谋隐藏数据,DA 就失效了;罚没是事后惩罚——EigenLayer 的 slashing 需要经过争议期与治理流程,不是即时生效,攻击者在罚没生效前有一个时间窗口;安全成本随质押量线性增长——要让 EigenDA 的安全级别接近以太坊 L1,需要租用接近 L1 规模的质押,成本是持续性的。
一句话总结:Celestia 用纠删码 + 采样把可用性变成概率问题,EigenDA 用 KZG + 再质押把它变成经济问题——前者假设「至少一个诚实轻节点在采样」,后者假设「多数质押不会串谋」。
5. Avail:有效性证明与轻客户端
5.1 Avail 的架构
Avail 是另一条独立的 DA 链,定位与 Celestia 接近(只做共识与 DA),但在两个地方做了不同的工程选择:使用 KZG 承诺而非 Merkle 根作为数据承诺,从而可以用有效性证明(validity proof)替代欺诈证明来保证编码正确性;同时提供面向应用链的 DA 抽象,强调「应用链只需要把数据交给 Avail,Avail 保证数据可得且有序」。
5.2 有效性证明与 KZG 承诺
在 Celestia 的 2D RS 设计中,如果某个恶意区块生产者提交了一个没有正确做 RS 编码的数据方块(例如直接把随机数据当作校验分片),轻节点在采样时无法立刻识别——因为采样只能判断「分片是否可得」,不能判断「分片是否是正确的编码结果」。传统上这需要编码欺诈证明:有人下载整行数据,验证其不满足 RS 约束,然后提交证明。
Avail 用 KZG 把这个过程变成了主动的有效性证明:
Avail 的编码有效性保证:
区块生产者提交数据时,必须同时提交:
1. 扩展后数据方块的 KZG 承诺 C
2. 对每个分片位置 i 的 KZG 求值证明 π_i
验证者 / 轻客户端可以:
- 对任意分片做 O(1) 的承诺验证,确认它是 C 所定义的编码的一部分
- KZG 承诺绑定了一个低次多项式,而 RS 编码正是
「在更多点上求值同一个低次多项式」,
于是承诺本身就把编码正确性编码进了密码学假设
效果:不需要下载整行、不需要欺诈证明窗口,
编码正确性在分片层面即可验证
注意这里的关键洞察:RS 编码 = 同一个多项式在更多点上求值。因此只要承诺的多项式次数足够低(次数 < k),那么它在任意点的求值必然是「正确编码」的分片。KZG 承诺天然绑定了多项式次数,编码正确性就被免费获得了。
Avail 轻客户端与采样:Avail 的轻客户端同样是采样型的:
Avail 轻客户端流程:
1. 只下载区块头(含 KZG 承诺、数据根、扩展参数)
2. 随机采样 s 个分片位置
3. 对每个位置:从 DHT 请求分片 → 用区块头里的承诺验证(O(1) 群运算)
验证失败 → 立即广播「区块无效」
4. 采样全部成功 → 接受区块头,信任其数据可用
与 Celestia 的差异:
- Celestia:采样分片后用 NMT 证明校验位置(Merkle 路径,O(log n))
- Avail:采样分片后用 KZG 承诺校验(常数时间,但依赖配对运算)
- Celestia 需要编码欺诈证明兜底;Avail 用有效性证明前置规避
5.4 三家 DA 层的横向对比
| 维度 | Celestia | EigenDA | Avail |
|---|---|---|---|
| 架构定位 | 独立 DA 链 | EigenLayer 上的 AVS | 独立 DA 链 |
| 共识机制 | CometBFT | 复用以太坊共识 | BABE/GRANDPA 系 |
| 编码方案 | 2D Reed-Solomon | Reed-Solomon + KZG | 2D Reed-Solomon + KZG |
| 数据承诺 | 命名空间 Merkle 树 | KZG 承诺 | KZG 承诺 |
| 可用性验证 | 采样 + 编码欺诈证明 | 运营商签名 + KZG 分片验证 | 采样 + KZG 有效性证明 |
| 安全来源 | 自身验证者 + 采样概率 | 再质押 ETH 的经济安全 | 自身验证者 + 采样概率 |
| 出块间隔量级 | 秒级 | 分钟级批次 | 秒级 |
| 典型适用场景 | 通用 Rollup / 主权 Rollup | 高吞吐 Rollup、成本敏感 | 应用链、需要有效性证明的场景 |
一句话总结:Celestia 与 Avail 都在解决「编码是否正确」这个采样无法覆盖的盲区,只是路径不同——Celestia 用欺诈证明事后兜底,Avail 用 KZG 有效性证明事前绑定;EigenDA 则干脆把可用性外包给有真金白银质押的运营商集合。
6. Rollup 的 DA 选型与成本对比
6.1 三种 DA 模式
对 Rollup 而言,DA 选型本质上是在「成本」与「安全假设」之间做权衡:
模式 A:Calldata(EIP-4844 之前的主流)
数据写入 L1 交易的 calldata;成本每字节 16 gas(非零字节),最贵
安全:完全继承以太坊 L1,无额外假设
限制:与 L1 普通交易争抢区块空间,gas 费高时成本爆炸
模式 B:Blob(EIP-4844 之后)
数据写入 blob,承诺(versioned hash)放进区块头
成本:独立的 blob gas 市场,价格极低
安全:完全继承以太坊共识,但数据约 18 天后被剪枝
限制:每区块 6 个 blob 上限(目标 3),单 blob 128 KB
模式 C:外部 DA 层(Celestia / EigenDA / Avail)
数据发布到独立 DA 层,只把承诺写入 L1
成本:比 blob 更低,且不占以太坊区块空间
安全:引入 DA 层自身的信任假设(采样安全性或再质押经济安全)
限制:桥与提款逻辑需要额外验证 DA 承诺
6.2 EIP-4844 blob 的机制细节
理解 blob 的定价与生命周期是选型的前提:
EIP-4844 关键参数(Dencun 硬分叉引入):
BLOB_SIZE = 4096 个 field element × 32 字节 = 131072 字节(128 KB)
GAS_PER_BLOB = 131072(2^17)
TARGET_BLOB_PER_BLOCK = 3
MAX_BLOB_PER_BLOCK = 6
MIN_BLOB_GASPRICE = 1 wei
保留期 = 4096 个 epoch(约 18 天)
定价机制:与 EIP-1559 同构,但使用独立的 blob gas 市场
blob_base_fee 随超额 blob gas 指数上升;
目标 3 个 blob / 区块 → 超出则价格指数上涨,低于则回落
链上访问方式:
- BLOBHASH 操作码(0x49):读取当前交易引用的 blob versioned hash
- point evaluation 预编译合约(地址 0x0a):验证 KZG 求值证明
- 执行层无法直接读取 blob 内容,只能验证承诺与求值证明
6.3 成本模型与量级对比
用一个具体的 Rollup 场景估算:每个批次发布 1 MB 数据。
场景:每个批次 1 MB 数据,ETH = 3000 美元,base fee = 20 gwei
【模式 A:calldata】
1 MB = 1048576 字节,按 16 gas/字节:
gas = 1048576 × 16 = 16,777,216 gas
成本 = 16777216 × 20e-9 ETH = 0.3355 ETH ≈ 1006 美元
→ 每 MB 约 1000 美元量级
【模式 B:blob(EIP-4844)】
1 MB 数据 = 8 个 blob(每个 128 KB)
blob gas = 8 × 131072 = 1,048,576 blob gas
最低价(1 wei/blob gas):成本 ≈ 1.05e-12 ETH ≈ 0.000003 美元
blob base fee = 20 gwei 的紧张情况:成本 ≈ 0.021 ETH ≈ 63 美元
→ 常态下几乎免费,拥堵时约为 calldata 的 1/16
→ 相比 calldata 的降幅:常态下 5~8 个数量级,拥堵时约 16 倍
【模式 C:外部 DA 层】
Celestia / EigenDA 的每 MB 成本通常在亚美元量级,
且不占用以太坊区块空间,但需要额外支付 L1 上的承诺提交成本
(一个 versioned hash / 承诺约 20~50 字节 calldata,可忽略)
→ 成本最低,但引入 DA 层信任假设
注意这里必须诚实地指出:blob 在最低价附近几乎免费是 EIP-4844 的设计结果(MIN_BLOB_GASPRICE = 1 wei),这在实践中造成了一个副作用——blob 空间长期处于极低利用率状态下的「免费」,而一旦出现批量发布的需求(如铭文类应用),blob base fee 会指数级飙升。成本估算必须同时考虑常态与拥堵两个区间。
6.4 blob 与 Celestia 的对比表
| 维度 | EIP-4844 blob | Celestia DA |
|---|---|---|
| 数据容量 | 每 blob 128 KB,每区块最多 6 个(约 768 KB) | 区块大小可调,理论吞吐远高于 blob |
| 定价市场 | 独立 blob gas 市场,最低 1 wei | 独立手续费市场(TIA 计价) |
| 数据保留 | 约 18 天后剪枝 | 长期保留(由 DA 层共识决定) |
| 安全来源 | 完全继承以太坊 L1 共识 | Celestia 验证者集合 + DAS 采样概率 |
| 桥的验证成本 | 低:验证 blob versioned hash 即可 | 需额外验证 DA 承诺与采样结果 |
| 提款安全假设 | 与 L1 相同 | 需信任 Celestia 的可用性保证 |
| 适用场景 | 主流 Rollup 默认选择 | 高吞吐应用链、成本极度敏感场景 |
6.5 合约侧的 DA 适配器
无论选哪种 DA,Rollup 的结算合约都需要一个统一的「DA 承诺校验」入口。下面是一个可切换 DA 后端的最小接口:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @notice DA 承诺的统一表示
/// @dev 不同 DA 后端的承诺形态不同,用 kind 区分解析方式
struct DACommitment {
uint8 kind; // 0 = calldata, 1 = blob, 2 = external DA
bytes32 commitment; // calldata: keccak 哈希; blob: versioned hash; 外部: DA 层承诺
uint64 dataLength; // 原始数据长度(字节)
}
interface IDABackend {
/// @notice 校验该批次的 DA 承诺是否有效
function verifyCommitment(DACommitment calldata c) external view returns (bool);
/// @notice 返回该后端的数据保留窗口(秒),用于桥的提款延迟设置
function retentionWindow() external view returns (uint64);
}
/// @notice 基于 EIP-4844 blob 的 DA 后端
contract BlobDABackend is IDABackend {
error BlobHashMismatch(uint256 index, bytes32 expected, bytes32 actual);
function verifyCommitment(DACommitment calldata c) external view returns (bool) {
if (c.kind != 1) return false;
// 批次交易中第 0 个 blob 的 versioned hash 必须与承诺一致
bytes32 h = blobhash(0);
if (h != c.commitment) revert BlobHashMismatch(0, c.commitment, h);
return true;
}
function retentionWindow() external pure returns (uint64) {
// EIP-4844 保留期约 4096 epoch,按 12 秒/槽位、32 槽位/epoch 估算
return 4096 * 32 * 12; // 约 18 天
}
}
/// @notice 基于外部 DA 层(Celestia / EigenDA / Avail)的后端
/// @dev 需要 DA 层提供轻客户端或预言机把「采样结果」喂进合约
contract ExternalDABackend is IDABackend {
address public immutable daAttester;
uint64 private immutable _retention;
mapping(bytes32 => bool) public attested;
error UnauthorizedAttester(address caller);
error CommitmentNotAttested(bytes32 commitment);
constructor(address attester_, uint64 retention_) {
daAttester = attester_;
_retention = retention_;
}
/// @notice DA 层轻客户端把采样通过结果提交到链上
/// @dev 生产实现须验证 proof(多签聚合 或 DA 层的有效性证明)
function attest(bytes32 commitment, bytes calldata) external {
if (msg.sender != daAttester) revert UnauthorizedAttester(msg.sender);
attested[commitment] = true;
}
function verifyCommitment(DACommitment calldata c) external view returns (bool) {
if (c.kind != 2) return false;
if (!attested[c.commitment]) revert CommitmentNotAttested(c.commitment);
return true;
}
function retentionWindow() external view returns (uint64) { return _retention; }
}
这段代码暴露了一个容易被忽略的设计要点:外部 DA 的 retentionWindow() 必须参与桥的提款延迟设置。如果 DA 层只保留 30 天数据,而 Optimistic Rollup 的挑战期是 7 天,那么任何依赖「数据在挑战期内可得」的提款逻辑都必须显式校验这个时间约束。
一句话总结:DA 选型不是「越便宜越好」——calldata 最贵但零额外假设,blob 便宜且继承 L1 安全但只有 18 天保留,外部 DA 最便宜但把安全外包给了另一个系统;正确做法是把 DA 后端抽象成可替换接口,并让保留窗口显式参与桥的安全参数。
7. 工程落地与踩坑
7.1 DA 适配器接口设计
从上面的合约可以看出,一个可维护的 DA 抽象需要满足三点:承诺格式统一(用 kind 字段区分后端,避免为每种 DA 写一套结算逻辑)、保留窗口可查询(让桥、挑战期、数据同步任务都能读取并据此调整参数)、验证可组合(把「承诺有效」与「数据可用」分成两个函数——前者是纯链上检查,后者依赖外部证明)。常见的架构错误是把这两件事混在一个 require 里,导致升级 DA 后端时必须重新部署整个结算合约。
7.2 blob 的过期与历史数据可用性
这是从 calldata 迁移到 blob 后最容易踩的坑:
问题:blob 数据约 18 天后被以太坊节点剪枝。
影响面:
1. 新加入的全节点无法通过 blob 重放历史状态
→ 必须依赖其他节点提供的历史数据快照
2. 需要历史数据的应用(区块浏览器、索引器、审计工具)
必须在保留期内把 blob 数据落地到自己的存储
3. 桥的提款验证如果依赖「重新下载 blob 数据」,18 天后会直接失效
正确做法:
- 索引器在 blob 提交后立即拉取并持久化(含 KZG 证明校验)
- 桥的验证逻辑只依赖「状态根 + 承诺」,不依赖重新下载原始数据
- 明确记录每个批次的 blob 保留到期时间,作为运维指标
7.3 桥、DA 承诺与提款安全
DA 承诺与桥的安全耦合是最容易出事故的地方。三条必须遵守的原则:承诺必须绑定到批次,不能是全局变量——如果一个 DA 承诺可以被复用(例如只校验「某个根存在」而不校验「该根属于这个批次」),攻击者就能用旧批次的合法承诺为新的恶意批次背书;提款延迟必须不小于 DA 保留窗口的交集——当 Rollup 同时使用 blob 和外部 DA 时,取两者的最小值作为安全边界;DA 失败必须 fail-closed——轻节点在采样超时或网络异常时应判定「不可用」,而不是「乐观接受」,Celestia 与 Avail 的轻客户端都遵循这一原则,自研 DA 校验逻辑时必须显式实现。
7.4 采样安全性论证背后的假设
论文里的 (1/4)^s 很漂亮,但工程实现中有几个会削弱它的现实因素:
| 假设 | 现实偏差 | 缓解方式 |
|---|---|---|
| 采样位置真随机 | 客户端 PRNG 被污染或复用种子 | 使用系统级 CSPRNG,每次采样重新取种子 |
| 网络请求不可被阻断 | 对手可对特定轻节点做连接级封锁 | 多路复用请求、随机对等节点、fail-closed 策略 |
| 分片请求的诚实响应 | 恶意节点可返回错误数据 | 用 Merkle/KZG 证明校验每个分片 |
| 数据承诺绑定编码 | 承诺与实际分发不一致 | KZG 绑定(EigenDA/Avail)或编码欺诈证明(Celestia) |
生产踩坑清单:
- blob 数量硬编码。
MAX_BLOB_PER_BLOCK会随硬分叉调整,把 6 写死在合约或客户端里会在下一次分叉后失效。 - 忽略 blob base fee 的指数上涨。在拥堵期,blob 成本可能从近乎免费涨到超过 calldata 的估算值,成本模型必须有降级策略(例如回退到外部 DA 或延迟批次)。
- 把 DA 层的手续费代币与 ETH 混算。Celestia 的 TIA 价格与 ETH 独立波动,跨系统成本比较必须按实时汇率并做敏感性分析。
- 采样次数与安全级别不匹配。
s = 5时(1/4)^5 ≈ 0.1%的漏检概率在金融场景下不可接受,生产环境通常需要s ≥ 15。 - 未验证分片的 Merkle/KZG 证明。只从网络拿到分片就当作有效数据,会让恶意节点用垃圾数据污染采样结果。
- DA 承诺与状态根分离提交。如果两者在不同的交易中提交,中间存在一个「状态根已确认但 DA 未确认」的窗口,攻击者可利用该窗口发起提款。
- 忽视
blobhash的索引语义。blobhash(0)读取的是当前交易引用的第 0 个 blob,在批次交易之外调用会返回 0,导致校验静默通过。 - 索引器未在保留期内落地数据。18 天窗口一旦错过,历史数据就永久丢失。
一句话总结:DA 层的工程风险几乎都集中在「承诺与数据的绑定关系」上——承诺必须绑定批次、分片必须验证证明、提款延迟必须覆盖保留窗口、失败必须 fail-closed,这四条守住了,模块化的信任假设才站得住。
8. 总结
- 模块化的本质是接口标准化:执行、结算、共识、DA 四层各自独立演进,Rollup 是最早的模块化实践,而 DA 层是拆层之后最先撞到的瓶颈。
- 数据可用性是链上不可见的风险:区块在出、哈希在更新,但数据可能已经丢失;DA 层的任务是把这个问题变成轻节点可概率验证的问题。
- Celestia 用 2D Reed-Solomon + DAS 采样:1/4 阈值让攻击者必须隐藏 3/4 的数据,从而让
s次采样以(1/4)^s的漏检概率换取极高的安全级别。 - EigenDA 用 KZG + 纠删码 + 再质押:把可用性从概率问题变成经济问题,安全成本随租用的质押量线性增长,罚没是事后惩罚而非即时生效。
- Avail 用 KZG 有效性证明规避编码欺诈证明:因为 RS 编码就是「同一个低次多项式在更多点求值」,KZG 承诺天然绑定了编码正确性。
- Rollup 的 DA 选型是成本与信任假设的权衡:calldata 最贵但零假设,blob 近乎免费但只有约 18 天保留,外部 DA 最便宜但引入新的信任依赖。
- 工程落地的核心是承诺绑定:DA 承诺必须绑定批次、分片必须验证证明、提款延迟必须覆盖保留窗口、采样失败必须 fail-closed。
相关阅读
- Layer2 扩容:Rollup 架构、数据可用性与跨 L2 桥
- Rollup 序列器、L3 与应用链
- 区块链共识算法深入
- 区块链密码学基础
- 零知识证明:zk-SNARKs、zk-STARKs、电路与隐私应用
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。