术语表 /开发者参考
MSG_CMPCT_BLOCK
- MSG_CMPCT_BLOCK 是什么?
- MSG_CMPCT_BLOCK 是编号为4的清单类型,是仅用于请求的代码:它从不出现在通告中,只能用于发送给事先已同意使用它的对等节点的 getdata 消息。
规定于 BIP-152。
紧凑区块是协商使用的,而非通告使用的。对等节点发送一次 sendcmpct 消息,表示将接受紧凑区块,此后对方才可以用类型4而不是类型2来响应新区块。BIP152 随 Bitcoin Core 0.13.0于2016年8月推出,其节省的开销正是全部意义所在:用六个字节指明接收方已经持有的交易,而不是将其重复传送一遍所需的两百个字节或更多。
运作方式
MSG_CMPCT_BLOCK 请求的是区块的描述而不是区块本身,只有当两个节点的内存池相近时,这份描述才有价值。
首先是协商。sendcmpct 消息包含一个标志和一个版本号:版本1按 txid 标识交易,版本2按见证 txid 标识交易,自隔离见证启用以来只有这一版本在使用。节点绝不能在发给未发送过 sendcmpct 的对等节点的 getdata 中放入类型4,因为该对等节点没有义务理解它。
回复是一条 cmpctblock 消息,其中包含80字节的区块头、一个八字节的随机数、每笔交易对应的一个六字节短标识符,以及少量完整提供的交易,其中始终包括 coinbase 交易,因为接收方不可能已经见过它。短标识符由 SipHash 生成,密钥取自区块头和该随机数,因此每个区块、每次请求的短标识符都不相同。这种随机化是一种防御措施:若采用固定方案,攻击者就可以预先计算出两笔相互冲突的交易,从而同时阻碍全网的区块重建。
接收方将这些标识符与其内存池进行匹配,用 getblocktxn 请求缺失的交易,并在本地重建区块。之后的验证与通常的验证无异,也不涉及任何共识规则。
深度是有限制的。Bitcoin Core 只为最近的五个区块提供紧凑区块,对更早区块的请求则以完整区块作答,因为落后这么多的接收方没有可用的内存池,最终会请求区块中的每一笔交易。
在哪里会遇到它
查看 MSG_CMPCT_BLOCK 最清楚的方式是 Bitcoin Core 自身的日志,它会报告每次重建的完成情况。
使用 -debug=cmpctblock 启动节点后,每个新区块都会生成一行记录,说明预填充了多少笔交易、在内存池中找到了多少笔、必须另行获取多少笔。在已运行数小时的机器上,需要获取的数量通常为零,区块到达时只有数十千字节,而不是一点五兆字节。一个包含3,000笔交易的区块,需要18,000字节的短标识符,外加区块头和 coinbase 交易。
这一计算在刚启动的节点上就不成立了。内存池为空意味着每个标识符都无法匹配,后续请求要求获取整个区块,多出的一次往返使紧凑区块的路径比直接请求区块更慢。这就是为什么该代码属于处于链端的节点,而从不出现在初始同步期间。
对于在家中运行节点的人来说,这项功能决定了普通网络连接能否跟上网络的节奏,还是每次出块时都会落后。