abortrescan 按下的是暂停键:中止钱包重扫后账本处于什么状态 图 1
abortrescan 按下的是暂停键:中止钱包重扫后账本处于什么状态 · 图 1

用 RPC 给钱包做历史重扫时,进度条跑了几十分钟还没完,你想叫停——这时候该按的刹车就是 abortrescan。它名字短,语义却容易被误解:它停的是”这一次扫描动作”,不是撤掉已扫到的账,也不是取消钱包的扫描状态。本文按 Bitcoin Core v31.0 源码核对它的行为边界。

一、刹车踩下去到底发生什么

源码里 abortrescan 做的事极其小:检查这个钱包当前确实在扫描、且还没被中止过,然后把一个原子布尔标志置位,返回 true。扫描线程每处理完一个区块都会回头查这个标志,看到它就提前结束循环,在日志里记一行”在某个高度中止、进度多少”,收尾时该扫的内存池还是会扫一遍。所以它不是拔电源:调用返回 true 的那一刻扫描线程可能还在跑当前这一块,真正的停止发生在下一个检查点。想确认是否真的停了,去 getwalletinfo 看 scanning 字段——它要么还在报 duration 和 progress,要么已经变成 false,这才是权威状态。

二、返回值 true 不等于”我中止成功了”

两种情况会返回 false 而没有任何报错:钱包根本没在扫描,或者中止请求已经发出过了。也就是说 false 的语义接近”没东西可停”,而不是失败。脚本里别把 false 当成异常抛出来。另外,这条命令没有参数,一次只影响当前 RPC 指向的那个钱包——多钱包节点上忘了用 rpcwallet 指明目标,就可能停错人。

三、中止之后账本是什么状态

扫描是逐块推进的:中止点之前的区块已经按正常流程处理,期间发现的收款会正常入账、正常出现在交易列表;中止点之后直到链尖的那段没有补扫。这正是最容易丢币的窗口——如果你刚导入一个有历史的描述符然后中止,那笔位于未扫区间的收款不会自己浮出来。所以中止之前要想清楚:你只是不想等了,还是不需要那段历史?前者应该择机再跑一次 rescanblockchain 补上区间;后者(比如只是误扫了别人的地址)用 removeprunedfunds 之类工具清理导入的记录更对症。顺带说明一个常见误解:中止不会回滚已入账的数据,也不会把钱包退回导入前的状态——描述符本身还在钱包里,随时可以续扫,账本的进度和描述符的存废是两回事。

四、哪些操作会主动要求你先中止

源码里有三处会直接报错并点名这条命令:改钱包密码、锁定钱包、加密钱包。逻辑相同——扫描线程正拿着钱包的解密状态干活,此时动锁会造成状态撕裂,所以核心选择一刀切:要动锁,先叫停扫描。遇到 “wallet is currently being used to rescan” 这类报错,按提示先 abortrescan 再操作,是官方写进错误消息里的正解,不是玄学偏方。

五、实战建议

导入历史描述符之前,先用 getdescriptoractivity 或区块浏览器确认历史上有没有活动,没有就设 birth 时间跳过扫描,比扫完再中止省几小时;必须扫描时给它划定明确的起止高度,别默认从头扫全链;中途要腾资源,中止、记好 current block 日志,之后从那个高度续扫即可。还有一条容易被忽略的纪律:中止与续扫之间,别把”余额暂时没变多”当成扫描失败的证据——重扫只是把已属于钱包的输出重新认领进账本,本来就在账上的钱不会因为多扫一遍而重复出现。abortrescan 的定位是扫描任务的暂停键——键本身没有智能,智能在你决定要不要回来续扫。

风险提示:钱包与密钥操作存在丢失资产风险,任何中止、重扫之前请先备份钱包文件;本文不构成投资建议。