区块链分叉检测与回扫系统(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的数据在数据库,会造成

Go 复制代码
currentBlock.Hash!= nextBlock.preHash

使得程序报错,此时必须要有应对手段,这就是本项目所要讲的回扫问题

(3)逻辑概要

假设你的数据库当前是:

数据库状态:100 ->101-B

链上实际: 100->101-A->102-A

检测逻辑:

Go 复制代码
    //从链上拉取高度 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,指向它的父区块:
Go 复制代码
区块100               区块101                     区块102

100 hash="0xaaa" <-----  parentHash="0xaaa" <--------parentHash="0xbbb"
    
                         101 Hash= "0xbbb".          102 Hash="0xccc"
  • 核心逻辑:
java 复制代码
    链上区块 N 的 parentHash == 数据库中区块 (N-1) 的 hash ?
        相等 → 正常
        不等 → Reorg
  • 关键代码:
Go 复制代码
dbBlock := GetBlockByHeight(height - 1)
    if chainBlock.ParentHash != dbBlock.Hash {
        return true  // Reorg!
    }

三、回扫实现

回扫分三个步骤:

  1. 找分叉点:从当前高度往回找,直到 parentHash 匹配

  2. 回滚:删除分叉点及以后的区块

  3. 重新同步:从分叉点拉取新数据

关键代码:

Go 复制代码
    // 找分叉点
    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即可。

相关推荐
凯丨1 分钟前
会“做梦“的 AI:用一句话生成可以玩的世界——读懂世界模型 Genie 3
人工智能·microsoft
踏着七彩祥云的小丑1 分钟前
AI学习——记忆系统
人工智能·学习·ai
ACP广源盛139246256737 分钟前
GSV2221@ACP# 高带宽低功耗显示转换芯片,赋能 TRAE SOLO 设备高清扩展升级
人工智能·嵌入式硬件·电脑·音视频
大强同学8 分钟前
我用 Claude Code,把 NotebookLM 变成了 Obsidian 插件
人工智能·agent·claude·skill·notebooklm
non-action_pilgrim11 分钟前
Go 高并发踩坑:关于在 for 循环里使用 time.After 后所进行的问题分析
golang
J2虾虾15 分钟前
Spring AI Alibaba - Memory 短期记忆
人工智能·spring·microsoft
刘一说22 分钟前
AI科技热点日报 | 2026年5月30日
人工智能·科技
大模型最新论文速读26 分钟前
SkillOpt:把 skill 文档当成模型权重来训练
论文阅读·人工智能·深度学习·机器学习·自然语言处理
吃好睡好便好26 分钟前
矩阵的左乘和右乘
人工智能·学习·线性代数·算法·matlab·矩阵
俊哥V27 分钟前
每日 AI 研究简报 · 2026-05-30
人工智能·ai