理解比特币脚本的堆栈操作
在 GitHub 上查看 Demo 代码"比特币脚本语言"
在第一部分中,我介绍了用于常量和推送数据的 Script 操作码。我们正在慢慢接近你将在比特币实际交易中包含的脚本。具体来说,我们必然会在某个时候处理哈希和 ECDSA 签名,这就是为什么 Script 甚至有用于加密函数的操作码。
看看一些常见的算术操作码:
操作码 | 编码 |
---|---|
OP_ADD |
93 |
OP_SUB |
94 |
这两者都是完全基于堆栈的操作,意味着它们不需要显式参数。OP_ADD
(OP_SUB
)弹出堆栈顶部的两个项目并将它们相加(相减)。操作的结果然后再次推到顶部。
示例:
55 59 93 56 94
或者:
OP_5 OP_9 OP_ADD OP_6 OP_SUB
这是堆栈的演变过程:
[]
[5]
[5, 9]
[14]
[14, 6]
[8]
脚本返回 8。
同样,脚本用于交易验证,比较是验证者的主要需求:
操作码 | 编码 |
---|---|
OP_EQUAL |
87 |
OP_EQUAL
弹出并比较堆栈顶部的两个项目,然后如果它们相等则推送 OP_TRUE
,否则推送 OP_FALSE
。
示例:
02 c3 72 02 03 72 01 c0 93 87
或者:
[c3 72] [03 72] [c0] OP_ADD OP_EQUAL
这是堆栈的演变过程:
[]
[c3 72]
[c3 72, 03 72]
[c3 72, 03 72, c0]
[c3 72, c3 72]
[1]
值得注意的是,脚本最终“成功”,因为它返回 OP_TRUE
。
这是你将用于堆栈操作的唯一操作码:
操作码 | 编码 |
---|---|
OP_DUP |
76 |
OP_DUP
不需要参数,它只是复制堆栈顶部的项目。
示例:
02 c3 72 02 03 72 01 c0 93 87
或者:
[b9 0c a2 fe] OP_DUP OP_EQUAL
这是堆栈的演变过程:
[]
[b9 0c a2 fe]
[b9 0c a2 fe, b9 0c a2 fe]
[1]
显然,脚本成功,因为 OP_EQUAL
在 OP_DUP
之后永远不会失败!
这些操作码无疑是最有趣的:
操作码 | 编码 |
---|---|
OP_HASH160 |
a9 |
OP_CHECKSIG |
ac |
OP_HASH160
弹出堆栈顶部的项目,对其执行 hash160,然后将结果推回。基本上,这个操作码计算出比特币 P2PKH 地址,从 ECDSA 公钥生成。
OP_CHECKSIG
弹出堆栈顶部的两个项目,第一个是 ECDSA 公钥,第二个是 DER 编码的 ECDSA 签名。之后,如果签名对该公钥有效,则推送 OP_TRUE
,否则推送 OP_FALSE
。这是 Script 版本的 OpenSSL 的 ECDSA_verify
。
这两个操作码将在下一篇文章中描述。
本章没有代码示例。最终,脚本是一个数据数组,你唯一的贡献是将操作码名称映射到原始字节。我们本可以开发一个小型的 Script 解释器,但这远远超出了我们的目标。典型的比特币客户端不会运行脚本,因为这是一个挖矿任务,所以我们的关注点只是编写矿工会接受的格式良好的脚本。
你学习了一些更多的 Script 操作码,包括对 ECDSA 验证至关重要的加密函数。
在下一篇文章中,我们将探讨密钥和地址在_比特币标准脚本_中的作用。如果你喜欢这篇文章,请分享,并使用下面的表单提出问题和评论!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!