converttopsbt:把老式十六进制交易反向装进 PSBT 的那扇门 图 1
converttopsbt:把老式十六进制交易反向装进 PSBT 的那扇门 · 图 1

PSBT 成为离线签名标准格式之后,一条不显眼的转换命令接住了旧流程与新格式之间的接缝:converttopsbt 把”网络序列化”的裸交易十六进制反向装回 PSBT 容器。命令文档在 v31.0 源码里第一句就划定了适用面:只应搭配 createrawtransactionfundrawtransaction 的产出来用,新应用应该直接用 createpsbtwalletcreatefundedpsbt。这句话背后是 PSBT 与裸交易的本质差异,本文按源码把它讲透。

为什么”反向转换”天生残缺

裸交易格式是为广播设计的极简容器:输入只有 txid 加 vout 加 scriptSig,输出只有金额加脚本,没有任何”这个输入由谁签、用哪层脚本、需要几个签名”的元数据。PSBT 则是一个带富元数据的半成品容器——每个输入挂着非见证前交易、见证 UTXO、到期时间(用于时间锁的模拟高度),每个输出挂着脚本与未知键。把裸交易转进 PSBT 时,转换命令能做的只有格式搬运:它把输入输出逐条复制进 PSBT 结构,但无法凭空补出签名者信息。对 segwit 输入,PSBT 规范要求 witness_utxo 字段存放被花输出的脚本与金额,转换命令只能按输入引用留空占位,等待签名器或后续流程补齐;对旧式非见证输入则需要 non_witness_utxo 级别的前交易全文。这就是文档为什么限定”只配合这两条命令”:createrawtransaction/fundrawtransaction 的产出恰好是一笔结构规整、尚未签名的交易,转换不会遇到语义悬崖;而把一笔网络上已签名、或来源不明的交易硬转 PSBT,得到的是一个元数据稀疏、签名器可能拒签的残缺容器。

converttopsbt:把老式十六进制交易反向装进 PSBT 的那扇门 图 2
converttopsbt:把老式十六进制交易反向装进 PSBT 的那扇门 · 图 2

permitsigdata:一个默认保守的破坏性开关

第二个参数 permitsigdata 默认 false。默认行为:输入里若已带签名字节,命令直接失败——因为对着已有签名硬转出来的 PSBT 语义上是矛盾的(PSBT 的 scriptSig 位置是”待填”,装着一段完成签名的历史数据没有意义)。打开开关后行为急转:源码把输入里检测到的签名字节全部丢弃后继续转换。这个”丢弃”必须被理解为不可逆的信息损毁——那段 scriptSig 可能是唯一记录着已收集签名的地方,转完 PSBT 再 finalize 出来的交易签名已经不在。命令文档把这层含义写得很直白:true 时”任何输入中的签名将被丢弃并继续转换”。只有两种正当场景:一是明知输入是占位垃圾数据;二是你确切知道签名字节的去向备份。默认 false 是源码替你做的安全选择,脚本包装时不要用宽松解析器把它悄悄翻转。

iswitness:让解码不再靠猜

第三个参数 iswitness 处理的是裸交易格式的著名歧义:同一串十六进制按”带见证字段”和”不带见证字段”两种语法解析都可能成功。默认省略时命令按启发式测试判定,这与 decoderawtransaction 家族一致。文档建议:调用方如果确切知道交易是否带见证,应当显式传值——因为启发式误判的下游后果是让 segwit 交易走了非见证解析路径,转换出来的 PSBT 输入形状整个错位。对固定工具链而言,显式传 iswitness 是消除一整类偶发 bug 的廉价保险。

什么时候真的需要它

合理的清单其实很短:迁移旧的脚本化流程(历史上用裸 hex 流转的多签系统)到签名器时,用它接一段过渡期;对 fundrawtransaction 产物想继续走 PSBT 签名器而非钱包内签名,用它换轨;集成测试里构造 PSBT 初始状态。清单之外,新建流程的正确起点永远是直接产出 PSBT 的 createpsbt/walletcreatefundedpsbt——从源头避免格式退化,比事后补救便宜。转换命令的位置是”历史接缝”,把它理解成一种兼容层而不是功能,选型就不会错。

风险提示:本文是交易格式转换机制说明,涉及资产转移的流程请先小额演练;本文不构成投资建议。