学习视频来源:https://www.bilibili.com/video/BV1Vt411X7JF/?p=9
本博客除了包含自己的在学习过程中记录的笔记外,还包含少部分自己扩展的内容,如有错误,敬请指正。
文章目录
- 1.比特币脚本
- 2.交易结构与脚本执行模型
-
- [2.1 输入(Input)](#2.1 输入(Input))
- [2.2 输出(Output)](#2.2 输出(Output))
- [3. 脚本类型](#3. 脚本类型)
-
- [3.1 P2PK(Pay-to-Public-Key)](#3.1 P2PK(Pay-to-Public-Key))
- [3.2 P2PKH(Pay-to-Public-Key-Hash)最常用](#3.2 P2PKH(Pay-to-Public-Key-Hash)最常用)
- [3.3 P2SH(BIP-16):支持复杂逻辑](#3.3 P2SH(BIP-16):支持复杂逻辑)
-
- [为什么需要 P2SH?](#为什么需要 P2SH?)
- [P2SH 工作流程](#P2SH 工作流程)
- 验证
- [3.4 Proof of Burn(销毁证明,特殊脚本)](#3.4 Proof of Burn(销毁证明,特殊脚本))
- [4 总结](#4 总结)
1.比特币脚本
比特币使用一种基于栈的、无状态、非图灵完备的脚本语言来控制交易的花费逻辑。与 C++ 等高级语言不同,它没有全局变量、内存管理或循环结构,所有操作都通过对栈的压入与验证完成。
2.交易结构与脚本执行模型
2.1 输入(Input)
表示"这笔钱来自哪一笔交易的哪个输出"。包含:
txid+output index:引用前序 UTXO;sigscript(即scriptSig):解锁脚本,提供签名和公钥;pkscript:前序交易对应输出的锁定脚本(用于验证)。
2.2 输出(Output)
表示"这笔钱给谁、如何花"。 包含:
value:金额(satoshi);pkscript(即scriptPubKey):锁定脚本,定义花费条件。
脚本的执行方式是将输入的解锁脚本(scriptSig)与前一笔交易对应输出的锁定脚本(scriptPubKey)直接拼接成一个连续的脚本,然后由脚本引擎从左到右一次性执行, 后因安全原因改为分步执行 :先运行 scriptSig 压栈,再运行 scriptPubKey 验证。
3. 脚本类型
3.1 P2PK(Pay-to-Public-Key)
- 输出脚本 :
PUSHDATA(PubKey) CHECKSIG - 输入脚本 :
PUSHDATA(Signature) - 已基本淘汰(公钥直接暴露)。
3.2 P2PKH(Pay-to-Public-Key-Hash)最常用
-
输出脚本 :
textDUP HASH160 <20-byte PubKeyHash> EQUALVERIFY CHECKSIG -
输入脚本 :
textPUSHDATA(Signature) PUSHDATA(PubKey) -
双重验证 :
- 公钥哈希 = 输出中指定的哈希;
- 签名能被该公钥验证。
真实交易示例分析
当前交易(发送者)
找的是和课堂上老师用的例子。来自 https://www.blockchain.com/explorer/transactions/btc/921af728159e3019c18bbe0de9c70aa563ad27f3f562294d993a208d4fcfdd24
json
{
"txid": "921af728159e3019c18bbe0de9c70aa563ad27f3f562294d993a208d4fcfdd24",
"size": 226,
"version": 1,
"locktime": 0,
"fee": 29040,
"inputs": [
{
"coinbase": false,
"txid": "c0cb92ca8e41070233bf965d808b0fc4bac144dab05690b17823fac3e184c57b",
"output": 0,
"sigscript": "483045022100928496fb0d2a25e4e7c99b9c60d4d0d12fcf8974a0faffcb30119b0d385872a30220253d3d0c507e5e44e123bc28b795ab4a38bf3b205455403e77aa72d58d9e17110121022ef8d3a6dd8a7039e513acc8ecf9b094ed7e85439824a1d11920f85927cd0018",
"sequence": 4294967295,
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 76469684,
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"witness": []
}
],
"outputs": [
{
"address": "19z8LJkNXLrTv2QK5jgTncJCGUEEfpQvSr",
"pkscript": "76a914628ed6567c0b9056067309f07bbea2992ecad74388ac",
"value": 22684000,
"spent": true,
"spender": {
"txid": "437f8e2d8b33dc46f73e8d57be5fc739c5a70d2dc02e1326a6a530adf4c3c57b",
"input": 0
}
},
{
"address": "1LvGTpdyeVLcLCDK2m9f7Pbh7zwhs7NYhX",
"pkscript": "76a914da7d57dfd02c6f5a9c649e891b5ac199ad012cd288ac",
"value": 53756644,
"spent": true,
"spender": {
"txid": "a9fcce7933c672b058a4c9534ca1e975db002f85d19ef7124356e7285c48c428",
"input": 0
}
}
],
"block": {
"height": 530657,
"position": 25
},
"deleted": false,
"time": 1530846727,
"rbf": false,
"weight": 904
}
输入脚本解析(sigscript)
text
PUSHDATA(72) 3045022100928496fb0d2a25e7c99b9c60d4d0d12fcf8974a0faffcb30119b0d385872a30220253d3d0c507e5e44e123bc28b795ab4a38bf3b205455403e77aa72d58d9e171101
PUSHDATA(33) 022ef8d3a6dd8a7039e513acc8ecf9b094ed7e85439824a1d11920f85927cd0018
- 第一部分:72 字节 DER 签名 +
01(SIGHASH_ALL); - 第二部分:33 字节压缩公钥。
前一笔交易(资金来源)
txid: c0cb92ca8e41070233bf965d808b0fc4bac144dab05690b17823fac3e184c57b, output 0
json
{
"txid": "c0cb92ca8e41070233bf965d808b0fc4bac144dab05690b17823fac3e184c57b",
"size": 475,
"version": 1,
"locktime": 0,
"fee": 82620,
"inputs": [
{
"coinbase": false,
"txid": "343dd4e72c2930920165b00bd0e6e5f1ff58f39a0eef4bab693c9f6d2dca58c4",
"output": 1,
"sigscript": "4830450221008bdde213541181b84a9293b93596b78b372d940ae4afae10c3f0d5efbcc4455902206d6528cc6ed0ddfaf0c695bec398b556d3260500f741fa4289a88d8a599060e301210270c79aaaf9fdf9ffec4d86303c61d7d755862c1828dd65b57099d96182e418e2",
"sequence": 4294967295,
"pkscript": "76a914e3be4f0efcd56a44a31d8afdb57f1d8a30f361c088ac",
"value": 12978756,
"address": "1MmCNSBzRFE3B3hi5c7eGryx6uGtvDQNTD",
"witness": []
},
{
"coinbase": false,
"txid": "8482405c4f2df5fce6161a0e0b8271725a881f299842f94e90864ca44cb4e5ba",
"output": 8,
"sigscript": "473044022052940cb78c8e8fa3830a3136ae4364f08e32f45633bb2b0272bdc2d2b82751e1022046199239f57d1bde462dcec6947aba1eb419f3ba099ef36b643a6713233b38170121021033831adce9027538a5bb76c5ea3fa90156c80c6d890914322696695be47571",
"sequence": 4294967295,
"pkscript": "76a914eac94a3f1432476e7f3f1f0dcbfaed206d65986688ac",
"value": 463573548,
"address": "1NQSFmLbKCvP7J9rUcLwBH73ML351dXJPu",
"witness": []
}
],
"outputs": [
{
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 76469684,
"spent": true,
"spender": {
"txid": "921af728159e3019c18bbe0de9c70aa563ad27f3f562294d993a208d4fcfdd24",
"input": 0
}
},
{
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 100000000,
"spent": true,
"spender": {
"txid": "600275ef9a3452bdca9758d464c5879df8bd0cc7af1d72b5aeaf38685635199b",
"input": 1
}
},
{
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 100000000,
"spent": true,
"spender": {
"txid": "600275ef9a3452bdca9758d464c5879df8bd0cc7af1d72b5aeaf38685635199b",
"input": 2
}
},
{
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 100000000,
"spent": true,
"spender": {
"txid": "600275ef9a3452bdca9758d464c5879df8bd0cc7af1d72b5aeaf38685635199b",
"input": 3
}
},
{
"address": "1MaBFqBEfcQyXPv3fm5WAW9aQuJuKHaA3A",
"pkscript": "76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac",
"value": 100000000,
"spent": true,
"spender": {
"txid": "d3fb29551a956b9d857761bfefe336f7aab90a2759992c4975df6ab97dd51cd3",
"input": 0
}
}
],
"block": {
"height": 530654,
"position": 15
},
"deleted": false,
"time": 1530845388,
"rbf": false,
"weight": 1900
}
对应输出脚本(pkscript)
hex
76a914e1a8cdae6411b17ee1d4cecfe47bafce37e14d1488ac
解析为:
text
OP_DUP OP_HASH160 e1a8cdae6411b17ee1d4cecfe47bafce37e14d14 OP_EQUALVERIFY OP_CHECKSIG
拼接后完整脚本执行
text
PUSHDATA(72) <签名>
PUSHDATA(33) <公钥>
OP_DUP
OP_HASH160
PUSHDATA(20) e1a8cdae6411b17ee1d4cecfe47bafce37e14d14
OP_EQUALVERIFY
OP_CHECKSIG
验证通过,说明提供的公钥哈希匹配 且签名有效。
3.3 P2SH(BIP-16):支持复杂逻辑
为什么需要 P2SH?
- 多重签名等复杂脚本太长,放在输出中不友好;
- 用户需提前知道所有公钥,体验差。
比如电商场景:用户只需向商家公布的 P2SH 地址付款,无需关心内部是 3-of-5 还是 2-of-3。商家可随时更换策略,只需发布新脚本的哈希。
P2SH 工作流程
-
接收方构造 赎回脚本(Redeem Script),如多签脚本;
-
计算其
HASH160→ 得到redeemScriptHash; -
输出脚本简化为:
textOP_HASH160 PUSHDATA(redeemScriptHash) OP_EQUAL -
花费时,输入脚本提供:
textPUSHDATA(Sig1) ... PUSHDATA(SigM) PUSHDATA(serialized_redeemScript)
验证
- 验证
HASH160(serialized_redeemScript) == redeemScriptHash; - 反序列化并执行
redeemScript,验证签名。
电商场景:用户只需向商家公布的 P2SH 地址付款,无需关心内部是 3-of-5 还是 2-of-3。商家可随时更换策略,只需发布新脚本的哈希。
3.4 Proof of Burn(销毁证明,特殊脚本)
脚本形式
text
OP_RETURN <任意数据>
特性
- Provably Unspendable:因为第一句是return,所有后边的数据都不会执行,任何尝试花费该输出的交易都会失败。 UTXO 可被剪枝,节省节点存储。
常用的2个场景
- Altcoin 分发:销毁 BTC 换取新币;
- 区块链存证:写入哈希值作为不可篡改证据(如版权、合同摘要)。类似与coinBase,但是coinBase只能在铸币交易写入,而这个可以用于任何交易。
4 总结
比特币脚本语言非常简单的,但在密码学方面异常强大,比如一行代码检查多重签名 ,一个脚本哈希就可以代表万般逻辑!