同一个哈希为什么有两个样子:比特币交易与区块哈希的字节序 图 1
同一个哈希为什么有两个样子:比特币交易与区块哈希的字节序 · 图 1

同一笔比特币交易,在区块浏览器的地址栏里是一串十六进制字符,在某些底层工具的原始输出里却是同一批字符倒着排列——两个“哈希”都对,只是一个用了显示顺序,一个用了内部顺序。第一次遇到的人常以为自己复制错了,其实是比特币的字节序约定在起作用。

两种顺序各用在哪里

比特币的交易哈希和区块哈希,都由 SHA256 哈希函数算出一串字节。这串字节按哈希函数原样输出的排列,可称“自然顺序”;把字节序列整体倒序后显示,可称“显示顺序”。约定是:区块和交易的原始数据结构内部引用彼此(比如区块头里的前一块哈希、交易输入里引用的前一笔交易)用自然顺序,而对外显示、搜索、RPC 输出用倒过来的显示顺序。当年中本聪为了让区块哈希显示时前面能出现一串零、看起来更符合人类写大数的习惯,做了这个反转,此后成为惯例。

结果是两个日常现象。其一,在原始交易数据里搜 TXID 搜不到,把每两字符为一组、按字节倒序翻转一遍就能对上;区块头里的前块哈希看着像“尾巴上一堆零”,也是同一原因。其二,你在浏览器里能查到的哈希,直接塞进某些解析原始文件的脚本会报“不存在”。以太坊没有这个约定:Keccak 输出的十六进制一般原样显示,不存在“换地方就对不上”的问题,所以这个坑基本只在比特币工具链出现。

手工翻转的正确姿势

常见错误是把整串字符直接反转。哈希的十六进制表示里每两个字符代表一个字节,正确做法是以两字符为一组、把组的先后顺序倒过来,组内两字符不动。以创世区块为例,哈希函数原样输出以 6fe28c0a 开头,按字节倒序后变成著名的 000000000019d668 开头——前块哈希那种“前面一堆零”的观感正是这么来的。用脚本处理时,先按每两字符切组、再倒序拼接即可;只写一个字符串倒序的写法会连组内顺序一起翻,得到错误结果。

什么场景会真的撞上

三类场景最常见。第一,自己写脚本解析区块文件(找输入引用的前一笔交易、核对默克尔树中间节点),拿到的哈希与浏览器对不上:先做字节倒序再比对。第二,用 RPC 或浏览器查到的哈希拿去喂某个声称“接收原始哈希”的工具得到空结果:先确认工具期望哪种顺序,两个顺序各试一次。第三,对账时发现同一交易出现“两个哈希”:先排除重组等真实分叉情况;若两串只是互为倒序,那它们是同一笔交易的两种写法,不是两笔交易,更不是被篡改的痕迹——把其中一串按字节翻转后与另一串完全相等,即可当场结案。

边界与习惯

字节序约定是工具层习惯,不改变交易本身:签名、金额、输入输出在任何一种顺序下都是同一份数据。日常用户不需要手工翻转任何东西,钱包和浏览器已经统一用显示顺序;需要动手的往往是开发者、对账脚本和数据分析。给脚本作者的实用建议是:所有对外展示与查询统一转显示顺序,所有文件内引用保持自然顺序,函数命名里写明“rev”,避免半年后自己也踩。比特币交易在浏览器中的常规读法,可参考 比特币区块浏览器哪里不一样;交易哈希的基本查询路径见 交易哈希怎么查

理解这两种顺序也能省掉大量“数据被篡改了”的虚惊。还有一条实用提醒:闪电网络通道数据、部分索引器与数据库导出格式对哈希采用哪种顺序各有说明,接入新工具前先花一分钟查它的字段文档,比事后怀疑数据被改动便宜得多。数字资产操作存在风险,本文只解释数据表示约定,不构成投资建议。