AUG56 bitcoin body 250: createrawtransaction
比特币里绝大多数转账都从钱包命令出发,但有一类场景恰好相反:你没有热钱包、不想让私钥触网,只想先把一笔交易的骨架用十六进制拼出来,拿到离线机器上签名,再广播。承担这个角色的是 createrawtransaction。它只造不签、不存不播,帮助文本把这四点写得非常直白:交易输入不会被签名,也不会被存进钱包或发送到网络。理解它的五个参数,比记住命令名重要得多。
输入表:只认 txid 和 vout
第一个参数是输入数组,每个元素填 txid 和 vout,可选填 sequence。命令本身并不核实这些输出是否真的存在、是否还没被花掉,它只是把你写的数字序列化进交易。换句话说,用一笔早已花掉的输出也能成功造出一串十六进制,真正的判决发生在 testmempoolaccept 或 sendrawtransaction 阶段,由节点重新校验。拼完先预检再广播,是这条路线的基本纪律。
输出表:地址与数据两种格子
第二个参数是输出数组,每个元素要么是以地址为键、金额(单位为 BTC)为值的键值对,要么是一个 data 键配十六进制数据,后者会被装进一个 OP_RETURN 输出。这里有两条硬规则:同一个地址在数组里只能出现一次;data 输出最多只能有一个,且至少要有其中一个类型的输出。帮助文本还提到,出于兼容性,第二个参数也接受把键值对直接摊平的字典写法,但数组写法更不容易踩到重复键。
replaceable 默认是真:容易被忽略的 RBF 信号
第三个参数 locktime 默认 0;第四个参数 replaceable 默认值为真,也就是造出来的交易默认带 BIP125 可替换信号。这与直觉相反的地方在于:如果你显式给某些输入写了 sequence,而它的取值和 replaceable 的说法不相容,命令会直接报错,而不是悄悄以某一个为准。想让交易不可替换,要么把 replaceable 设为假,要么把所有输入的 sequence 写到不可替换的取值,两边必须自洽。
version 是 v30 才新开的一格
从 Bitcoin Core 30.0 起,createrawtransaction、createpsbt、send、sendall、walletcreatefundedpsbt 五个命令统一增加了 version 参数,允许指定标准版本号,默认值即当前标准版本。这一格的意义在测试和特殊协议场景:例如想造一笔不带任何替换语义暗示的 v1 交易,或者在 regtest 上演练版本相关规则。普通转账不需要动它。
它不做的事,恰好都要有人做
和 fundrawtransaction 或钱包的 send 相比,createrawtransaction 不选币、不造找零、不估费用:输入总额减去输出总额剩下的部分全部成为手续费,算错方向就可能把大额找零整笔烧掉。工程上常见的补救是在流程末端加一步自动核对:把造好的十六进制交给 decoderawtransaction 回读,逐项比对输入、输出、找零和估算的费差,确认无误再进入签名环节。离线签名流程里每个环节的账都应该由机器复核,而不是靠操作者的眼睛。
三条常见误读,各对应一个动作
第一条误读是把它当发号机:以为 createrawtransaction 会像钱包命令一样自动补齐找零,于是输入写一枚大额 UTXO、输出只写收款金额,剩下的整笔进了矿工的口袋。这条命令的字典里没有找零二字,输出数组写几笔就是几笔,差额全部计为费用,动作上应当把找零输出当作必填项写进模板。第二条误读是把成功返回当成校验通过:造出的十六进制哪怕指向不存在的输出,命令也照样给出字符串,真正的裁判在预检与广播环节,所以离线流程里十六进制在过私钥之前应该先让联网节点跑一次只读校验,把无效输入挡在签名之前。第三条误读是忽略默认值的时代性:早年的裸交易命令不带替换信号,现在的默认值是可替换,两边工具对同一笔骨架算出的交易编号可能不同,跨工具传参时把 replaceable 与 locktime、sequence 一起写全,让每个环节读到的都是同一种语义,而不是各自信任各自的默认。
风险提示:手工构造交易可能因输错金额、漏写找零或选错输入造成资产损失,且链上交易一经确认不可撤销;本文为机制说明,不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。