你的钱在一个 L2 上。状态转移全部被零知识证明保证过,绝对正确,一个字节都没错。

然后排序器不再公布数据。

你的余额还在链上,正确无误。可你不知道它是多少,也就构造不出取款需要的那份证明。

钱在,你取不出来。

前三讲反复指向同一个问题。这一讲正面处理它。

一、把问题说准确

⚠️ “数据可用性(DA)“这个名字有误导性——它讲的不是"存储”,是"发布”。

⭐ 准确的问题:
   一个区块生产者广播了区块头(含数据的承诺)。
   他是否真的把【完整数据】发布出去了,
      使得任何想要的人都能拿到?

注意它不问"数据会不会被永久保存"。 它只问:在发布的那一刻,数据是否真的进入了公共可及的状态。

二、为什么这个问题特别难

它有一个反直觉的性质:无法被归责。

❌ 方案一:让节点举报"我没收到数据"
   ⚠️ 一个恶意节点可以在数据明明发布了的情况下谎称没收到。
   ⟹ 无法区分"数据真的没发"和"这个人在撒谎"

❌ 方案二:让发布者签名承诺"我发布了"
   他可以【只发给一部分人】。
      收到的人说"发了",没收到的人说"没发"。
   ⟹ 从链上看,双方的证词无法裁决

❌ 方案三:谁没收到就罚发布者
   那么任何人都可以通过谎称"没收到"来诬告发布者

打个比方

这三条路走不通的原因,可以用一句日常的话说清:“我没收到你的信"这件事,没法证明。

收到了,你可以把信拿出来。没收到,你拿不出任何东西——而拿不出东西,和"你在撒谎说没收到”,长得一模一样。

于是仲裁者面对两份互相矛盾的证词,手上没有任何可以裁决的材料

⭐ 这被称为"渔夫困境(fisherman’s dilemma)":

对于"某件事没有发生"这类命题,不存在简洁的证明。

"这笔交易无效" —— ⭐ 可以证明(把交易和状态拿出来算一遍)
"这份数据没有被发布" —— 【无法证明】

正因为无法归责,DA 不能靠惩罚机制解决,只能靠"让每个人自己去验证"——而这正是第五节采样方案的出发点。

三、它为什么是全部 L2 安全的地基

回顾前三讲,每一条都通向这里:

① Optimistic Rollup(第 27 讲)
   ⚠️ 没有数据 ⟹ 挑战者无法重算状态 ⟹ 生成不了欺诈证明
   ⟹ 排序器可以提交任意错误状态而无人能挑战

② ZK Rollup / Validium(第 26、28 讲)
   状态转移是被证明过的,绝对正确。
   但数据被扣留时,你【不知道自己的余额是多少】,
      也就【构造不出提款所需的 Merkle 证明】。
   ⟹ 钱在链上,正确无误,而你取不出来。

③ 轻客户端(第 13 讲)
   没有数据 ⟹ 欺诈证明无法生成 ⟹ SPV 无法被补救

所以 L2 的分类,本质上就是按"数据发到哪里"来分的:

Rollup    —— ⭐ 数据发到 L1        ⟹ 安全性 = L1 的安全性
Validium  —— 数据在链下委员会   ⟹ 安全性 = 那个委员会
侧链      —— 数据在自己的链上   ⟹ 安全性 = 它自己的共识

四、朴素方案与它的代价

最简单的保证:让所有人都下载所有数据。

⭐ 这确实解决了问题——你自己下到了,就知道它可用。
但它把我们送回第 3 讲那个约束:T ≤ R / c
⟹ 数据量受限于普通人的带宽

所以真正的问题变成:能不能在【不下载全部数据】的前提下,高置信度地确认它是可用的?

五、数据可用性采样

⭐ 既然"没收到"证明不了,那就别去证明它——换成每个人自己抽查几下。下面这一节的全部巧妙之处,是让"抽几下"这个廉价动作,能对"数据是否可用"给出极高的置信度。

朴素采样为什么不行

想法:每个轻节点随机抽查几个数据块。

⚠️ 攻击者只需藏起【1%】的数据,整块数据就无法完整重建。
   而随机抽 30 次都没碰到那 1% 的概率是 0.99³⁰ ≈ 74%。
⟹ 大概率抽不到,采样几乎无效。

根本问题:藏一点点就能造成致命破坏,而一点点很难被随机抽到。

纠删码把这个不对称扭转过来

把 n 个数据块,用 Reed-Solomon 码扩展成 2n 个:
   ⭐ 任意 n 个就能恢复出全部原始数据。

⟹ 攻击者要让数据【不可恢复】,
   必须藏起【超过一半】的块(即多于 n 个)。

这是整个方案的关键一步:它把"藏 1%“这个廉价攻击,变成了"必须藏 50% 以上”。

于是随机采样立刻变得极其有效:

攻击者藏起了超过一半的数据。
一个轻节点随机抽查 k 个位置,⭐ 全部命中"可用"部分的概率 ≤ (1/2)ᵏ

   k = 10  ⟹ 约 1/1000
   k = 20  ⟹ 约 1/100 万
   k = 30  ⟹ 约 1/10 亿

每个轻节点只下载 30 个小块(几十 KB),就能以 10⁻⁹ 的错误率确认"数据可用"。

而且节点越多越安全:所有轻节点的采样合起来,实际上覆盖了全部数据——它们共同"托管"了这份数据,而没有任何一个人下载了全部。

还差一步:编码本身可能是错的

⚠️ 如果攻击者【故意错误地编码】,
   那么"任意 n 个块可恢复"这个前提就不成立。
   ⟹ 你抽到的块都"可用",但拼起来是垃圾。

两种解决办法:

① 纠删码错误证明(fraud proof)
   ⚠️ 需要有人下载足够多的块来发现编码错误,
      于是引入了二维纠删码:
      按行列两个方向编码,使得"证明某一行编码错误"
      只需要那一行的数据,而不是全部。

② 多项式承诺(KZG)—— 以太坊选的路
   把每一行数据看成一个多项式,发布它的 KZG 承诺。
   每个采样点都附带一个【常数大小】的证明,
      证明"这个位置的值确实在承诺的多项式上"。
   ⟹ 编码正确性由密码学直接保证,根本不需要欺诈证明。

这就是第 8 讲提到的 KZG 在这里的真正用途,也是以太坊举办 14 万人可信设置仪式(第 28 讲)的原因。

六、EIP-4844:Blob

坎昆升级引入了一种专门承载 DA 数据的新载体。

一个 blob = 4096 个域元素 × 32 字节 = 128 KiB
每个区块目标 3 个 blob,上限 6 个(上线时的参数)

三个关键设计:

① blob 数据不进入 EVM

合约只能看到 blob 的【versioned hash】(一个 32 字节的 KZG 承诺哈希),
⚠️ 无法读取 blob 的内容。

为什么:Rollup 根本不需要在合约里读这些数据——
   它只需要"数据已发布"这个事实,以及一个能被证明绑定的承诺。
⟹ 于是数据不必进入状态,也不必被 EVM 处理,成本大幅降低。

② 独立的费用市场

blob 有自己的 blob gas 和 blob 基础费,
⭐ 与普通交易的 Gas 市场【完全解耦】,各自按 EIP-1559 式规则调整。

⟹ NFT 热潮推高普通 Gas 时,不会连带推高 Rollup 的数据成本
⟹ 反之亦然

这是一个很好的机制设计:两种需求性质不同,就该有两个市场。

③ 约 18 天后删除

blob 只保留约 4096 个 epoch(约 18 天),之后节点可以删除。

这看起来很惊人——“数据被删了,还叫可用吗?”

回到第一节的定义就清楚了:

DA 保证的是"数据在【发布的那一刻】确实进入了公共可及状态",
⭐ 而不是"数据被永久保存"。

⟹ 只要在那 18 天里,所有关心的人(Rollup 节点、
   挑战者、想提款的用户)都有充分时间取走它,
   DA 的职责就完成了。

⟹ 长期存档是【另一件事】,由 Rollup 运营方、
   区块浏览器、归档节点等自行负责——
   而且它只需要 1-of-N 假设:只要有一个人还存着就行。

这个区分极其重要,因为它解释了为什么 DA 可以便宜:全网永久存储是昂贵的,而"保证发布 + 短期保留"便宜得多。

七、Danksharding 与 DA 层的选择

完整的 Danksharding 目标:⭐ 每个区块 32 MB 的 blob 数据,
   而全节点【只做采样,不下载全部】。
⟹ 结合第 13 讲的无状态客户端,验证成本与数据量彻底解耦。

不同 DA 方案的安全性差异

方案 数据在哪 谁保证可用 安全性
以太坊 blob L1 全体以太坊验证者 + DAS 最高
独立 DA 链(如 Celestia) 自己的链 它自己的验证者集 + DAS 取决于该链的质押量
DA 委员会(DAC) 少数几台服务器 一个多签 等于那个多签
不发布 只有排序器有 等于信任排序器

评估任何 L2 时,“数据发到哪里"是第一个该问的问题,而不是"用了 OP 还是 ZK”。

⚠️ 一个用 ZK 证明但把数据放在 5/8 委员会里的方案,
   安全性上限就是那 5/8 委员会——
   无论它的密码学多漂亮。

八、Go:纠删码与采样

package da

import "math"

// SampleFailureProbability 返回"数据不可恢复但采样全部通过"的概率。
// ⭐ 纠删码保证:攻击者要让数据不可恢复,必须藏起超过一半的块。
// 于是每次随机采样命中"可用部分"的概率 ≤ 1/2。
func SampleFailureProbability(samples int) float64 {
	return math.Pow(0.5, float64(samples))
}

// SamplesNeeded 返回把失败概率压到 target 以下所需的采样次数。
func SamplesNeeded(target float64) int {
	n := 0
	for SampleFailureProbability(n) > target {
		n++
	}
	return n // target = 1e-9 时约为 30
}

// NaiveSampleFailure 对照组:没有纠删码时的情况。
// 攻击者只需藏起 hiddenFraction(比如 1%),
// 而随机采样很难碰到它——这说明了纠删码为什么是必需的。
func NaiveSampleFailure(samples int, hiddenFraction float64) float64 {
	return math.Pow(1-hiddenFraction, float64(samples))
}

// ─────────── Reed-Solomon 扩展(概念示意) ───────────

// Extend 把 n 个数据块扩展成 2n 个。
// 做法:把数据看成一个 n−1 次多项式在 n 个点上的取值,
// 再求出它在另外 n 个点上的值。
// ⟹ 任意 n 个点唯一确定该多项式 ⟹ 任意 n 个块可恢复全部。
// (与第 8 讲 Shamir 秘密分享是同一个数学原理。)
func Extend(data [][]byte, encode func([][]byte) [][]byte) [][]byte {
	return encode(data) // 返回 2n 个块
}

// Recoverable 判断给定的可用块数是否足以恢复原始数据。
func Recoverable(availableBlocks, originalBlocks int) bool {
	return availableBlocks >= originalBlocks
}

// MinHiddenToBreak 返回攻击者要让数据不可恢复至少需要藏起多少块。
// 扩展到 2n 之后,藏起 n+1 个才能让"任意 n 个"这个条件失效
// ——即必须藏起【超过一半】。
func MinHiddenToBreak(originalBlocks int) int {
	return originalBlocks + 1 // 总共 2n 块,藏起 n+1 块
}

// ─────────── Blob 费用市场(EIP-4844) ───────────

const (
	BlobSize            = 131072 // 128 KiB = 4096 × 32 字节
	TargetBlobsPerBlock = 3
	MaxBlobsPerBlock    = 6
)

// NextBlobBaseFee 用与 EIP-1559 相同的反馈规则调整 blob 基础费。
// 关键在于它是【独立市场】:普通交易拥堵不会推高 Rollup 的数据成本。
func NextBlobBaseFee(parentFee uint64, parentBlobs int) uint64 {
	switch {
	case parentBlobs > TargetBlobsPerBlock:
		return parentFee + parentFee/8 // 上限约 +12.5%
	case parentBlobs < TargetBlobsPerBlock:
		if parentFee <= 1 {
			return 1
		}
		return parentFee - parentFee/8
	default:
		return parentFee
	}
}

// RetentionEpochs 是 blob 的保留期(约 18 天)。
// 删除不损害安全性:DA 保证的是"发布的那一刻数据公开可及",
// 而不是"永久保存"。长期存档是另一件事,
// 且它只需要 1-of-N 假设——有一个人还存着就够了。
const RetentionEpochs = 4096

九、本讲小结

  • 数据可用性讲的是"发布",不是"存储"。 它只问:在发布的那一刻,数据是否真的进入了公共可及状态。
  • ⭐⭐ 它无法被归责(渔夫困境):无法证明"某件事没发生"。举报可以撒谎,签名可以只发给一部分人。所以 DA 不能靠惩罚解决,只能靠每个人自己验证。
  • 它是全部 L2 安全的地基:没有数据,欺诈证明生成不了;有效性证明再正确,你也构造不出提款所需的 Merkle 证明——钱在链上、正确无误,而你取不出来。
  • L2 的分类本质上就是按"数据发到哪"划分的:Rollup 发到 L1、Validium 在委员会、侧链在自己链上。
  • 朴素采样无效:藏起 1% 就能让数据不可恢复,而 30 次随机抽样有 74% 概率碰不到。
  • ⭐⭐ 纠删码扭转了这个不对称:n 个块扩展成 2n,任意 n 个可恢复 ⟹ 攻击者必须藏起一半以上。于是 k 次采样的失败概率降到 (1/2)ᵏ——30 次采样、几十 KB,错误率约十亿分之一。
  • 节点越多越安全:所有轻节点的采样合起来覆盖了全部数据,而没有任何一个人下载了全部
  • 还需保证编码本身正确:二维纠删码 + 错误证明,或 KZG 承诺直接用密码学保证(以太坊的选择,也是那场 14 万人仪式的用途)。
  • EIP-4844 blob 的三个设计:数据不进 EVM(只暴露 versioned hash)、独立费用市场(NFT 热潮不再推高 Rollup 成本)、约 18 天后删除。
  • 删除不损害安全性,因为 DA 保证的是"发布过"而非"永久存"。长期存档是另一件事,且只需要 1-of-N——有一个人还存着就够了。 这正是 DA 能便宜的原因。
  • 评估 L2 时第一个该问的是"数据发到哪里",不是"用了 OP 还是 ZK"。 一个用 ZK 但把数据放在 5/8 委员会的方案,安全上限就是那个委员会。

思考题

  1. 用自己的话说清"数据可用性是发布而不是存储",并解释这个区分为什么让 blob 可以被删除。
  2. 为什么"某件事没有发生"无法被简洁证明?请构造一个具体的场景,说明举报机制会失效。
  3. 一个 Validium 的状态转移全部有 ZK 证明。运营者扣留数据时,你具体缺少什么、因而做不到什么?
  4. 没有纠删码时,攻击者藏 5% 的数据,你抽查 50 次碰到它的概率是多少?
  5. 有了纠删码后,为什么攻击者必须藏起一半以上?请从"任意 n 个块可恢复"推导。
  6. 要把失败概率压到 10⁻¹²,需要采样多少次?下载量大约是多少?
  7. 为什么"节点越多越安全"?请说明轻节点的采样如何共同覆盖全部数据。
  8. 攻击者故意错误编码会怎样?分别说明二维纠删码和 KZG 各自如何解决它,并比较代价。
  9. 为什么 blob 数据不让 EVM 读取?如果允许读取会带来什么问题?
  10. 一个 L2 宣称"我们用 ZK 证明,数据由一个 8 人委员会保管,其中 5 人签名即可"。请给出它的安全性上限,并说明它是不是 L2。