跳转到正文
buybitcoinsmart

术语表 /挖矿与共识

序列化区块

序列化区块是什么?
序列化区块是区块在网络传输或磁盘存储时所呈现的确切字节串:80字节的区块头,一个交易数量,然后是按顺序排列的每一笔交易。

规定于 BIP-144。

序列化是把抽象的区块转换为可以计算哈希、发送和存储的形式的过程。创世区块序列化后为285字节:区块头80字节,交易数量1字节,其唯一的币基交易204字节。如果您曾把原始十六进制数据粘贴到区块浏览器中,或以 verbosity 0运行过 getblock,您看到的就是它。

运作方式

序列化区块由三部分首尾相接组成,只有第一部分的长度是固定的。

区块头始终为80字节,顺序如下:4字节的版本号、32字节的前一区块头哈希、32字节的默克尔根、4字节的时间戳、4字节的 nBits 目标编码,以及4字节的随机数。接下来是交易数量,以 compactSize 写入,这是一种可变长度整数,计数小于253时占1字节,数值极大时最多占9字节。然后是交易本身,每笔都完整序列化,币基交易排在最前。

自 BIP144 起,同一个区块有两种合法的序列化形式。精简形式完全不含见证数据,是2017年之前的软件所期望的格式。完整形式则包含见证数据,并在原本应为输入数量的位置,用一个0x00 字节后接一个0x01 标志字节,标记每笔携带见证数据的交易。两种形式编码的是同一个区块,也产生相同的区块哈希,因为哈希只涵盖那80字节的区块头,而其中的默克尔根所承诺的是交易 ID,交易 ID 由精简编码计算得出。这种分离正是隔离见证(segregated witness)的字面含义。

有一个习惯会让每个人至少出错一次:多字节整数以小端序写入,因此时间戳0x495FAB29 在网络上显示为29 ab 5f 49,而哈希的显示顺序与其序列化字节顺序相反。您从区块浏览器中复制的区块哈希,并不是文件中实际存放的字节序列。

在哪里会遇到它

序列化区块在点对点网络中通过 block 消息传输。每条消息首先带有24字节的消息头:4字节的起始字符串(主网为 f9beb4d9)、12字节的命令名、4字节的负载长度,以及4字节的校验和,校验和取自对负载进行双重 SHA-256运算结果的前四个字节。Bitcoin Core 将单条消息的负载上限设为4,000,000字节,这是网络限制,而非共识限制。

同样的字节也会存入您的磁盘。Bitcoin Core 将区块追加到名为 blk00000.dat 及后续编号的文件中,每个文件上限为128 MiB,使用相同的起始字符串,并在每个区块之前加上长度前缀,以便线性扫描文件。创世区块是例外:它作为常量编译在软件中,而不是通过下载获得,这使它成为同步中的节点衡量其他一切的锚点。

在日常使用中,序列化数据会出现在 verbosity 0的 getblock RPC 调用中、大多数区块浏览器的原始数据或十六进制标签页中,以及可以手动解码区块的工具里。任何想核实区块浏览器所述是否属实的人最终都会来到这里,因为十六进制数据是唯一没有被任何人重新格式化过的表示形式。

序列化区块 vs 区块

区块是对象,序列化区块是它的一种编码。这一区分在2017年之前只是形式上的,那一年 SegWit 使每个区块有了两种长度不同的有效编码,于是区块大小成了一个需要限定说明的问题。Bitcoin Core 在一次 RPC 响应中用三种方式作答:size 表示完整序列化的大小,strippedsize 表示不含见证数据的大小,weight 则是规则实际执行的数值。

请勿混淆

常见问题

为什么一个区块有两种不同的大小?

因为 SegWit 使每个区块有两种有效的序列化形式。精简形式省略见证数据,完整形式包含见证数据,所以 Bitcoin Core 对同一个区块分别报告 size、strippedsize 和 weight。

区块哈希是对整个序列化区块计算的哈希吗?

不是。它只是对80字节区块头进行的双重 SHA-256运算。交易通过该区块头中所承诺的默克尔根被间接涵盖。

相关术语

挖矿与共识中的更多术语

阅读本页英文版