跨链桥如何工作?以 Wormhole 为案例(第四部分)

  • Sec3dev
  • 发布于 2023-01-18 22:59
  • 阅读 38

本文深入探讨了 Wormhole 如何防止 VAA 重复攻击,确保每个 VAA 只能成功使用一次。文章详细介绍了在 Solana 和 Ethereum 上的实现机制,包括如何利用全球标记保持已完成的 VAA 的唯一性,从而防止恶意用户通过重复使用相同 VAA 来窃取代币。

第 1 部分 第 2 部分 第 3 部分 之后,本文着重解释 Wormhole 如何防止 VAA 重放攻击(即,同一消息在目标链上永远不能被交付两次)。

这是非常重要的,因为否则恶意用户可能通过多次以相同 VAA 赎回从而盗取代币。

如何防止相同消息的双重交付(VAA 重放)?

本质上,每个成功赎回的 VAA 都必须在全局范围内被记录,方法是保持一个链上标志,指示该 VAA 已经被赎回。

任何尝试重用被 is_already_redeemed 标记的 VAA 的交易都会被拒绝。

接下来我们将解释这如何在 Solana 和以太坊上实现。

在 Solana 上,最终消息交付功能 (complete_native 和 complete_wrapped) 都采用输入 PDA 账户 claim,并利用它来防止 VAA 双重签名:

pub claim: Mut<Claim<’b>>,

在调用时,claim 账户必须未初始化:

pub type Claim<'a> = Data<'a, ClaimData, { Uninitialized }>;
// 未初始化

consume 函数被调用以初始化并检查 claim 账户的有效性:

claim 账户是由 emitter_address、emitter_chain 和 VAA 中的序列确定的 PDA:

claim 账户有一个标志 claimed,在初始化后被设置为真 ( line 87 ):

通过上述方法,Wormhole 确保每个具有唯一组合的 VAA(emitter_address、emitter_chain 和 sequence)创建一个唯一的 claim 账户,该账户只能成功使用一次。

在以太坊上,Wormhole 同样维护一个全局映射 completedTransfers,用于存储所有完成的 VAA 哈希:

mapping(bytes32 => bool) completedTransfers;

VAA 哈希是对 VAA 字节(不包括守护者签名)进行的 keccak256 哈希:

确保即使守护者不同,每个 VAA 哈希对同一消息都是唯一的。

在每次消息交付调用中,它会检查 VAA 哈希是否已经标记( isTransferCompleted line 497),如果是则中止,否则将传递该消息并标记哈希( setTransferCompleted line 498)。

在上述内容中,_state.completedTransfers 是全局存储中的映射,必须在每次成功的消息传输中更新:

// 消耗的代币转账的映射
mapping(bytes32 => bool) completedTransfers;

请注意,在以太坊上,全球存储操作 (SSTORE) 会产生最大的 Gas 成本。这解释了为何赎回代币是昂贵的。例如,在以下交易中,调用 completeTransfer 的费用为 $6.81 (270K gas):

以太坊上 “代币赎回” 交易

  • 原文链接: sec3.dev/blog/bridges4...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Sec3dev
Sec3dev
https://www.sec3.dev/