The BitCoin Scripting Language
交易实例
交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d 5c0b", "confirmations": 23, "time": 1530846727, "blocktime": 1530846727 }
交易的输入 "vin": [{ "txid": "c0cb c57b", "vout": 0, "scriptsig": { "asm": "3045...0018", "hex": "4830...0018" }, }], 这里的 scriptsig 之后将以 input script 指代
交易的输出 "vout": [{ "value": 0.22684000, "n": 0, "scriptpubkey": { "asm": "DUP HASH160 628e d743 EQUALVERIFY CHECKSIG", "hex": "76a9 88ac", "reqsigs": 1, "type": "pubkeyhash", "addresses": [ "19z8LJkNXLrTv2QK5jgTncJCGUEEfpQvSr"] } },{ "value": 0.53756644, "n": 1, "scriptpubkey": { "asm": "DUP HASH160 da7d 2cd2 EQUALVERIFY CHECKSIG", "hex": "76a9 88ac", "reqsigs": 1, "type": "pubkeyhash", "addresses": ["1LvGTpdyeVLcLCDK2m9f7Pbh7zwhs7NYhX"] } }], 这里的 scriptpubkey 之后将以 output script 指代
A B B C TX: A B TX: B C vin: txid vout input script vout: value n output script vin: txid vout input script vout: value n output script
A B B C TX: A B TX: B C vin: txid vout input script vout: value n output script vin: txid vout input script vout: value n output script input script output script 拼接成一段完整的在栈上运行的脚本
P2PK (Pay to Public Key) input script: PUSHDATA(Sig) output script: PUSHDATA(PubKey) CHECKSIG
PUSHDATA(Sig) PUSHDATA(PubKey) CHECKSIG
PUSHDATA(Sig) PUSHDATA(PubKey) CHECKSIG Sig
PUSHDATA(Sig) PUSHDATA(PubKey) CHECKSIG PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) CHECKSIG TRUE
实例 交易 ea44e97271691990157559d0bdd9959e02790c34db6c006d779e82fa5aee708e 的第一个输入 : 交易 f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 的第一个输出 :
P2PKH (Pay to Public Key Hash) input script: PUSHDATA(Sig) PUSHDATA(PubKey) output script: DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG PubKey PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG PubKeyHash PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG PubKeyHash PubKeyHash PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG PubKey Sig
PUSHDATA(Sig) PUSHDATA(PubKey) DUP HASH160 PUSHDATA(PubKeyHash) EQUALVERIFY CHECKSIG TRUE
实例 交易 921af728159e3019c18bbe0de9c70aa563ad27f3f562294d993a208d4fcfdd24 的第一个输入 : 交易 c0cb92ca8e41070233bf965d808b0fc4bac144dab05690b17823fac3e184c57b 的第一个输出 :
P2SH (Pay to Script Hash) 采用 BIP16 的方案 input script: PUSHDATA(Sig) PUSHDATA(serialized redeemscript) output script: HASH160 PUSHDATA(redeemScriptHash) EQUAL
进一步说明 input script 要给出一些签名 ( 数目不定 ) 及一段序列化的 redeemscript 验证时分两步 : 第一步验证这段序列化的 redeemscript 是否与 output script 中的哈希值匹配? 第二步反序列化并执行 redeemscript, 配合前边的签名是否可以执行通过? redeemscript 可以设计成多种形式, 比如前面介绍的 P2PK 或者 P2PKH 形式, 以及后面要介绍的多重签名形式
用 P2SH 实现 P2PK redeemscript: PUSHDATA(PubKey) CHECKSIG input script: PUSHDATA(Sig) PUSHDATA(serialized redeemscript) output script: HASH160 PUSHDATA(redeemScriptHash) EQUAL
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL serirs Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL RSH Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL RSH RSH Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(Sig) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(PubKey) CHECKSIG Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(PubKey) CHECKSIG PubKey Sig serirs: serialized RedeemScript RSH: RedeemScriptHash
P2SH+P2PK 的执行 PUSHDATA(PubKey) CHECKSIG TRUE serirs: serialized RedeemScript RSH: RedeemScriptHash
多重签名 最早的多重签名, 目前已经不推荐使用 input script: x PUSHDATA(Sig_1) PUSHDATA(Sig_2)... PUSHDATA(Sig_M) outputscript: M PUSHDATA(pubkey_1) PUSHDATA(pubkey_2)... PUSHDATA(pubkey_N) N CHECKMULTISIG
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG 2 Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_1 2 Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_2 pubkey_1 2 Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_3 pubkey_2 pubkey_1 2 Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG 3 pubkey_3 pubkey_2 pubkey_1 2 Sig_2 Sig_1
PUSHDATA(Sig_1) PUSHDATA(Sig_2) 2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG TRUE
用 P2SH 实现多重签名 input script: x PUSHDATA(Sig_1) PUSHDATA(Sig_2)... PUSHDATA(Sig_M) redeemscript: M PUSHDATA(pubkey_1) PUSHDATA(pubkey_2)... PUSHDATA(pubkey_N) N CHECKMULTISIG PUSHDATA(serialized RedeemScript) output script: HASH160 PUSHDATA(RedeemScriptHash) EQUAL
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL Sig_2 Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL serirs Sig_2 Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL RSH Sig_2 Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL RSH RSH Sig_2 Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
PUSHDATA(Sig_1) PUSHDATA(Sig_2) PUSHDATA(seriRS) HASH160 PUSHDATA(RSH) EQUAL Sig_2 Sig_1 serirs: serialized RedeemScript RSH: RedeemScriptHash
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG 2 Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_1 2 Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_2 pubkey_1 2 Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG pubkey_3 pubkey_2 pubkey_1 2 Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG 3 pubkey_3 pubkey_2 pubkey_1 2 Sig_2 Sig_1
2 PUSHDATA(pubkey_1) PUSHDATA(pubkey_2) PUSHDATA(pubkey_3) 3 CHECKMULTISIG TRUE
实例 交易 bc26380619a36e0ecbb5bae4eebf78d8fdef24ba5ed5fd040e7bff37311e180d 的第一个输入 : push 的最后一个数据是序列化的脚本, 反序列化后得到 : 2 027c 74a3 022c c94b 0357 ce3a 3 CHECKMULTISIG 交易 0ac29fc675909eb565a0984fe13a47dae16ca53fb477b9e03446c898b925ab6b 的第二个输出 :
Proof of Burn output script: RETURN [zero or more ops or text] 包含了这样的 output script 的 output 被称为 Provably Unspendable/Prunable Outputs 假如有一个交易的 input 指向这个 output, 不论 input 里的 input script 如何设计, 执行到 RETURN 这个命令之后都会直接返回 false,return 后面的其他指令也就不会执行了, 所以这个 output 无法再被花出去, 对应的 UTXO 也就可以被剪枝了, 无需保存
实例 这是一个 coinbase 交易, 第二个输出对应的 value 是 0, 矿工利用 Null Data 的特性, 在 RETURN 后边记录了一些信息
实例