区块链分叉检测与回扫系统(Go语言)
本文将手把手带你实现一个完整的区块链分叉检测与回扫系统,适合对区块链同步机制感兴趣的开发者
代码链接:https://github.com/Meiwen1/rollback-scan
在说区块链分叉检测之前,首先要明白分叉是什么
一、分叉
可以将链想象成一根分叉的树叉
正常情况:

分叉情况:

1.1 分叉分类
1.1.1 硬分叉
(1) 定义
协议规则的不向后兼容变更,旧版本节点无法验证新版本产生的区块。
(2) 底层原理
旧规则:区块大小上限 = 1MB
新规则:区块大小上限 = 8MB
当新节点产出一个 2MB 的区块时:
新节点: 合法,接受 ✅
旧节点: 非法,拒绝 ❌
(3) 分叉结果
链永久分裂成两条独立链,各自运行,互不承认
可以参考 etc 与eth 的硬分叉案例
1.1.2 软分叉
(1) 定义
协议规则的向后兼容变更,旧版本节点可以验证新版本产生的区块(虽然可能不理解新功能)。
(2) 底层原理
旧规则: 交易格式 = [nonce, gasPrice, gasLimit, to, value, data]
新规则: 交易格式 = [nonce, gasPrice, gasLimit, to, value, data]+可选的新字段(旧节点忽略)
(3) 典型场景
比特币改进方案(BIP) 66:比特币签名验证的软叉
支付给脚本哈希(P2SH):在比特币网络上,一个软叉产生多重签名地址
(4) 分叉结果
链不会永久分裂,最终会统一到新规则链上(因为新节点算力通常更强)
1.1.3 🌟🌟链重组
这是我们项目要处理的核心
(1) 定义
链重组是指在区块链中,由于网络延迟或节点故障等原因,导致某些区块暂时无法被所有节点确认,从而出现多个 competing chains(竞争链)。当这些 competing chains 的长度相同时,网络会选择最长的 chain 作为主链,其他 competing chains 会被舍弃。这个过程就叫做链重组。
所以与分叉最大的区别是 主动与被动的关系 分叉是主动 链重组为被动
(2) 链重组发生过程详述:
时间线(T0到T3):

T3时刻同时存在101-A和101-B,这样就发生了 一种被迫的临时分叉
区块链自己如何去解决这个问题呢?
- 最长链原则(Longest Chain Rule)
在T4时刻 A链长度>B链长度,故维护A链 淘汰B链 但这不是一瞬的,是需要一段时间来进行选择的结果

最长链原则是链上遵循的一种基本原则,
链上数据是落到我们数据库里的,所以在代码中,我们要遵循最长链原则,就必须始终保持我们数据库的数据 都是来自链A(最长链)的数据,不能有链B(短链)的数据,如果我们有链B的数据在数据库,会造成
currentBlock.Hash!= nextBlock.preHash
使得程序报错,此时必须要有应对手段,这就是本项目所要讲的回扫问题
(3)逻辑概要
假设你的数据库当前是:
数据库状态:100 ->101-B
链上实际: 100->101-A->102-A
检测逻辑:
//从链上拉取高度 102 的区块
block102 := getBlockFromChain(102)
//检查: 102 的 parentHash 是否等于我数据库里 101 的hash
if block102.ParentHash != db.GetBlock(101).Hash{
//不等! 说明我将 101-B 这个区块存储到数据库这个行为是错的
//链上的101 已经变成101-A了
//需要重组(Reorg)!
}
回扫逻辑:
Step 1:找到分叉点
从当前高度往回找,直到parentHash 匹配检查101:链上 101-A.parentHash == 数据库100.hash
分叉点 = 高度 100
Step 2:回滚
删除数据库中 101 及以后的所有区块(删除101-B)Step 3:重新同步
从高度101开始重新拉取(得到 101-A,102-A)
(4) Reorg(回扫) 观念理解
Reorg 深度 = 被回滚的区块数量
深度1 = 只回滚 1个区块(常见)
深度2-3 = 偶尔发生
深度6+ = 非常罕见(这就是为什么BTC 要等 6 个确认)
深度100+ = 意味着51%攻击(几乎不可能,除非调用国家级的算力)
1.2 分叉对比
| 特性 | 硬分叉 | 软分叉 | 链重组 |
|---|---|---|---|
| 层级 | 协议层 | 协议层 | 共识层 |
| 兼容性 | 不兼容 | 向后兼容 | N/A |
| 是否永久 | 永久分裂 | 最终统一 | 临时,很快解决 |
| 需要处理? | 换节点/换链 | 通常自动 | 需要回扫 |
| 触发原因 | 人为升级 | 人为升级 | 网络延迟/攻击 |
可以大致的理解为 软硬分叉是主动分叉 而链重组是被动的临时分叉
二、分叉检测实现
检测原理:
- 每个区块都有一个 parentHash,指向它的父区块:
区块100 区块101 区块102
100 hash=”0xaaa“ <----- parentHash=“0xaaa” <--------parentHash="0xbbb"
101 Hash= “0xbbb”. 102 Hash="0xccc"
- 核心逻辑:
链上区块 N 的 parentHash == 数据库中区块 (N-1) 的 hash ?
相等 → 正常
不等 → Reorg
- 关键代码:
dbBlock := GetBlockByHeight(height - 1)
if chainBlock.ParentHash != dbBlock.Hash {
return true // Reorg!
}
三、回扫实现
回扫分三个步骤:
1. 找分叉点:从当前高度往回找,直到 parentHash 匹配
2. 回滚:删除分叉点及以后的区块
3. 重新同步:从分叉点拉取新数据
关键代码:
// 找分叉点
for height := startHeight; height > 0; height-- {
if chainBlock.ParentHash == dbBlock.Hash {
forkHeight = height
break
}
}
// 回滚
DeleteBlocksAbove(forkHeight)
主循环:
for h := startHeight; h <= chainHeight; h++ {
if CheckReorg(h) {
forkHeight := HandleReorg(h)
h = forkHeight - 1 // 重置起点
continue
}
SaveBlock(chainBlock)
}
四、运行代码



测试过程很简单只需要讲 hash值手动更改使得 currentBlock.Hash!=nextBlock.PreHash即可。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)