Agave的ed25519和secp256r1预编译程序中存在一个bug,该bug在新版v2.2引入的--transaction-structure view
选项的验证器中被暴露。
agave 的 ed25519 和 secp256r1 预编译程序实现中的一个 bug 在使用 v2.2 中引入的新的 --transaction-structure view
选项运行的验证器中被暴露出来。预编译程序在其逻辑中存在一个 bug,它假设来自交易类型的交易指令数据始终是 2 字节对齐的。当使用 transaction-view 时,此假设不成立,因为 transaction-view 对单个指令的数据没有对齐保证。这导致使用 transaction-view 的区块生产节点为预编译指令返回错误,而验证区块的节点为该指令返回成功——最终导致 leader 进程因 bankhash 不匹配而退出。最初的不匹配于 4 月 9 日报告给 Anza,并在 4 月 11 日发布了修复程序。这代表了一种可用性损失 bug,可用于关闭使用 --transaction-structure view
选项运行的验证器。如果该选项的使用很普遍,则网络可用性将面临风险。此 bug 不会对资金构成任何风险。
agave 中 ed25519 和 secp256k1 预编译程序的实现使用 bytemuck
crate 将原始指令数据强制转换为对 Ed25519SignatureOffsets
或 Secp256r1SignatureOffsets
结构的引用:
// bytemuck 希望结构体对齐
let offsets: &Ed25519SignatureOffsets = bytemuck::try_from_bytes(&data[start..end])
.map_err(|_| PrecompileError::InvalidDataOffsets)?;
这些结构体具有 2 字节对齐——这意味着如果指令数据中结构体的地址不是 2 的倍数,则 bytemuck
会返回错误而不是引用。该错误会向上堆栈传播,并最终导致 Custom(3)
指令错误。在 solana-sdk
交易类型 SanitizedTransaction
中,每个指令的数据都存储在一个单独的 Vec<u8>
中,分配器 (jemalloc) 保证该向量至少具有 8 字节对齐。因此,预编译实现中的假设始终得到满足。
在 v2.2 中,agave 在区块生产中引入了一种新的零拷贝交易解析器:transaction-view。此结构体不反序列化数据包;相反,它保留原始数据包数据并缓存相关偏移量以访问各个字段。这意味着指令数据不再保存在具有对齐保证的唯一 Vec<u8>
中,而是通过偏移量访问序列化数据包中的指令数据。如果偏移量不是 2 字节对齐的,则有效的预编译签名将在 leader 节点上失败,并显示 Custom(3)
错误。
直到最近,预编译指令中的失败才被视为协议违规。然而,随着 epoch 760 中 feature 9ypxGLzkMxi89eDerRKXWDXe44UY2z4hBig4mDhNq5Dp
的激活(SIMD-0159),此类失败变成了常规交易错误。在此功能激活之前,transaction-view 中的未对齐问题会导致 leader 丢弃原本有效的交易。激活此功能后,leader 开始将失败的预编译签名交易包含在其区块中,并且网络会按预期接受它们。但是,leader 会看到不同的 bankhash,因为交易可能在 leader 上失败,但在集群的其余部分成功。
这代表了一个严重的可用性损失 bug。如果 agave v2.2 已经广泛采用 --transaction-structure view
,那么攻击者可能会提交专门设计的交易来远程和重复地使验证器崩溃。
为了修复此漏洞,ed25519 和 secp256r1 的预编译实现已更新为不假设任何对齐:
// SAFETY:
// - data[start..] 保证 >= Ed25519SignatureOffsets 的大小
// - Ed25519SignatureOffsets 是一个 POD 类型,因此我们可以安全地将其作为未对齐的结构读取
let offsets = unsafe {
core::ptr::read_unaligned(data.as_ptr().add(start) as *const Ed25519SignatureOffsets)
};
secp256k1 预编译指令使用 bincode
反序列化类似的偏移量结构,因此未表现出相同的漏洞。
2025 年 4 月 9 日下午 6:00 - Temporal 提醒 Anza,他们最近升级到 v2.2.7 的验证器中存在 bankhash 不匹配。这种不匹配表明他们的节点以不同于集群其余部分的方式执行了该区块。
2025 年 4 月 9 日上午 9:00 - Anza 工程师协助 Temporal 工程师发现了该 bug,并确定了一个在 leader 执行和重放之间具有不同状态的交易。差异是由于 Ed25519 SigVerify Precompile
指令在重放期间成功,但在 leader 节点上失败,并显示 Err(InstructionError(0, Custom(3)))
。此时,根本原因被确定。
2025 年 4 月 10 日下午 3:40 - 在集群 discord 频道中发布公告,建议运行 v2.2 的节点不应使用 --transaction-structure view
CLI 标志
2025 年 4 月 11 日上午 10:30 - #5765 合并到 master
2025 年 4 月 11 日上午 11:30 - #5768 合并到 v2.2
2025 年 4 月 11 日下午 3:30 - 发布了包含修复程序的 v2.2.8
- 原文链接: anza.xyz/blog/precompile...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!