解读 RFC0035: P2P 网络协议升级

CKB 计划于 2021 年进行第一次硬分叉升级,该硬分叉升级包含了一组校验规则的不兼容更新。然而,区块链是去中心化网络,我们不可能要求所有节点同时重启并升级客户端,甚至不可能要求所有节点都升级客户端。**如何将一组校验规则的不兼容更新部署到去中心化的区块链网络?**这有多种方式,本文仅讨论 CKB 在本次硬分叉采用的方式。

硬分叉与节点

首先,校验规则的更新,主要是针对主链而言。社区约定一个主链高度 H

  • 高度小于 H 的块必须满足旧的校验规则

  • 高度大于等于 H 的块必须满足新的校验规则

从节点的角度对待检验规则的更新:

  • 若节点的主链高度小于 H ,节点采用旧的校验规则来校验其收到的块、交易和其它网络信息

  • 若节点的主链高度大于等于 H ,节点采用新的校验规则来校验其收到的块、交易和其它网络信息。人们也常常把主链高度到达 H 称为激活分叉H 称为分叉点

然后,在实现上,我们知道,CKB v0.1 ~ v0.43 版本这些旧的客户端,并没有包含本次硬分叉的内容, 只实现了旧的校验规则;而在 CKB v0.100 版本的客户端里同时实现了旧的和新的校验规则。CKB v0.100 将 H 硬编码进客户端,约定在主链到达 H 之前节点采用旧的校验规则,H 之后则采用新的校验规则。

结合客户端版本和节点的主链高度,我们可以将节点作以下分类:

  • 使用 v0.43 及更旧的版本客户端的节点,简称 v0.43 节点

  • 使用 v0.100 及更新的版本的客户端,且主链高度小于 H 的节点,简称 v0.100-non-activated 节点

  • 使用 v0.100 及更新的版本的客户端,且主链高度大于等于 H 的节点,简称 v0.100-activated 节点

硬分叉与网络连通性

在真实世界中,激活硬分叉会导致原来的区块链网络分裂成两个相互独立的网络。对于硬分叉的部署和激活,对于网络连通性有下列三个要求:

  1. 在激活硬分叉前,即网络中只存在 v0.43 和 v0.100-non-activated 节点,保证原来的网络不分裂

  2. 在激活硬分叉后,即网络中存在 v0.43、v0.100-non-activated 和 v0.100-activated 节点,原来的区块链网络将分裂为两个独立的网络,分别对应到新旧规则

  3. 保证所有的 v0.100-non-activated 节点和 v0.100-activated 节点同处于新规则网络

硬分叉与 p2p 协议

终于来到了本文的最初目的,介绍 RFC0035。

上述三个对网络连通性的要求,将由 p2p 协议层来负责。接下来阐述 p2p 协议层的具体是如何做到的:

  • v0.100 的客户端实现了两套 p2p 协议,按协议版本号区分,p2p-v1 和 p2p-v2。节点在激活前,同时开启 p2p-v1 和 p2p-v2;节点在激活分叉后,关闭 p2p-v1,只保留 p2p-v2 协议

  • v0.1~v0.43 的客户端,只开启了 p2p-v1(也只存在 p2p-v1 的代码,毕竟过去的代码还不包含 p2p-v2)。

p2p-v1 和 p2p-v2 除了版本号外,其内容几乎相同(后面会谈到不同的地方)。那为什么要对内容几乎相同的网络协议做版本号的区分呢?

目的就是为了实现前面所说的的三个目标:

  1. 激活分叉前,网络中只存在 v0.43 和 v0.100-non-activated 节点,所有节点能通过 p2p-v1 组网通信,即保证网络不会分裂

  2. 激活分叉后,v0.100-activated 节点关了 p2p-v1,所以 v0.100-activated 节点和 v0.43 节点无法通过相同版本的 p2p 协议来组网通信,即保证原网络分裂

  3. 激活分叉后,v0.100-activated 和 v0.100-non-activated 都开启了 p2p-v2,能通过 p2p-v2 组网通信,即保证 v0.100-activated 和 v0.100-non-activated 节点同处于新规则网络

p2p 协议的改动

最后我们通过对比 p2p-v2 与 p2p-v1 的异同,介绍本次硬分叉对 p2p 协议的改动。

我们知道,CKB 的 p2p 协议层共包含以下子协议: Identify , Ping , Feeler , DisconnectMessage , Time , Alert , Discovery , Sync , Relay

  1. 对于 Identity, Ping, Feeler, DisconnectMessage, Time, Alert 子协议,p2p-v1 和 p2p-v2 的内容完全相同

  2. 对于 Discovery 子协议,p2p-v2 微调了协议的信息的编码方式,减少了一点编解码的开销

  3. 对于 Sync 子协议,p2p-v2 调大了批量同步区块的限制参数,由 16 调大至 32,加速区块同步速度

  4. 对于 Relay 子协议,p2p-v2 改动稍微多一点

    Relay 子协议的一个重要功能是广播新鲜交易,节点通过 Relay 广播新鲜交易时,会在广播信息里带上执行该交易所话费的 VM cycles。若本地验证交易所花费的 cycles 与对端的广播信息所携带的 cycles 字段不一致,就判断对端为恶意节点并断开连接。

    而本次硬分叉引入了新版 VM(详见 rfc31, rfc32, rfc33),对于一个相同的交易,在新旧版本 VM 上执行所花费的 cycles 并不一致。为此,p2p-v2 在 Relay 广播信息增加了执行交易的 VM 版本号,来告知 cycles 所对应的 VM 版本。

    前面说到 CKB v0.100 在激活分叉前同时开启 p2p-v1 和 p2p-v2,这么说其实不太准确,因为有 Relay 这个特例,实际上,分叉激活前的节点只开启 p2p-v1 的 Relay 子协议,而分叉激活后同样也是关闭 p2p-v1 并开启 p2p-v2 的 Relay。

参考

2 Likes