三个体检开关为什么只在 regtest 开着:checkblockindex、checkaddrman 与 checkmempool 图 1
三个体检开关为什么只在 regtest 开着:checkblockindex、checkaddrman 与 checkmempool · 图 1

比特币核心有一组很少被人提起、但在测试实验室里天天用的参数:-checkblockindex-checkaddrman-checkmempool。它们不做网络通信、不改变共识规则,只让节点在运行过程中不停地”自我体检”——核对自己的内部数据结构是不是自相矛盾。理解它们的默认策略,能顺便解释一个常见困惑:为什么同一份代码,在主网和 regtest 上的行为差别这么大。

三个开关分别查什么

-checkblockindex 负责区块树与链状态之间的一致性:区块索引指向的父块对不对、活动链上的区块有没有被错误标记、UTXO 集合的视角与区块树的视角是否吻合。这类检查在实现上会遍历相关结构做双向核对,代价不小。

-checkaddrman 检查的是地址管理器:节点维护的”候选对端地址库”内部有没有重复、有没有把同一个地址塞进不该进的桶。它按操作次数计频,参数值就是”每多少次操作跑一次检查”,填 0 表示关闭。

-checkmempool 检查交易池:入池交易的依赖关系、祖先集合统计、费用排序这些内部账目是否自洽。它同样按交易计数触发,适合用来复现与交易池逻辑相关的疑难问题。

默认策略的关键:只在 regtest 开着

checkblockindexcheckmempool 帮助文本里的默认值写法很特殊,它写的是”默认值取决于网络,regtest 另有其值”。落到实现上,判断依据是一个叫”默认一致性检查”的网络属性:主网、testnet3、testnet4、signet 上这个属性都是关闭,只有 regtest 打开。也就是说,你在主网跑节点,默认情况下这两项深度自检是关着的;一换成 regtest,它们就自动开启。checkaddrman 稍有不同的帮助文本形态,默认值直接写明是 0——所有网络一律关闭,需要时手动给一个正整数才会按频次触发。

这不是随意为之。regtest 的定位是开发者与测试框架的沙盒,运行环境数据量小、可重复、不需要性能,把自检拉满是纯粹收益——任何内部不一致会第一时间炸出来,测试随即失败,问题被钉在引入它的那次改动上。主网正相反:全节点要连续追块、维护上百 GB 数据,一致性检查每跑一次都要扫过大量结构,开着会明显拖慢同步。主网的正确性主要靠另一条路径保障:启动时的历史区块抽样校验(-checkblocks-checklevel),以及共识规则本身在每次连接区块时的完整校验。

什么情况下值得手动打开

真实的运维场景不多,但有三种。一是怀疑数据目录被异常修改:比如磁盘掉电、有人手工动过 blocks 或 chainstate 目录,此时开一次区块索引自检,比凭哈希比对更快定位。二是排查一个只在特定节点上出现的诡异现象:同一笔交易别人正常、你这台不正常,交易池自检能直接告诉你内部账目在哪里断了。三是自建测试链做集成测试:这时应该干脆用 regtest,让自检自动全开。

需要提醒的是,这几个参数都带”仅调试”标记,普通帮助输出里看不到,需要用带调试项的帮助输出查看。它们是诊断工具而不是优化选项:开着不会让节点更安全、也不会让数据更准,只会让节点更慢。日常节点保持默认,把体检留给需要它的时刻。

还有一个容易顺手做错的事:把”开了自检所以更可信”当成安全感的来源。一致性检查核对的是节点自己内部账本的自洽性——索引指针、依赖统计这些软件自己维护的辅助结构对不对得上,它并不重新验证签名,也不会发现”共识规则本身被绕过”这种层面的问题。后者由每次连接区块时的完整校验负责,那条路径与自检参数无关。换句话说,自检是给软件排查自己的 bug 用的,不是给使用者增加信任用的。想给数据加一层独立信任,正确方向是换一台机器重新同步做交叉比对,或者用快照与校验和核对,而不是在同一个数据目录上打开几个调试开关。

风险提示:本文为节点诊断参数说明,不构成投资或运维建议;涉及数据目录的排查请先在副本上操作,不要在唯一副本上直接尝试修复类参数。