getchainstates:节点临时同时持有两条账的时候看什么 图 1
getchainstates:节点临时同时持有两条账的时候看什么 · 图 1

比特币节点默认只有一条”经过完整验证的链”:从创世块一路重算签名与规则走到 tip。assumeUTXO 快照同步改变了这个默认——节点可以从一个可信快照出发先跑起来,同时把”快照以下是否真实”的补课工作放在后台链上重算。补课期间,节点内部同时存在两条链状态:一条是从快照出发、还在被逐块回填验证的账,一条是仍在从头爬的老账(如果它在)。这段时间节点到底有几本账、各自追到哪、哪本是权威,普通 RPC 说不清——getchainstates 就是为这个时刻设计的。

返回结构:一条顶层信息加一本花名册

v31.1 的 getchainstates 不需要参数。顶层两个字段:headers 是节点见过的区块头数量(还没有任何头时为负一,区块头链和已验证链是两回事,这个数往往更大);chainstates 是数组,按累计工作量排序,活动链排在最后——“最后一条是权威”就是全部排序语义。

每一条链状态的档案字段相同:blocks 与 bestblockhash 说这条账记到哪个块;bits 和 target 分别给难度目标值的压缩形式和展开的十六进制目标阈值;difficulty 是倍率形式;verificationprogress 是对网络进度的估计。两个缓存字段 coins_db_cache_bytes 与 coins_tip_cache_bytes 报这条链的 UTXO 缓存配额拆分——两条链并存时各拿一份,看总内存预算时要把它们相加。

两个字段专门标记快照血统:snapshot_blockhash(仅当该链基于快照时出现,值是快照基准块)和 validated(布尔——快照链在回填完成前为 false,普通链恒为 true)。判断”补课完成没有”,看的就是活动链的 validated 和两条链何时合并成一条。

为什么不能拿 getblockchaininfo 代替

getblockchaininfo 永远只汇报活动链——它没有”其他账本”的概念。快照同步期间用它看进度一切正常,容易误以为节点已经完整验证;而 getchainstates 会把还在回填的那条(或历史的那条)一起列出来。运维上两者配合:getblockchaininfo 管”对外以哪条链为准”,getchainstates 管”内部还有几条、状态如何”。

补课期间还有个对网络身份的影响值得知道:v31.1 源码在快照激活与背景同步期间会把本节点的服务标志调整为受限模式——撤下 NODE_NETWORK、标记 NODE_NETWORK_LIMITED(通常仍可回看最近 288 个区块,但历史区块服务暂时关闭),同步完成后恢复。这是别的节点看你时”你是谁”的变化,也是这个双账本阶段在 P2P 侧的直接投影。

收尾的判据

背景验证完成的那一刻,两条链合并为一条:chainstates 数组长度回到 1,活动链的 validated 为 true。把这三行写进部署脚本的等待条件,比”过一晚上再看一眼”可靠得多。

把监控接在正确的字段上

三条能直接落地的判据。其一,chainstates 数组长度:1 是稳态,2 是快照补课中,长期大于 2 或突然变空都值得立刻翻日志。其二,活动链的 validated:为 false 说明对外服务的账本还欠着历史验证,此时节点在 P2P 侧的服务标志往往已降为受限模式,把这一位布尔值接进健康检查,比单独盯同步百分比更贴近节点现在可信到什么程度这个问题。其三,两块缓存字段的加总:双链并存时内存配额是双份的,容量告警线要按加总画,否则开启快照同步的头几天会出现莫名的内存爬升。再补一个反例:verificationprogress 是估计值、两条链各估各的,别拿两条的进度做减法当补课进度——补课进度的正确算法,是回填链 blocks 相对快照基准高度的增长。

风险提示:快照同步的可信根来自快照文件的元数据校验,快照来源仍需自己把关;字段定义基于 v31.1 源码,升级后请以帮助文本复核。本文不构成投资建议。