Skip to main content

Conflux 区块链数据同步指南

在某些应用场景下如区块链浏览器,需要将链上的区块信息重新写入链下数据库,便于快速查询索引以及聚合分析等操作。通常获取区块链数据的做法是搭一个全节点,然后调用全节点的 RPC 方法获取数据。当然也有别的方法,比如直接解析全节点数据库,这些方法技术难度更大,需要对区块链原理以及区块链数据的存储结构有深入理解,这里不做讨论。

Conflux 具有比 Ethereum 更复杂的特性,如出块时间短,可达到秒级出块;挖矿交易延迟执行等,关于更多 Conflux 特性可参考开发者文档或者白皮书。这对如何保证原子性地同步获取最新的区块提出了更多的挑战。以下是我们结合 Confura 数据同步实践过程中总结的一些经验教训,罗列的一些技术要点,希望能对社区开发者有所帮助。

Target 同步高度

因为 latest mined epoch 打包的交易并不会被立即执行,所以合理的数据同步方式是按照 latest state epoch 或者 latest confirmed epoch 高度进行同步。由于 latest state epoch 发生 pivot chain reorg 的概率比较大,建议使用 latest confirmed epoch 做为同步高度获取数据,减少频繁删除数据产生的性能损耗及实现复杂度。

获取频率

为了最大程度获取最新区块及减少无效 RPC 请求,可根据当前同步的 epoch 高度,动态设置 RPC 请求抓取频率:

  • 如果当前同步 epoch 高度 < target 同步高度 , 当前为 catch-up mode, 抓取频率可设置为毫秒级(可根据实际抓取效果设置)。
  • 如果当前同步数据已追平 target 同步高度,抓取频率可设置为出块时间如 1s。

获取过程

以下详细描述抓取单个 epoch 区块数据的流程步骤及调用的 RPC 方法。

a. 获取 epoch 下 block hash 列表

通过 cfx_getBlocksByEpoch 获取 epoch 下的 block hash 数组,数组中最后一个元素即为 pivot block hash。

b. 根据 block hash 获取 block/transaction 数据

通过 cfx_getBlockByHashWithPivotAssumption 获取区块的详细数据,为了防止数据获取过程中发生 reorg 导致数据不正确,该接口支持传入 pivot block hash 用于检测 pivot chain switch(如有则返回错误),保证操作原子性和数据准确性。

*为了保证数据的准确性,建议对获取的 block 进行数据有效性检查,如 epoch 高度和 block hash 是否匹配。

c. 获取 epoch 下的 transaction receipts

有如下这两种方式获取 transaction receipts:

  • 通过提取 block 中的执行交易 txn hash, 调用 cfx_getTransactionReceipt 获取每个交易的 receipts。
  • 通过传入 pivot block hash 调用 cfx_getEpochReceipts 批量获取 epoch 下的所有 receipts, 注意该 rpc 方法属于 debug 命名空间,默认不对外开放,需要额外配置 fullnode public_rpc_apis 选项才会开启。该接口支持传入 pivot block hash 用于检测 pivot chain switch(如有则返回错误),保证操作原子性和数据准确性。建议使用这种方式获取 receipts 数据,即高效又能保证操作原子性。 *为了保证数据的准确性,建议对获取的 receipt 进行数据有效性检查,如 epoch 高度、 block hash 和 txn hash 是否匹配。

d. 存储数据

将上述爬取的数据写入数据库等存储系统中,最好能使用事务保证数据写入的原子性。

Reorg 检测

为了保证数据的正确性,当发生 pivot chain switch 时需要将发生 reorg 高度的 epoch 数据从存储中删除,并从删除的 epoch 高度重新同步数据。有以下两种方式用于检测 pivot chain switch:

  • 使用 Pubsub 订阅 epochs 主题监听 latest state epoch 出块高度,当推送的 epoch 高度小于等于前续推送的 epoch 高度时表示在当前推送 epoch 高度由于 pivot chain switch 发生了 reorg,需要将该 epoch 高度以后的数据从存储中删除,并从该高度开始进行重新同步。
  • 同步抓取过程中,检查当前获取 epoch 数据的 parent hash 和上一条 epoch 数据的 pivot hash 是否匹配及 epoch number 是否连续,如不匹配的话,需删除上一条 epoch 数据并重新获取。