测试用的微型账本:fastprune 把比特币核心的区块文件缩到六十四千字节 图 1
测试用的微型账本:fastprune 把比特币核心的区块文件缩到六十四千字节 · 图 1

测试用的微型账本:fastprune 把比特币核心的区块文件缩到六十四千字节

剪枝模式(prune)是家用节点的省磁盘利器,但想在一台小机器、一段 CI 流水线或者一次教学演示里复现”剪枝之后的行为”,得先同步几十 GiB 真实链——成本高到多数人干脆不测。Bitcoin Core 为此留了一个调试开关 -fastprune:把区块文件切小、把允许修剪的高度线压低,让剪枝逻辑在几百个区块内就能被真实触发。这个参数平时不出现在帮助列表里,但它背后的两处改动,恰好暴露了剪枝机制依赖的两个平时看不见的前提。本文全部以 Bitcoin Core v31.0 源码为准。

参数的定义与作用域

src/init.cpp 注册处的帮助文本一句话:“Use smaller block files and lower minimum prune height for testing purposes”,且带 DEBUG_ONLY 与 DEBUG_TEST 分类——这正是它不出现在常规帮助输出里的原因。它不是”更积极的自动修剪”,不改变修剪策略本身,只把两个尺寸参数挪到适合测试的量级。

改动一:区块文件从 128 MiB 缩到 64 KiB

正常节点把区块以网络格式连续追加进 blocks/ 下的 blkNNNNN.dat 文件,每个文件写满 128 MiB(常量 MAX_BLOCKFILE_SIZE)才滚动到下一个;配套的 rev 撤销文件同样分片。开 fastprune 后,node/blockstorage.cpp 把 max_blockfile_size 改为 0x10000——六十四千字节,同时 FlatFileSeq 的分配块从正常的 16 MiB 降为 0x4000(16 KiB)。六十四千字节还带来一个边界问题:单个区块完全可能比文件还大,源码因此加了一段动态调整——当本块序列化尺寸不小于上限时,把该文件上限抬到”块尺寸加一”,保证任何区块都能整个装进一个文件。这个兜底平时用不上,恰好说明正常情况下 128 MiB 相对单块尺寸(极限四百万权重)的余量设计意图。文件变小带来的直接后果是同名文件数量暴涨:同一段链,正常目录里几百个 blk 文件,fastprune 目录下会是几万个小文件。磁盘占用没变、inode 与目录遍历开销大增——这也是它不进帮助列表、只在测试里用的原因之一。

改动二:修剪高度线从十万降到一百

剪枝不是”留下最近多少 MiB”一条规则就完事,源码里还有一条高度地板:主链参数里 nPruneAfterHeight 主网为 100000、测试网与 signet 为 1000——自动修剪只对超过这条线的区块动手,保证节点至少保留从创世起约两年的一段连续正文,早期链状态出问题时仍有据可查。kernel/chainparams.cpp 在 regtest 分支上按 opts.fastprune 把这条线切成一百或一千。也就是说,快剪模式下节点从第 101 个区块起就允许被修剪旧数据,配合微型文件,新初始化一个 regtest 节点、挖几十块、设个小目标体积,几分钟内就能观察到 blk 文件被真正回收的全过程。

什么场景值得用它

第一类是开发者的功能测试:写备份脚本、剪枝目录监控、磁盘告警逻辑的开发者,需要一个”真会剪枝”的链环境而不是手动删文件的模拟。第二类是教学与演示:向别人解释 blk 与 rev 文件如何配对、修剪为什么保留头与索引时,几十 KB 一个文件的目录结构比 GiB 级大文件直观得多。第三类是回归测试:升级版本后验证链重建、假设校验与剪枝组合的边界,微型链让跑全套用例的时间成本可控。使用时的自我提醒:这些文件尺寸与高度线都是调试值,别指望在真实节点上调它们省磁盘——-prune=<MB> 才是面向生产的旋钮;另外在测试里看到的行为(比如修剪频率、文件碎片化)会因微型参数而放大,与主网的实际节律存在量级差。

风险提示:本文为节点测试机制科普,参数与常量以 Bitcoin Core 当前版本源码为准,可能随版本调整;调试参数行为不等同于生产承诺;不构成投资建议。

与 prune 参数的关系

fastprune 不取代 -prune=<MB>:目标体积参数仍是开关剪枝模式的主入口,fastprune 只是在剪枝已启用的前提下把”地板高度”和”分片尺寸”换成调试值。两者叠加时的观察顺序也值得记住——先确认目标体积低于当前链总体积,剪枝才会真正动手;再确认链高度越过修剪高度线,旧文件才会被标记回收。测试里”设了 prune 却没见文件减少”,九成是卡在这两个前置条件之一,而不是 fastprune 本身失效。