跳转到正文
buybitcoinsmart

术语表 /开发者参考

内部字节序

内部字节序是什么?
内部字节序是比特币在序列化结构内部使用的排列方式:整数按最低有效字节在前的顺序写入,哈希摘要则按 SHA-256生成的顺序写入。

一个名称之下包含两种约定。交易或区块头中的每个整数字段都采用小端序,因此版本号2写作02000000,而每个32字节的哈希在原始数据中的排列,与哈希函数输出时完全一致。面向用户的工具在打印这些哈希之前会将其反转,这是手写解析器的结果与区块浏览器不一致的最常见原因。

运作方式

学习内部字节序,最好的办法是拆解80字节的创世区块头,因为其中每个字段都足够小,可以直接目测核对。

区块头以01000000开头,即版本号1,用四个小端序字节表示。接着是32个零字节,因为第一个区块没有父区块。然后是默克尔根,存储为3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a,这个摘要在每个区块浏览器中都显示为4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b,即逐字节倒序书写的结果。接着是29ab5f49,即时间戳1231006505,对应2009年1月3日 UTC 18:15:05。接着是 ffff001d,即难度字段,其逻辑值为0x1d00ffff。最后是1dac2b7c,即随机数2083236893。

金额遵循同样的规则。1个比特币等于100,000,000聪,恰好支付该数额的输出带有8个字节00e1f50500000000。

其原因出于历史,也相当平常。比特币是为 x86 机器编写的,这类机器按最低有效字节在前的顺序保存整数,最早的代码便按处理器已有的排列方式写出结构。哈希则从未被反转过。改变的是打印方式,因为 Bitcoin Core 将摘要存放在一个把它当作一个巨大数字处理的类中,而数字打印时最高有效部分在左边。

在哪里会遇到它

每当工具给您的是原始字节,而不是格式化后的结果,您得到的就是内部字节序。

使用 getrawtransaction 且不带 verbose 标志获取交易,或使用 getblockheader 并将 verbose 设为 false 获取区块头,其中的所有内容都按此顺序返回。硬件钱包导出的 PSBT、区块浏览器原始数据标签页背后的十六进制内容,以及节点 blocks 目录中的区块文件,也是如此。

最容易让人出错的字段,是每个输入开头的 outpoint。它用32个字节指明被花费的交易,这些字节读起来与区块浏览器所显示的标识符正好相反。这两个字符串不一致时,并不意味着数据损坏:将其中一个反转,两者便一致了。

内部字节序 vs RPC 字节序

内部字节序和 RPC 字节序描述的是同样的32个字节,只是方向相反,两者之间的转换规则有一个重要的例外。哈希摘要在输出给用户时要反转,再输入回来时要再次反转。整数则不然。区块高度、时间戳和以聪为单位的金额,都以普通十进制数字呈现,在输入或输出时反转其中任何一个,只会得到错误的值,而不是写法不同的同一个值。只反转哈希,其他一概不动,大多数字节序错误便会消失。

请勿混淆

常见问题

为什么原始交易中的哈希看起来是反的?

它们并没有反,打印出来的版本才是反的。摘要按 SHA-256生成的顺序存储,而显示工具会将其反转,因为 Bitcoin Core 把哈希视为一个大数,并先打印最高有效部分。

解析原始比特币数据时,需要反转每个字段吗?

不需要。整数是小端序,按小端序读取即可,只有32字节的哈希才需要反转,而且仅在要与区块浏览器或 RPC 调用显示的内容比对时才反转。

接着阅读

相关术语

开发者参考中的更多术语

阅读本页英文版