钱包把一笔交易交出去广播之后,故事并没有结束。如果它迟迟不进块,节点会周期性地把它再念一遍——这就是钱包的重播(rebroadcast)机制。Bitcoin Core v31.0 把这条逻辑集中写在 src/wallet/wallet.cpp 的 ResubmitWalletTransactions 里,节奏和门槛都藏在源码的几行注释与条件里,读它们比读论坛传说可靠得多。
一条旧命令的退场
早年核心有一个显式命令 resendwallettransactions,手动触发钱包把未确认交易全部重发。它在 0.15 时代有过一段小插曲:-walletbroadcast=0 时调用会直接断言失败,随后修成规范报错。到 0.19,这条 RPC 被整个移除,重播改为完全自动化。今天你在 v31.0 里找不到这个命令,但它的精神活着——只是换了一套更克制的时间表。

0.21 之后:从十五分钟到一到三天
0.21 的发布说明记录了关键转折:为了隐私,钱包重播频率从大约每十五分钟一次,降到每十二到三十六小时一次。源码里对应的实现是钱包头文件那行注释——“把下次重播时间设为从现在起十二到三十六小时之后的随机点”。随机化不是装饰:如果全网的钱包都在固定节拍重播,旁观者就能靠时间戳把同一钱包的交易串成一串。拉长周期加随机化,等于把这条指纹磨平了。
初播的可靠性靠什么兜底?答案是同版本引入的 unbroadcast 集合:交易第一次没能成功广播给对端时,节点把它记在账上,确认发出去为止。也就是说,“确保交易到达网络”由 unbroadcast 负责,“每隔一两天再喊一遍”才轮到周期重播,两者不重叠。
v31 源码里的三道闸门
ShouldResend 决定这次闹钟要不要响。第一道:钱包配了 walletbroadcast=0 就直接不响——关广播的钱包一条都不会重发,哪怕强制也不。第二道:节点还没到”可以安全广播”的状态(比如还在首次同步或 reindex)就不响,注释写得直白:同步期间的旧交易都会变成”未确认”,这时重发等于向全网 spam 自己的历史。第三道:未到 m_next_resend 时间点不响。
ResubmitWalletTransactions 决定响的时候播什么。默认(非强制)路径只挑”比最新区块时间早超过五分钟”的未确认交易——刚发出去几分钟的,网络还没来得及办事,重发没有信息量只有暴露。而节点启动时走的是另一条路:force=true 且只入本地内存池不向外广播,把自家交易重新塞进自家内存池,不惊动全世界。源码注释同时留了一句大实话:重播对加快确认没有任何作用,只会损耗隐私——它存在的意义是防交易在内存池重启、驱逐后悄悄失踪。
实操层面的三条推论
第一,交易卡住时不要指望重播来救。重播不改费用、不带 RBF 意图,原样重发进不了更高优先级的队列;加急要靠 bumpfee 一类的显式手段。第二,walletbroadcast=0 是”只签名不广播”的离线工作流开关,代价是自动重播同被关闭,签好的交易必须由人自己发出去,发没发、发去哪,钱包一概不管。第三,如果你的节点长期离线、时钟漂移严重,重播的时间判断会跟着失真,排障时在 debug 日志里搜 resubmit 字样,能看到每轮实际重发了几笔——这是判断”钱包到底在不在替你喊话”的最直接证据。
一分钟自查
想确认自己节点的重播行为,不用等一天:把 debug 日志级别调到 wallet 相关分类,等下一个重播窗口过去,日志里 resubmit 一行会写明这轮提交了几笔;启动时那次强制入池同样留痕。再交叉看内存池侧:getrawmempool 里你那笔未确认交易的计数与时间戳,能印证钱包的喊话确实到达了自家内存池。如果日志长期安静,依次排查三件事——钱包是不是 walletbroadcast=0、节点是不是还在 _ibd 没到可广播状态、m_next_resend 是不是被系统时间倒拨卡住。三条闸门都在源码里,日志是唯一的外部投影,看不懂行为时先看日志落在哪一道门前。
风险提示:本文描述节点自动化行为的机制,不构成任何投资建议;未确认交易的处置请结合费用与自身网络状况判断。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。