钱包增量同步最危险的错误,不是一次RPC失败,而是RPC已经返回、业务只写入一半数据却先保存了新游标。listsinceblock提供了处理重组所需的三个区域,但应用仍要自己把它们组织成可回滚账本。
一次响应要拆成三张清单
listsinceblock返回指定blockhash之后的wallet相关交易;若该块不在主链,则从分叉点起返回。
transactions用于处理从指定位置之后观察到的wallet交易,removed用于记录因重组离开原主链的历史事件,lastblock则给下一轮扫描一个更合适的起点。removed本身不是最终状态;应用还要结合当前confirmations、blockhash及transactions或gettransaction结果完成归并。
| 响应区域 | 写入动作 | 幂等键 | 失败时怎么办 |
|---|---|---|---|
| transactions | 插入或更新交易状态 | wallet + txid + 明细标识 | 整轮回滚 |
| removed | 记录重组事件,随后核对当前状态 | 原交易标识 | 整轮回滚 |
| lastblock | 更新扫描游标 | wallet同步任务 | 最后提交 |
同一txid可能包含多个wallet相关明细,收款、找零与手续费要按Bitcoin Core返回语义建模。业务余额不应简单把每条amount相加后当最终会计结果。
分叉点会改变扫描起跑线
include_removed默认true,removed记录因重组离开原主链的wallet交易;其中已重新进入当前主链的交易也可能带正confirmations,因此removed是重组历史证据而非一律代表当前撤销。剪枝节点上该信息不一定可用。
当传入的blockhash已不在主链,节点从共同祖先之后返回相关交易,帮助应用看到新主链的变化。removed默认开启,记录旧链上离开的wallet交易;但其中已重新进入当前主链的交易也可能显示正confirmations。应用应保存原确认高度、原区块哈希和重组时间,再以当前链状态决定confirmed、unconfirmed或removed,不能只见removed就直接冲销。
剪枝节点可能没有足够旧区块来构造完整removed结果。若系统承担充值入账或审计责任,应明确节点保留策略,并在发现历史不足时切换到保留完整历史的可信节点或执行受控重扫,而不是把空removed当成“没有重组”。
target_confirmations不负责过滤交易
target_confirmations不筛选transactions,只影响返回的lastblock;lastblock通常作为下一轮调用的游标。
这个参数容易被误解为“只返回达到N次确认的交易”。官方语义是它影响lastblock所指向的位置,而transactions仍可包含确认数不足的项目。是否给用户入账,必须由业务根据每条交易的confirmations、区块状态和风险策略再决定。
因此可以分离“观察账本”和“可用余额”:观察账本尽早记录交易,可用余额只在达到门槛后释放。发生重组时,观察记录变成removed或未确认,可用余额则按可逆策略冻结、冲销或进入人工队列。
同一txid重新上链如何去重
同一txid可能在removed出现后又重新进入主链,应用应更新状态而不是追加两条账务。
一笔交易离开旧链后可能仍在内存池,随后被新链区块再次确认。若removed处理成一条负向流水、transactions又追加一条正向流水,报表会出现虚假的两笔经济活动。更好的做法是以交易与明细标识更新生命周期:seen、confirmed、removed、reconfirmed,并保留每次区块归属的审计事件。
区块确认数下降到负值、回到零或再次变正,都应更新同一对象。对外通知也要去重:用户已经收到“到账”通知后发生回滚,应发状态变更通知,而不是再次把重新确认当作新充值。
用数据库事务封住游标漏洞
一轮同步的安全顺序是:锁定wallet同步任务;读取旧游标;调用RPC;在单个数据库事务内处理transactions与removed;写入新lastblock;提交事务。RPC超时不移动游标,数据库提交失败也不移动游标。重试同一轮时,所有写入通过幂等键更新。
若处理量很大需要分批,lastblock仍只能在所有批次完成后提交,可另设内部批次进度,但不能把它冒充链游标。多实例执行时使用任务锁或比较交换,避免两个进程交错覆盖游标。
上线前演练一次两块重组
在测试环境构造交易先确认、随后旧块失效、交易重新进入新块的序列,检查余额、通知、审计日志与游标是否一致。再模拟节点为剪枝模式、RPC中途超时、数据库最后一步失败和重复Webhook。只有这些失败路径通过,增量同步才算真正可用。
游标只在账本提交后前进
把lastblock与本轮交易状态放在同一个数据库事务里,才能让重试既不漏账也不重复。重组不是例外补丁,而应从第一天就进入钱包同步状态机。
listsinceblock如何防止重组漏账?的复查入口
复核这篇文章时,应从Bitcoin Core 31 listsinceblock、Bitcoin Core 31 gettransaction、Bitcoin Core 31 Release Notes开始,并同时检查页面访问日期。
当前不能越过的事实边界是:重组深度和扫描周期取决于业务风险偏好;剪枝节点无法承诺完整removed历史。
相关背景可继续查看getbalances对账、钱包目录与加载状态、内存池压力。本文用于信息与教育,不构成投资、法律或个案处理建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。