Golang开发比特币测试网原生交易触发mandatory-script-verify-flag报错
比特币原始交易验证失败排查方向
直接可定位的异常点
从现有btcdeb输出可直接发现两处核心问题:
- 赎回脚本解析完全错乱:正常P2SH解锁流程应按顺序将签名、公钥、完整赎回脚本压入栈后执行验证;当前输出中赎回脚本被拆解为无意义的零散操作码(出现
OP_UNKNOWN、错误的操作码匹配结果),不满足有效脚本的结构要求。 - 见证字段完全缺失:工具输出提示
got witness stack of size 0,若所花费的UTXO为P2WPKH/P2WSH类隔离见证类型,无见证结构的交易将直接触发验证失败。
逐字段校验维度
- UTXO匹配校验
- 核对交易vin中引用的UTXO索引:当前btcdeb识别的输入对应的是关联交易的1号输出,但构造的交易vin中写入的vout索引为0号,索引不匹配会导致脚本查找错误。
- 核对UTXO脚本类型:若UTXO为P2SH嵌套见证类型,交易结构必须携带符合规范的witness字段,不能仅将签名、公钥填充到scriptSig字段中——该类场景下scriptSig仅需存放赎回脚本的HASH值,实际签名、公钥、赎回脚本需放入witness栈。
- scriptSig结构校验
- 当前构造的scriptSig长度为
0x8a(138字节),结构为0x47 <DER格式签名> 0x41 <未压缩公钥>,该结构仅适用于普通P2PKH类型UTXO的花费流程,完全不兼容P2SH类型UTXO的解锁要求。 - P2SH类型UTXO的scriptSig正确结构为:依次放入所有解锁所需的栈元素,最后一个元素必须是完整序列化的赎回脚本(redeemScript),不能直接将签名、公钥作为scriptSig的全部内容。
- 当前构造的scriptSig长度为
签名正确性校验
- 签名预镜像校验
- 核对签名时使用的sighash预镜像计算逻辑,根据UTXO类型匹配对应的计算规则:普通P2PKH类型的签名需将原UTXO的scriptPubKey纳入预镜像计算范围;P2SH嵌套见证类型的签名需严格按照隔离见证的sighash计算规则,逐位匹配输入金额、输入输出哈希、锁定时间等字段,不能漏项。
- 核对签名使用的UTXO金额值:btcdeb识别的当前输入UTXO金额为1474796聪,需确认计算签名时使用的金额与该值完全一致,任何字节偏差都会导致签名验证失败。
- 公钥格式校验
- 当前使用的公钥为未压缩格式(长度
0x41,前缀0x04),若UTXO对应的公钥HASH160是基于压缩公钥计算得出,未压缩公钥算出的HASH值永远无法匹配,最终脚本栈顶必然为false值。
- 当前使用的公钥为未压缩格式(长度
- 签名标志校验
- 当前签名尾部携带的sighash标志为
0x01(SIGHASH_ALL),需确认该标志与构造交易时设置的签名标志完全一致,标志不匹配会导致签名被判定为无效。
- 当前签名尾部携带的sighash标志为
脚本执行栈调试方法
- 用btcdeb的单步执行功能,每执行一个操作码即时观察栈的变化:
- 正常脚本执行完成后,栈顶必须为非空的true值(即非零元素),若最终栈为空、或栈顶为零值,就会触发当前的
mandatory-script-verify-flag-failed报错。 - 逐字节对比HASH计算结果:比如执行
OP_HASH160时,栈内公钥计算得出的HASH160值,必须和scriptPubKey内嵌的目标HASH完全一致,哪怕单字节偏差都会导致OP_EQUAL操作返回false。
- 正常脚本执行完成后,栈顶必须为非空的true值(即非零元素),若最终栈为空、或栈顶为零值,就会触发当前的
内容的提问来源于stack exchange,提问作者it4ddict
相关产品推荐
相关产品推荐

