一句话版本
你在界面上确认了"转 100 USDC 给 Alice",钱包签名并广播了一笔交易。但链上那笔交易真的是你确认的那笔吗?中间经过了网页、浏览器扩展、钱包软件,任何一环被篡改,签出去的都可能是另一笔。 "签名后核对"的做法是:拿到交易哈希后,从链上把这笔交易读回来,和当初的意图逐字段比对。不一致就立刻告警、锁定会话。这是"写完再读一遍"(read-after-write)这条古老工程原则在区块链上的应用。
全文分三层:
- 通俗理解:寄出去的信,再拆开看一遍
- 实际用处:数据库、支付对账、区块链交易
- 原理与工程要点:比对哪些字段、哪些差异可以接受、发现不一致之后怎么办
第一层:通俗理解
1.1 寄出去的信,再拆开看一遍
你让秘书帮你寄一封重要的信。秘书封好寄出了。你怎么知道他寄出的就是你写的那封?
如果你能从邮局那里把寄出的信调出来看一眼,就能确认。区块链恰好提供了这个能力:所有交易都是公开的,任何人都能按交易哈希把它读出来。
1.2 为什么不能只看签名前的界面
| 环节 | 可能出的问题 |
|---|---|
| 网页 | 被篡改,显示 A 地址,实际请求钱包签 B 地址 |
| 浏览器扩展 | 恶意扩展拦截并修改钱包请求 |
| 钱包软件 | 被替换成恶意版本 |
| 用户自己 | 在钱包弹窗里改了参数(比如手续费),或者点错了 |
签名前的核对,核对的是"界面上显示的东西";签名后的核对,核对的是"真正上链的东西"。
第二层:实际用处
- 数据库:重要写入之后再读一次(read-after-write),确认写入的就是想写的,尤其在多副本、最终一致的系统里。
- 支付对账:银行和支付公司每天把自己的账和清算机构的账逐笔比对,发现差异立刻调查。这就是"签名后核对"在金融业的版本。
- 区块链钱包:
- 交易被广播后,用交易哈希从链上取回交易,逐字段比对;
- 用两家独立的节点取回,防止单个节点撒谎(见《多源交叉验证》)。
- 软件发布:发布后从线上重新下载产物,比对哈希(见《Bybit事件与前端完整性》)。
Caloogy Wallet 也采用了广播后比对。
第三层:原理与工程要点
3.1 比对哪些字段
| 字段 | 必须一致 | 说明 |
|---|---|---|
from |
是 | 从哪个地址发出 |
to |
是 | 对 ERC-20 转账,这里是代币合约地址 |
value |
是 | 转出的 ETH 数量 |
input(calldata) |
是 | 对 ERC-20 转账,真正的收款人和金额编码在这里 |
chainId |
是 | 防止签到了另一条链(见《签名登录与防重放》) |
| gas 相关字段 | 允许在一定范围内不同 | 钱包通常允许用户调整手续费 |
注意第 4 项:ERC-20 转账时,to 是代币合约,真正的收款人藏在 calldata 里。只比对 to 会漏掉最关键的篡改。
3.2 哪些差异可以接受
钱包允许用户修改手续费,所以 maxFeePerGas、maxPriorityFeePerGas、gasLimit 不一致是正常的。但应当设一个上限:手续费被改到意图的好几倍,也应该视为异常(可能是"用天价手续费掏空余额"的攻击,或者只是用户误操作,都值得提醒)。
3.3 发现不一致之后
不一致说明签名链路上至少有一环不可信,处理要果断:
- 立即把这笔意图标记为异常;
- 结束当前会话,要求重新认证;
- 通过独立渠道(邮件、站内通知)发出高优先级告警;
- 记入审计日志(见《哈希链审计日志》)。
此时交易很可能已经上链,追不回来。签名后核对的价值不在于挽回这一笔,而在于:
- 第一时间发现链路被攻破,阻止下一笔;
- 给调查留下明确证据。
3.4 追踪交易的后续状态
交易广播后还可能出现几种情况,也都要跟踪:
| 状态 | 说明 |
|---|---|
| 已上链 | 读收据,确认执行成功(没有 revert) |
| 长时间未上链 | 可能手续费太低,或者被丢弃 |
| 被替换 | 同一个 nonce 上出现了另一笔交易。可能是用户自己加速或取消,也可能是有人拿到了私钥抢先发了一笔 |
"被替换"尤其值得警惕:如果用户没有做过加速或取消操作,同一个 nonce 却出现了另一笔交易,几乎可以肯定私钥已经泄露。
3.5 和"签名前核对"是互补的
| 签名前核对 | 签名后核对 | |
|---|---|---|
| 核对对象 | 界面显示的内容、模拟结果 | 链上实际的交易 |
| 能否阻止损失 | 能 | 通常不能(已上链) |
| 能否发现链路被篡改 | 不能(篡改者控制了界面) | 能 |
两者缺一不可。
总结
| 层次 | 要点 |
|---|---|
| 直觉 | 寄出的信再拆开看一遍 |
| 原则 | read-after-write;对账 |
| 字段 | from、to、value、input、chainId 必须一致;gas 有上限的容差 |
| 价值 | 发现链路被攻破、阻止下一笔、留下证据 |