历史上金额最大的几次加密资产被盗,大部分不是发生在链上,是发生在桥上。
这不是巧合。这一讲会说明:桥的脆弱是结构性的——不是因为写桥的人水平差,而是因为桥要做的那件事,在原理上就没法像链本身那样被保证。
一、为什么跨链这么难
链 A 上的一个合约,想知道"链 B 上发生了什么"。
⚠️ 它做不到。
打个比方
两条链的关系,像两间没有窗户、也没有电话的密室。
房间里的人可以完美地记录房间内发生的一切。但"隔壁房间发生了什么",他们没有任何自己观测的手段——只能听某个能进出两间房的人转述。
⭐ 而只要有转述,问题就变成了"这个人可不可信",密码学在这一步帮不上忙。
⚠️ 这一点最容易被营销话术盖过去。“去信任化的桥"“无需信任的跨链"这类说法,没有一个能真正取消上面那个转述者——它们能做的只是把转述者换成一群人、或者换成一个可以被惩罚的人。信任被稀释、被抵押、被分散了,但它没有消失。 下面几节的分类,本质上就是按"转述者是谁、出错时你能拿他怎么办"来排的。
⭐ 根本原因回到第 1 讲第六节:
一条链是一台复制状态机,它只知道自己被喂了什么。
链 A 的节点不会去运行链 B 的客户端,也没有任何机制让它"看到"链 B。所以:
⭐ 任何跨链方案,本质上都是一个【关于链 B 状态的预言机】。
⟹ 而预言机必然引入某种信任假设。
⟹ 问题不是"要不要信任",而是"信任谁、信任多少"。
二、桥做什么
三种基本形态:
① 锁定-铸造
在链 A 锁住 100 个代币 ⟹ 在链 B 铸出 100 个"包装代币"
⚠️ 链 B 上的那 100 个,价值完全依赖于链 A 锁仓的安全
② 销毁-释放
上面的逆过程
③ 流动性池
两条链各有一个池子,用户在 A 存入、从 B 的池子取出
不涉及铸造,但需要做市商提供两边的流动性
⚠️ 注意第 ① 种的含义:链 B 上的"BTC"根本不是 BTC。 它是一张由桥背书的欠条——第六节会展开这件事的后果。
三、三类信任假设
这是本讲的核心分类,也是评估任何桥的唯一有效框架。
① 原生验证:在链 A 上运行链 B 的轻客户端
⭐ 在链 A 的合约里,实现链 B 的共识验证逻辑:
验证链 B 的区块头签名、验证 Merkle 证明。
⟹ 信任假设 = min(链 A 的安全性, 链 B 的安全性)
【不引入任何额外的信任方】
⭐ 这是唯一"没有新增信任"的方案。
⚠️ 但代价很大:
① 昂贵:在合约里验证另一条链的共识,Gas 成本很高
(所以链 B 最好用 BLS 聚合签名这类验证便宜的方案,第 8 讲)
② ⚠️ 对 PoW 链尤其困难:要在合约里跟踪难度和最重链
③ 需要为【每一对】链定制实现
④ 若链 B 硬分叉,桥合约也必须跟着升级
代表:
⭐ Rollup 的官方桥 —— 最纯粹的原生验证。
L1 上的合约本来就知道 L2 的状态根(第 27、28 讲),
⟹ 提款只需一个 Merkle 证明,零额外信任。
IBC(Cosmos)—— 为轻客户端验证专门设计的链间协议,
依赖 Tendermint 的即时最终性(第 19 讲)让轻客户端验证变得可行。
② 外部验证:一组人观察并签名
一组验证者(多签、MPC、或独立的验证者网络)监视链 B,
看到事件后共同签名,链 A 的合约验证这个签名。
⚠️ 信任假设 = 【那组人】
⟹ 与两条链本身的安全性【完全无关】
这是最常见的形态,因为它最容易实现、最通用、最便宜。 也是历史上损失最惨重的形态。
③ 乐观验证
假设提交的跨链消息是正确的,设置一个挑战期,
任何人可以在期内提交欺诈证明。
⭐ 信任假设 = 1-of-N(第 27 讲)
代价 = 延迟(挑战期)
四、历史事故几乎全部集中在一类
⭐ 这一节是那两间密室最贵的一课:事故几乎全部发生在"转述者"身上,而不是密室的墙上。下面按转述者是谁来排,你会看到损失规模和这个人的可替代性高度相关。
按涉案规模排列几起最著名的事件。⚠️ 注意"被盗金额"和"最终损失"是两回事,下面分开写:
Ronin 桥(2022) 涉案约 6.2 亿美元
⚠️ 5/9 多签。攻击者用鱼叉式钓鱼拿到 4 个验证者密钥,
第 5 个来自一个此前被授权代签的外部验证者。
密码学完好无损——它就是按设计工作的。
Poly Network(2021) 涉案约 6.1 亿美元
跨链管理员权限可被构造的消息篡改。
⚠️ 但攻击者随后【全额归还】了资金,实际损失接近零。
BNB 桥(2022) ⚠️ 凭空增发约 5.7 亿美元,
但链被及时暂停,真正转移出去的约 1 亿
轻客户端证明(IAVL Merkle 证明)的验证实现存在漏洞,可伪造证明。
Wormhole(2022) 涉案约 3.2 亿美元
签名验证的实现缺陷——一个校验被绕过。
⚠️ 缺口由投资方补足,用户未直接承担。
Nomad(2022) 涉案约 1.9 亿美元
一次初始化把"零消息根"设成了可信,
于是【任意消息】都能通过验证。
而且因为攻击方法极其简单,最后变成了公开的哄抢。
⚠️ 其中一部分后来被白帽归还。
⭐ 把"涉案"和"损失"分开,本身就说明了一件事:这类事故的最终结果,很大程度上取决于【链外的反应速度和补救意愿】——暂停链、协商归还、投资方兜底。⚠️ 而这些都不是协议保证。
⭐ 两个共同点,值得反复看:
① ⭐ 绝大多数是【外部验证型】,或原生验证的【实现出错】。
没有一起是因为密码学被攻破。
② 失败点集中在两处:【密钥管理】和【实现细节】。
⟹ 这与第 7 讲(k 重用)、第 24 讲(Parity)是同一个模式:
系统在数学上成立,在工程上失守。
五、为什么桥是最大的攻击目标
① ⭐ 资产高度集中
所有跨过去的资产都锁在【同一个合约】里。
⟹ 一个桥的锁仓量可能超过许多条链的市值。
② 安全性等于最弱环节
桥连接的两条链可能各自都很安全,
但攻击者只需要攻破【桥本身】。
③ 复杂度极高
两套共识 + 消息格式 + 重放保护 + 升级机制 + 密钥管理,
每一处都是攻击面。
④ 桥往往比它连接的链更新、更少被审视
⭐ 一个有用的判断:一个桥锁着 10 亿美元,而攻破它只需要拿到 5 个私钥——那么这 10 亿美元的实际安全性,等于那 5 个人的运维水平。
六、包装资产与连锁风险
链 B 上的 wBTC 不是 BTC,它是一张欠条。
⚠️ 桥被攻破 ⟹ 抵押品没了 ⟹ 欠条归零。
⭐ 而真正危险的是二阶效应:
包装资产被用作 DeFi 的抵押品
⟹ 桥被攻破,包装资产归零
⟹ ⭐ 所有以它为抵押的借贷【瞬间资不抵债】
⟹ 清算引擎试图卖出已经归零的抵押品,失败
⟹ 坏账扩散到整个借贷协议,波及从未碰过这座桥的用户
⭐ 所以桥的风险不会停留在桥上,它会通过组合性传染。
七、“多链但非跨链”
Vitalik 提出过一个精确的论点,值得完整理解:
⭐ 场景一:只有多条链,没有桥
攻击者用 51% 攻击了链 B。
⟹ 损害【局限在链 B 内部】。链 A 的用户毫发无损。
场景二:链 A 和链 B 之间有桥
攻击者用 51% 攻击链 B,
⟹ 在链 B 上伪造一笔"我存了 100 万代币"的交易
⟹ 通过桥把它提到链 A
⟹ 链 A 上的资产被真实地取走了
⭐ 结论:桥让攻击的破坏面从"被攻击的那条链"扩大到"所有与它相连的链”。
⚠️ 而整个网络的安全性,被拉低到最弱那条链的水平。
⭐ 这个论点的实际含义:
连接一条安全性低的链,不是"给用户多一个选择",
⭐ 而是把自己的安全性也拉到那条链的水平——
至少在跨过去的那部分资产上如此。
八、评估一个桥的四个问题
① ⭐ 它属于哪一类?
原生验证 / 外部验证 / 乐观验证
② 如果是外部验证:谁在签名?阈值多少?他们独立吗?
"5/9 多签"要看这 9 个是不是同一家公司的 9 台服务器。
Ronin 事件中,多个验证者节点由同一实体运营。
③ 锁了多少钱?攻破它需要多少成本?
如果锁仓远大于攻击成本,被攻击只是时间问题。
④ 合约能升级吗?谁能升级?有时间锁吗?
第 24 讲的四个问题在这里同样适用。
⚠️ 一个常见的营销话术:
"我们的桥由去中心化的验证者网络保障安全"
⭐ 追问:几个验证者?谁运营?质押了多少?作恶会被罚没吗?
如果作恶没有链上可执行的惩罚,那"验证者网络"只是"多签"的另一个说法。
九、Go:桥的信任模型
package bridge
import "math"
type TrustModel int
const (
// NativelyVerified:在链 A 上运行链 B 的轻客户端。
// ⭐ 唯一不引入新信任方的方案。安全性 = min(两条链)。
NativelyVerified TrustModel = iota
// ExternallyVerified:一组外部签名者背书。
// 安全性 = 那组人,与两条链本身无关。
ExternallyVerified
// OptimisticallyVerified:默认相信 + 挑战期。
// 安全性 = 1-of-N(第 27 讲)。
OptimisticallyVerified
)
type Bridge struct {
Name string
Model TrustModel
// 外部验证型的参数
Signers int
Threshold int
IndependentOps int // 实际【独立运营方】数量,可能远小于 Signers
SlashableStake bool // 作恶是否有链上可执行的惩罚
// 乐观验证型的参数
ChallengeWindowHours int
LockedValueUSD float64
Upgradeable bool
TimelockHours int
}
// EffectiveThreshold 返回攻击者【实际】需要攻破的实体数量。
// Ronin 的教训:9 个验证者不等于 9 个独立实体。
// 真正的阈值受限于独立运营方的数量。
func (b *Bridge) EffectiveThreshold() int {
if b.Model != ExternallyVerified {
return 0
}
if b.IndependentOps > 0 && b.IndependentOps < b.Threshold {
return b.IndependentOps
}
return b.Threshold
}
// SecurityCeiling 返回这座桥的安全性上限的文字描述。
// 核心判断:一座桥的安全性【不会超过】它的信任假设。
func (b *Bridge) SecurityCeiling() string {
switch b.Model {
case NativelyVerified:
return "min(链A安全性, 链B安全性) —— 无额外信任"
case OptimisticallyVerified:
return "1-of-N 诚实且能在挑战期内上链"
default:
if !b.SlashableStake {
// 没有罚没 ⟹ "验证者网络"实质就是多签
return "等于那 N 个签名者的运维与操守 —— 无链上惩罚"
}
return "等于签名者的质押总额"
}
}
// RiskRatio 返回"锁仓价值 ÷ 攻击成本"。
// 大于 1 意味着攻击在经济上划算(第 17 讲的安全比)。
func (b *Bridge) RiskRatio(costPerKeyUSD float64) float64 {
if b.Model != ExternallyVerified {
return 0 // 该模型下不适用此算法
}
attackCost := float64(b.EffectiveThreshold()) * costPerKeyUSD
if attackCost == 0 {
return math.Inf(1)
}
return b.LockedValueUSD / attackCost
}
// ContagionRisk 描述包装资产的二阶风险。
// 桥的风险不会停留在桥上——它通过 DeFi 的组合性传染。
type ContagionRisk struct {
WrappedAssetTVL float64 // 包装资产的总量
UsedAsCollateral float64 // 其中被用作借贷抵押品的部分
DownstreamProtos int // 有多少协议接受它
}
// PotentialLoss 返回桥被攻破时的潜在总损失。
// 它远大于桥本身的锁仓量:
// 以包装资产为抵押的借贷会瞬间变成坏账,
// 波及从未使用过这座桥的用户。
func (c *ContagionRisk) PotentialLoss(bridgeTVL float64) float64 {
return bridgeTVL + c.UsedAsCollateral
}
十、本讲小结
- 跨链难的根源是第 1 讲的预言机问题:一条链是复制状态机,只知道自己被喂了什么。任何桥本质上都是"关于另一条链的预言机”。 ⟹ 问题不是要不要信任,而是信任谁、信任多少。
- 链 B 上的"BTC"不是 BTC,是一张由桥背书的欠条。
- 三类信任假设:
- 原生验证(在链 A 上跑链 B 的轻客户端):唯一不引入新信任方,安全性 = min(两条链)。昂贵、需为每对链定制、对 PoW 尤其难。Rollup 官方桥是最纯粹的原生验证。
- 外部验证(一组人签名):安全性等于那组人,与两条链完全无关。 最常见,也损失最惨重。
- 乐观验证:1-of-N + 挑战期延迟。
- ⭐⭐ 历史上几起最大事故(Ronin 6.2 亿、Poly 6.1 亿、BNB 桥 5.7 亿、Wormhole 3.2 亿、Nomad 1.9 亿,⚠️ 均为涉案金额,最终损失因归还/暂停/兜底而低得多)的两个共同点:几乎全是外部验证型或原生验证的实现出错;没有一起是密码学被攻破。失败点集中在密钥管理和实现细节——系统在数学上成立,在工程上失守。
- 桥是最大攻击目标的四个原因:资产高度集中在一个合约、安全性等于最弱环节、复杂度极高、比它连接的链更新更少被审视。
- 一个有用的判断:桥锁着 10 亿而攻破只需 5 个私钥 ⟹ 这 10 亿的实际安全性等于那 5 个人的运维水平。
- ⭐⭐ 包装资产的二阶风险:它被用作 DeFi 抵押品 ⟹ 桥被攻破后借贷瞬间资不抵债 ⟹ 坏账波及从未碰过这座桥的用户。桥的风险通过组合性传染。
- “多链但非跨链”:没有桥时,51% 攻击的损害局限在那条链内;有桥时,攻击者可以在弱链上伪造存款并提到强链上。⟹ 桥让破坏面扩大到所有相连的链,整个网络的安全性被拉低到最弱那条链。
- 评估四问:属于哪一类;外部验证的话签名者是否真的独立(Ronin 的 9 个验证者不是 9 个独立实体);锁仓 vs 攻击成本;升级权与时间锁。
- “去中心化验证者网络"要追问:几个、谁运营、质押多少、作恶罚没吗。没有链上可执行的惩罚,它就只是多签的另一个说法。
思考题
- 为什么链 A 的合约无法直接读取链 B 的状态?这与第 1 讲的预言机问题是什么关系?
- 原生验证桥为什么"不引入额外信任”?它对链 B 的共识机制有什么要求?为什么 PoW 特别难?
- Rollup 的官方桥和一个普通的外部验证桥,信任假设差在哪里?请具体到"谁作恶会导致你损失"。
- Ronin 事件中密码学完全没被攻破。请说明它到底哪里失守了,以及"5/9 多签"这个描述掩盖了什么。
- Nomad 事件里"零消息根被设为可信"意味着什么?为什么会演变成公开哄抢?
- 一座桥锁着 5 亿美元,由 8 个验证者的 5/8 多签保护。请估算它的安全比,并说明你还需要哪些信息。
- 完整描述包装资产的连锁清算过程。为什么从未使用过这座桥的用户也会受损?
- 用"多链但非跨链"的论证,说明连接一条低安全性链的真实代价。这个代价由谁承担?
- 有人说"我们的桥有 21 个验证者,非常去中心化"。列出你要追问的所有问题。
- 设计一个尽可能安全的 ETH ↔ Cosmos 桥。说明你会选哪种信任模型、遇到什么困难、最终不得不接受什么假设。