换链不是重放,是倒带
比特币节点选链的原则是累计工作量最大的那条。当一条更重的竞争链出现,节点要做的事情叫”断开再连接”:把当前主链顶端的区块逐个拆下,退回两条链分道扬镳的那个高度,再逐个挂上新链的区块。关键在于拆的动作。区块里花的每一笔钱,都已经在 UTXO 集合(未花费输出集合)里被划掉了;区块的 coinbase 奖励也已经被标记为进入成熟倒计时。要拆掉一个区块,节点必须分毫不差地还原它改动过的一切:把被这个区块花掉的输出重新放回未花费集合,把区块奖励退回未成熟状态,把相关的支出位图恢复原样。这件事没有捷径,不可能靠重新扫描全链现场推导,靠的是每个区块落盘时就备好的一份专属账本,撤销数据(undo data)。
撤销数据长什么样、放在哪
节点在把一个区块写进 blocks 目录的区块文件时,会同步写一个同序的撤销文件,里面记录这个区块花掉了哪些历史输出、各自属于哪个高度、金额与脚本是什么。区块文件负责”这个块做了什么”,撤销文件负责”怎么把它撤销”。两者按文件序号一一配对。正因为这份数据是逐块生成的,节点才能在毫秒级完成一次状态倒带,重组对本地账本来说像倒放映带,而不是一场重新审计。
由此能推出一条实用结论:能不能跟进一次重组,取决于手上还留着多深的撤销数据。多深的回滚就需要多深的撤销账本。如果一段链的回滚所需的撤销文件已经缺失,节点就不可能自行切换到那条链——状态无从还原,猜测更不被允许。这种缺失在日常运行中几乎不会遇到,更常见于剪枝节点把老数据删掉之后的极端场景,届时通常只能重新同步或人工介入,而不是系统坏了。
剪枝节点的边界
剪枝(pruning)模式下节点为了省磁盘会删除旧区块文件,但删除逻辑对撤销数据格外克制:它总是尽量保留近期块及其配套数据,因为近期块仍在正常的重组可达深度之内。换句话说,剪枝改变的是节点能回答多老的历史问题,基本不改变它应对日常深度重组的能力。但边界依然存在:剪枝节点无法像全节点那样随时重放任意历史,重组深度超出保留范围时它的容错空间也更小。跑服务、跑后端的用户选不选剪枝,本质是在磁盘成本与历史完整性之间标价,而不是在安全与不安全之间选择。
重组发生时链上会看到什么
一笔交易所在区块被孤立,交易本身并没有”被删除”——它要么随另一条链上的等价区块继续有效,要么回到内存池排队,要么与竞争交易冲突而永久失效。对收款方来说,最直观的信号是区块浏览器上确认数突然变小甚至归零。节点侧可以用区块链接口观察链尖跳动,钱包则靠重新扫描找回去向。需要明确:一确认从来不是”落袋”的数学分界线,只是风险足够低的经验值;六块以上回滚在主网历史上屈指可数,这也是六确认惯例的依据来源。
一个容易混淆的点
撤销数据与区块数据是两本账,用途完全不同:前者只为回滚服务,后者负责完整重放历史、给钱包重扫和给对端供块。有人以为剪枝后节点”记不住账本”,其实账本的权威形态是 UTXO 集合与区块文件的组合,撤销文件只是回滚用的保险丝。理解这三份数据各自的职责,重组、剪枝、钱包重扫这些概念就不再神秘:比特币节点处理”历史可能改写”的方式,从来不是争论,而是提前把退路备好。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。