一、文档里最直白的一段警告
sendrawtransaction 的官方说明有一句话值得逐字读:交易会被无条件发送给当前所有连接的节点,因此拿它做手动重发会损害隐私——因为节点之间正常情况下不会重复广播自己内存池里已有的非钱包交易,一条”不该被转发”的交易突然从你这台机器满世界转发,等于向全网举手说”我是源头”。这段话承认了一个设计事实:这条命令是为”我确认这条交易需要立刻出去”准备的推土机,不是日常发交易的路径。日常走钱包接口,交易混在正常的中继规则里传播,起源信号天然弱得多。

二、第一道闸门:maxfeerate
命令的第二个参数是 maxfeerate,默认 0.10 BTC/kvB。它的含义不是”你愿意付多少”,而是”看到这么贵的费率我拒绝发送”——一道防手滑的保险:签名环节费率填错、单位搞反,这笔交易没出这道门就被拦下。设成 0 表示费率不限;文档同时写明费率超过 1 BTC/kvB 的交易本身就会被拒绝。第三方服务给的裸交易、链下流程里拼出来的裸交易,落地前都值得过一遍这道检查,再配合第三个参数 maxburnamount 限制交易里”主动销毁”的金额上限。
三、第二道闸门:先预演再广播
正式发送之前,testmempoolaccept 提供一次只读的预演:传入裸交易(支持一组,可预演父子包),返回是否会进内存池、被拒的话拒绝原因、以及节点此刻的最低准入费率。它不广播、不改变任何状态。于是裸交易的正确流水线是三步:构造完成后先 testmempoolaccept 看 allowed 与 reject-reason;有冲突或费率不足先处理,改完再预演;确认通过后再 sendrawtransaction,并且只在”确实需要手动推”的场合推。离线签名场景里,冷设备签完的裸交易带回在线机器落地,这条流水线的价值最大——广播不可撤回,预演是最后免费的检查。
四、新近的改进与仍然存在的权衡
较新的源码里出现了一个私有广播开关:启用后,本机提交的交易不再立刻向全部对端广播,而是排队等在网络上”被自然带回”,队列有容量上限、满了这条命令直接失败,直到腾出空位。它针对的正是第一节的起源泄露,属于缓解而非根治——只要交易最终从你这台机器出去,时机与来源统计就有可挖掘的信号;而它带来的时延对争分夺秒的替换类交易不友好,这类交易本来就应该立刻传播。理解这个权衡的用处在于:对”手动重发会暴露”不需要恐慌,它是一次可以用场景换的场景——一次性、不赶时间的补播,泄露面本来就小;真正要避免的模式是把 sendrawtransaction 当成默认发信通道反复使用。
五、清单收尾
落地前五项检查:裸交易的输入是否仍可用(被花掉就是另一种报错)、费率是否落在两个上限之内、目标网络是否与原交易一致(测试网裸交易发到主网只会以报错收场)、是否先跑过 testmempoolaccept、以及这一次到底是不是”必须手动”的场景。五项都过,再按回车。
补充:报错码的最小地图
手动广播常见的报错各有一张脸:-25 通常是交易已在链上或验证类通用错误,-26 是被网络规则拒绝,正文里带具体原因字符串,-27 表示交易的输出已在 UTXO 集合里,多半是重复提交。看到报错先读 message 再决定动作:费率为零的裸交易要改的是构造端,不是重发端;已在链上的交易重发一百次也不会多一个确认。把这三个码和 testmempoolaccept 的预演结果对照着装进脚本,手动广播就从玄学操作变成有分支逻辑的流程。
顺带更新一个较新的实践:钱包侧现在也能走”只签名、由外部决定何时广播”的路径,把”签好”和”发出”两个决定拆开的流程因此不再必须手搓裸交易。把本文的闸门思路用在自动化里,结论是同一句话——广播永远放在最后一步、由可控的一端统一执行,签名环节保持无网络即可完工。这条流水线纪律对所有钱包软件通用,与用哪家实现无关。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。