更多资源
回滚机制

回滚机制#

ord节点的主要功能是按照 ordinals 协议将 Bitcoin 的交易数据解析为铭文,但由于 Bitcoin 的共识协议是最终确定性的 POW,因此可能因为区块重组而导致数据回滚。而当发生区块回滚时,ord 节点对于回滚区块的解析数据已经写入磁盘,且没有办法清理因区块回滚而失效的数据,因此 ord 节点将不能继续解析区块,只能停留在某一高度。

回滚功能重要性#

如果 Bitcoin 节点在 9999 高度出了一个区块 00000000000000000005ae2d26e36788a3f4f2770495c5c6cf2e2e75cf8ec33c,但因为后续又出现了一条更长的链,其在9999高度的区块为 0000000000000000000266ef9c0057fa9ca62f4d1e701070e3025a217829b3c1,那么 00000000000000000005ae2d26e36788a3f4f2770495c5c6cf2e2e75cf8ec33c 这个区块里的数据就不再有效,ord 节点解析该区块而产生的数据都需要删除,否则后续的铭文数据都会发生混乱。

  而由于 ord 节点为了保证铭文数据是最新的,会实时解析最新高度的区块并写入磁盘,当发生区块回滚时,清理失效数据的唯一方案就是重新从头解析一遍所有区块。或者我们可以定期备份数据,发生回滚时可以停掉ord节点,然后从备份数据重新同步,但显然这并不是一个完美的解决方案。如果能够自动化完成该过程,这将会是一个令人满意的方案。

回滚实现原理#

  为了能够实现自动数据回滚,我们引入了 redb 的 savepoint 功能,可以理解为一个内存级别的数据备份。因为理论上 Bitcoin 的回滚最多不会超过6个区块,因此可以每 3 个区块制作一个 savepoint,并至多保留 4 个 savepoint,这样至少可以备份到 10 个高度之前的数据。具体流程如下:

  1. 节点启动时首先制作一个 savepoint。

  2. 检查db中保存的区块高度 n,并向Bitcoin节点请求高度为 n+1 的区块。

  3. 每当查询一个高度为 n 的新区块时,通过对比 block{n}.header.prev\_blockhash 与 block{n-1}.hash 是否一致。若一致则进入步骤d,否则说明发生了区块重组,进入步骤e。

  4. 若当前高度为 3 的倍数,则制作一个 savepoint。若当前已制作的 savepoint 个数大于 4 ,则删除最老的 savepoint。

  5. 用最新的 savepoint 恢复数据,然后回到步骤 b 。

由于 ord 节点只有同步到 Bitcoin 节点的最新高度时才有可能遇到区块重组的问题,因此引入了一个fast-sync模式的判断。当 ord 节点落后 Bitcoin 节点超过 10 个区块时,此时认为 ord 节点处于fast-sync模式,为了尽快追到最新高度,并不会制作 savepoint。

回滚功能的启用方法#

在开发时,数据回滚被视为ord节点一个独立的 feature,因此应当通过 Rust 特性参数--features=rollback来启用,当不配置该参数时,回滚功能不会起作用。