藏川线前段

--- 摄于 2017 年 9 月 藏川线前段

CKB hardfork features(三)

上篇说到 VM 版本的变化,这篇来讲讲网络协议相关的改动,这是保证 fork 升级最基础的一步,需要让节点在网络不断开的前提下平滑通过 hardfork 的关键时间点,对于一个 p2p 应用来说,有很多需要考虑的地方。

问题所在

  1. 包含 hardfork 版本的客户端必须兼容之前所有版本实现,并且在走过 hardfork 时点后,主动断开所有旧版本客户端的连接,并永久拒绝任何旧版本客户端的连接
  2. 由于不同版本的 VM 对同一个 script 的执行可能得出不同的 cycles,必须以 VM 切换为时点,清理不符合的验证版本,让它不会在网络中传播导致节点被 ban
  3. 考虑到新块广播是以 gossip 方式在网络上传播的,势必会存在一个时点网络上的节点处于半分裂状态,即有些跨过了 hardfork,有些还没过去,对于有能力跨过但尚未跨过的客户端,需要让它有能力有空间同步上来,而不是当成无效节点断开连接
  4. 对于临时加入的有能力跨过 hardfork 的客户端,不能因为 hardfrok 已经过去了很久而拒绝它
  5. 动态切换过程中,不能因为任何原因导致分裂

方案及实现

RFC:https://github.com/nervosnetwork/rfcs/pull/234

PR:https://github.com/nervosnetwork/ckb/pull/2796

在 eth 网络中,如果要 hardfork,那么在握手阶段,需要用类似 flag 的实现区分开,并且永久保留在实现里面(咱理解应该没啥问题),但在 ckb 中,咱不得不夸一下两年前花了一点功夫实现的网络库 —— Tentacle。在实现网络库的时候,就考虑到了多版本协议兼容的问题,并且还保留了随时用旧协议替换新协议的能力,用多路复用来支持多协议,虽然这两年以来这些功能并没有真正意义上发挥作用,但,在 hardfork 这个时点,它终于派上用场了(有点欣慰

ckb 的网络协议林林总总加起来大概有七八个,每一个都可以独立打开,虽然如果不开核心协议 sync 的连接会定时被清理,但它终究是赋予了可以单独开任何协议的可能性,为了兼容旧客户端并彻底堵死 hardfork 之后被旧客户端连接的可能性,所有协议都必须在这次变化中以兼容模式升级版本,即 hardfork 版本下支持打开版本 1,2 协议,当 hardfork 时点过去后,ckb 将再发一个版本,清理掉这些兼容代码,用一种非常清爽的方式将网络的冗余代码删除。

唯一特殊的升级在于 relay 协议,这个协议涉及到交易广播,因为 VM 版本不同而导致 cycles 可能不一致,那么单纯的兼容升级就无法使用了,因为节点无法保证对端状态是否与自己一致,如果不一致,交易广播的行为就可能导致网络分裂,于是需要一种相对复杂的方式升级,即同时挂载两个行为互斥的 relay 协议,严格限制他们互斥的使用时间点,让处于任何时点的客户端只能接到对应时点的交易,避免网络分裂问题。

小结

到此,几个代码量相对比较大的改动就说完了,剩下的虽然改动相对较小,但复杂程度其实并不低,只是复杂的地方代码无法体现罢了(摊手.jpg

评论区

加载更多

登录后评论