在链上世界里,把一笔交易从签名到广播到归档完整串起来的,是那串看着头皮发麻的十六进制。钱包界面再花哨,节点收到的都是这一串字节;区块浏览器把它拆开显示,也只是替你按顺序解析了一遍。看懂它的骨架,比记住任何具体数字都有用,因为骨架变了才有风险,字段名换了都只是皮。
为什么十六进制是最后的通用形态
一笔交易在被签名之后,就固化成一段不可改动的字节序列。广播时通过 eth_sendRawTransaction 交给节点,节点验签后放进交易池;之后不管经过多少个节点、被哪家浏览器展示,它都必须还原成同一串字节、同一个哈希。这条性质也是很多场景的基础:离线签名把签名结果交回联网机器、交易被多个通道重复广播、故障时手工重发同一笔交易,靠的都是”签名即封版”。反过来说,签完之后你能改的只有怎么发,不能改发什么。
信封规则:类型字节决定后面怎么拆
EIP-2718 给交易定了统一的信封:TransactionType || TransactionPayload。类型字节排在最前,告诉解析方后面的负载该按哪种结构拆,并且规定有效的类型值不超过 0x7f。这条上限不是随手写的——旧式(未加类型前缀)的交易首字节一定大于等于 0xc0,两者在字节层面天然不重叠,老节点遇到不认识的类型字节会明确拒绝,而不会按旧格式误读一段它其实看不懂的字节。这就把”加了新类型会不会让老节点读错”这件最危险的事挡在了解析层之外。
常见的两种类型值得记住位置:
- 类型
0x01(EIP-2930):在原本那组字段之外多带一份访问列表,把交易打算读的地址和存储槽提前声明。列表里的地址和键要预付固定费用,列表外的访问照样允许,只是单价更高。它的价值在于费用更 predictable,以及给一些链下验证、批量打包的工具提供更清楚的读取边界,不是普通转账的必需品。 - 类型
0x02(EIP-1559):用两个上限字段取代过去的单一费率字段——一个是你愿意为每单位 gas 付的总上限,另一个是其中愿意额外给打包方的优先费,实际成交价由当个区块的费用市场决定。字段序列里还包含访问列表位,即使你没用到列表,解析时的位置也要留着。
怎么确认你手上那串是哪一种
不要只靠肉眼数长度。稳妥的做法是双源交叉:先用能解析交易类型的区块浏览器或 RPC 查出这笔交易的类型字段,再对照同一哈希的原始字节串首字节。如果页面显示的是 0x02 而原始串开头也是 0x02,两者互相印证;对不上时先怀疑自己拿错了串(比如误把交易回执或输入数据当成了整笔交易),而不是怀疑网络出问题。浏览器域名和双源核验的做法在 假区块浏览器怎么骗人?域名核验与双源交叉验证 里讲得比较细。
顺带区分三个容易混的十六进制:交易哈希是这笔交易的摘要,短得多;输入数据字段只是发给合约的调用载荷,拆开方式和整笔交易完全不同,详见 交易的输入数据字段怎么读:四字节选择器、参数槽位与解不出来的情况;回执是执行结果,属于另一套结构,里面还有 gas 用量与日志。三者形状相似,含义完全不同层次。
手搓原始交易的三个坑
第一,把字段顺序按界面顺序填。界面是给人看的,字节序列是按类型定义排的,错一格就等于签了另一笔交易。第二,把上限字段当成实际会付的钱。上限只是保险封顶,实际结算用多少由 gas 用量和成交价决定,填高不会加速,填低则可能在费用不够时直接失败或长期无人打包。第三,以为链标识字段无关紧要。它正是防止同一签名在两条链上被重放的关卡,去掉它就等于把这笔签名交到任何重放它的人手里。
普通用户不需要手搓交易,但有几种场景值得看懂:核对离线签名交回联网机器的结果是不是同一笔、比对替换交易与原交易的差别只在费率、以及在广播报错时判断是被拒还是重复提交。理解这些结构,判断依据就从”看起来一样”变成”字节一致”。所有涉及真实资产的操作都有风险,本文只讲交易结构与核验方法,不涉及任何收益预期或买卖建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。