比特币锁定/解锁脚本工作原理及《Mastering Bitcoin》实操异常咨询
比特币锁定与解锁脚本工作原理
咱们先把这个核心逻辑讲透:比特币交易的有效性完全依赖**锁定脚本(ScriptPubKey)和解锁脚本(ScriptSig)**的配合执行,只有当两者组合运行后返回TRUE,这笔交易才会被网络认可。
- 锁定脚本(ScriptPubKey):这是附着在未花费UTXO上的“锁”,直白来说就是规定「谁才有资格花这笔钱」。最常用的P2PKH(支付到公钥哈希)脚本格式是:
OP_DUP OP_HASH160 <目标公钥哈希> OP_EQUALVERIFY OP_CHECKSIG,翻译成人话就是:你必须拿出对应的公钥,以及用该公钥对应私钥生成的签名,才能打开这把锁。 - 解锁脚本(ScriptSig):这是你在交易输入里附带的“钥匙”,包含满足锁定脚本要求的数据。比如P2PKH对应的解锁脚本就是
<签名> <公钥>,把这两个数据提供给节点,让它验证你是否有资格花费这笔UTXO。 - 验证执行过程:节点会把解锁脚本放在前面,锁定脚本接在后面,拼成完整脚本执行:
<签名> <公钥> OP_DUP OP_HASH160 <目标公钥哈希> OP_EQUALVERIFY OP_CHECKSIG
一步步拆解执行逻辑:- 先把签名和公钥压入脚本栈
OP_DUP复制栈顶的公钥,此时栈从顶到下为「公钥、公钥、签名」OP_HASH160对栈顶公钥计算哈希,得到公钥哈希值OP_EQUALVERIFY对比这个计算出的哈希和锁定脚本里的目标公钥哈希,不一致则直接终止并返回FALSE- 最后
OP_CHECKSIG用公钥验证签名的有效性,没问题就返回TRUE,交易通过验证
《Mastering Bitcoin》第6章操作错误排查
从你给出的ScriptSig内容来看,签名是标准DER格式(开头3045),末尾的01是SIGHASH_ALL标志位,格式上是对的,但结果出错大概率是这些细节没做好:
- 公钥不完整:你贴出的公钥末尾是
...,如果实际操作中你输入的公钥是截断的,OP_CHECKSIG必然验证失败。要确认公钥是完整的65字节(非压缩公钥开头为04,压缩公钥是02/03,这里你用的是非压缩公钥,必须凑足65字节)。 - 签名的交易哈希错误:比特币签名是对交易的特定哈希值生成的,如果你签名时没按规则排除当前输入的ScriptSig(SIGHASH_ALL会自动排除,避免循环依赖),或者漏了交易的输出金额、锁定脚本等关键字段,生成的签名就会无效。建议严格按照书中步骤重新构建待签名的交易结构,再用私钥重新生成签名。
- 锁定脚本与解锁脚本不匹配:先确认你要解锁的UTXO的锁定脚本内容——如果是P2PKH脚本,你需要用自己的公钥计算哈希,和锁定脚本里的哈希对比,确保两者完全一致。要是公钥哈希对不上,哪怕签名再正确也没用。
- 交易基础字段错误:比如你引用的UTXO的txid或输出索引填错了,或者输出金额计算错误(手续费不足或超过输入总和),这些都会导致整个交易验证失败,不一定是脚本本身的问题。
- 脚本拼接顺序错误:手动构建脚本时,千万别把锁定脚本放在前面、解锁脚本放在后面,节点验证时是解锁脚本在前,锁定脚本在后,顺序反了执行结果肯定是
FALSE。
给你一个具体的排查步骤:
- 找到你要解锁的UTXO的锁定脚本,用
OP_HASH160计算你提供的公钥的哈希,对比锁定脚本里的哈希值,确认是否一致。 - 严格按照书中步骤重新构建待签名的交易(注意排除当前输入的ScriptSig字段),用私钥重新生成签名。
- 手动模拟脚本执行:把解锁脚本和锁定脚本拼起来,一步步走栈操作,看哪一步返回
FALSE,就能精准定位问题。
内容的提问来源于stack exchange,提问作者ehds
相关产品推荐
相关产品推荐

