术语表 /节点与软件
起始字符串
又称 Start string。
- 起始字符串是什么?
- 起始字符串是每条比特币网络消息开头的四字节前缀,在读取任何其他内容之前,它会表明发送方所在的网络。
四个字节可以防止比特币的各个并行网络之间意外互相通信。主网使用 f9beb4d9,回归测试网(regtest)使用 fabfb5da,节点读到意料之外的值时,会丢弃该消息,通常连连接也一并断开。这项检查针对的是配置错误,而不是攻击者,因为任何人都可以发送正确的四个字节。
运作方式
起始字符串占据消息的第0至第3个字节,节点会在为后续内容分配内存之前先对其进行检验。
Bitcoin Core 为每条链在代码中写死了一个值。主网是0xf9beb4d9。Testnet3 是0x0b110907。Testnet4 随 BIP94 一同加入 Bitcoin Core 28.0,其值为0x1c163f28。Regtest 是0xfabfb5da。Signet 是个有趣的特例:它的四个字节不是常量,而是对挑战脚本进行哈希运算得出的,该脚本规定了谁可以为该 signet 的区块签名,因此公共的默认 signet 与您为测试而自行搭建的私有 signet 会自动拒绝彼此通信。
这些值并不是为了好看而挑选的。它们是在普通数据流中不太可能出现的字节序列,因此客户端在读取损坏或失去同步的 TCP 数据流时,可以向前扫描,直到再次找到该模式,并从该处继续,而不必丢弃所有内容。
同样的四个字节也会写入磁盘。在存放原始区块的 blk00000.dat 文件中,每个已存储的区块前面都有其所在网络的起始字符串和一个四字节的长度。正是这种分帧方式,使节点能够遍历一个尚未写完的区块文件,找到记录之间的边界,并且只丢弃被截断的尾部,而不是整个文件。
在哪里会遇到它
只要是检查比特币流量而不仅仅是使用它,就会遇到起始字符串。
在端口8333上打开一份抓包记录,会话中的每一帧都以 f9 be b4 d9 开头。协议分析器正是依据这一特征来标记流量。每个派生自该代码库的项目,都把修改这四个字节作为最先做的事情之一,这也是为什么各个分叉项目即使握手流程在其他方面完全相同,也无法互相连接。
对普通用户来说,它只会出现一次,表现为一种毫无提示的沉默。如果把为测试网配置的钱包指向主网节点,既没有报错,也没有拒绝通知,更没有连接:节点读到四个无法识别的字节,丢弃该消息,最终断开该对等节点。当节点和钱包彼此看不到对方时,首先要检查的就是两端是否处于同一网络。
起始字符串 vs 消息头
起始字符串是一个字段;消息头则包含全部四个字段。消息头共24个字节,依次由起始字符串、十二字节的 ASCII 命令名、四字节的有效载荷长度和四字节的校验和组成。起始字符串说明是哪个网络,命令说明是哪种消息,长度说明还要读取多少内容。人们指消息头时常常把这两个名称混用,而在十六进制转储中计算字节偏移量时,这种混用尤其容易造成混淆。