比特币标准脚本

比特币标准脚本是如何运行的

在 GitHub 上查看 Demo 代码"标准比特币脚本"

我告诉过你比特币脚本是什么,但没有确切说明它的用途。顺便说一下,在关于交易处理的文章中,我通过介绍交易输入和输出,概述了比特币如何流动。我们即将连接这些点。

验证脚本

到目前为止,我们了解到脚本是一段执行并产生结果的代码。当从未花费的交易输出(UTXO)构建交易时,有两个脚本我们特别感兴趣:

  • 未花费的输出脚本,称之为 OS
  • 花费输入脚本,称之为 IS

问题在于生成这样的 IS,使得连接的脚本 VS = IS + OS(即 验证脚本),在执行后返回非零值。考虑到这一点,验证脚本决定了交易输入是否有权花费之前的未花费输出。这听起来可能很难理解,但其实并不难。

考虑输入脚本:

OP_6 OP_DUP

以及之前的输出脚本:

OP_ADD OP_12 OP_EQUAL

现在将它们连接起来,得到以下验证脚本:

OP_6 OP_DUP OP_ADD OP_12 OP_EQUAL

看看堆栈是如何演变的:

[]
[6]
[6, 6]
[12]
[12, 12]
[1]

很好,验证脚本在堆栈上以 1 (OP_TRUE) 结束,因此输入脚本可以花费之前的输出脚本。

弱点

事实上,许多其他输入脚本也符合要求,例如:

OP_4 OP_8

或者:

OP_1 OP_15 OP_ADD OP_7 OP_SUB OP_3

看看任何有基本数学知识的人如何轻易地偷走输出币。相反,看看这个非常简单的输出脚本:

OP_FALSE

无论输入脚本是什么,验证脚本都不会成功。任何发送到这个输出的比特币将永远丢失。

事实上,所有上述脚本都是危险的,并且会被主网拒绝,因为它们不是_标准_的。矿工不接受非标准脚本的交易,因为在许多情况下,它们可能会直接或间接导致资金损失。

比特币标准脚本

实际上,任何类型的脚本都可以包含在交易中。不过,出于安全原因,只有标准脚本会被主网矿工接受。“标准”一词来自 IsStandard 检查,这是 Bitcoin Core 中的一段代码,确保脚本符合几种众所周知的类别之一。

截至 Bitcoin Core 0.10,这些被认为是标准脚本:

  1. P2PKH(pay-to-public-key-hash 支付到公钥哈希)
  2. P2SH(pay-to-script-hash 支付到脚本哈希)
  3. P2PK(pay-to-public-key 支付到公钥)
  4. 多重签名
  5. OP_RETURN 元数据

在本课程中,我们只讨论前几种。供你参考,测试网矿工完全跳过 IsStandard 检查,因此测试网网络适合尝试实验性脚本。

P2PKH 脚本

区块链中最常见的标准脚本以 P2PKH 地址(支付到公钥哈希)命名。通过拥有一个目标 P2PKH 比特币地址,我们可以编写一个输出脚本,将币发送到该地址。通过拥有生成目标地址的私钥,我们可以编写一个输入脚本,稍后花费这些币。

输出脚本

P2PKH 输出脚本包含一个 Base58Check 解码的目标地址,即 ECDSA 公钥的 hash160:

OP_DUP
OP_HASH160
[hash160(public_key)]
OP_EQUALVERIFY
OP_CHECKSIG

以我们的示例压缩公钥为例:

02
82 00 6e 93 98 a6 98 6e
da 61 fe 91 67 4c 3a 10
8c 39 94 75 bf 1e 73 8f
19 df c2 db 11 db 1d 28

及其 hash160 摘要:

6b f1 9e 55 f9 4d 98 6b
46 40 c1 54 d8 64 69 93
41 91 95 11

在测试网版本化和 Base58Check 编码后显示为:

mqMi3XYqsPvBWtrJTk8euPWDVmFTZ5jHuK

将钱发送到此地址的输出脚本是:

76 (OP_DUP)
a9 (OP_HASH160)

14 6b f1 9e 55 f9 4d 98
6b 46 40 c1 54 d8 64 69
93 41 91 95 11

88 (OP_EQUALVERIFY)
ac (OP_CHECKSIG)

其中 14 是一个隐式推送操作码,表示接下来有 20 个字节,即 hash160 摘要。单独的输出脚本在不知道相应的输入脚本的情况下是没有意义的,所以继续阅读。

输入脚本

P2PKH 输入脚本包含一个 DER 编码的 ECDSA 签名和一个原始公钥,可以是未压缩的或压缩的。在这样的输入脚本中,除了推送操作码外,没有其他操作码:

[signature] 
[public_key]

例如,取自 ECDSA 章节的 70 字节签名,并附加 SIGHASH_ALL 常量 (01):

30 44
02 20
2b 2b 52 9b db dc 93 e7
8a f7 e0 02 28 b1 79 91
8b 03 2d 76 90 2f 74 ef
45 44 26 f7 d0 6c d0 f9
02 20
62 dd c7 64 51 cd 04 cb
56 7c a5 c5 e0 47 e8 ac
41 d3 d4 cf 7c b9 24 34
d5 5c b4 86 cc cf 6a f2
01

SIGHASH 后缀是与合约相关的高级主题。在本系列中,我们将坚持使用 SIGHASH_ALL,因为我们将始终签署所有交易输入。

如果你现在取前一段中的公钥,你就有了一个典型的输入脚本:

47 30 44 02 20 2b 2b 52
9b db dc 93 e7 8a f7 e0
02 28 b1 79 91 8b 03 2d
76 90 2f 74 ef 45 44 26
f7 d0 6c d0 f9 02 20 62
dd c7 64 51 cd 04 cb 56
7c a5 c5 e0 47 e8 ac 41
d3 d4 cf 7c b9 24 34 d5
5c b4 86 cc cf 6a f2 01

21 02 82 00 6e 93 98 a6
98 6e da 61 fe 91 67 4c
3a 10 8c 39 94 75 bf 1e
73 8f 19 df c2 db 11 db
1d 28

其中 4721 是推送的签名和公钥的十六进制长度。

验证

如果我们想花费我们在示例地址上收到的钱,我们必须提供一个特定的输入脚本,以便复合验证脚本成功。如果输入是“真实的”,则以下脚本将返回非零值:

[signature]
[public_key]
OP_DUP
OP_HASH160
[hash160(public_key)]
OP_EQUALVERIFY
OP_CHECKSIG

如果输入脚本有效,逐步描述如下:

  1. 输入签名被推送。
  2. 输入公钥被推送。
  3. 堆栈顶部项(公钥)被复制。
  4. 堆栈顶部项(公钥)被 hash160 哈希。
  5. 输出 hash160 被推送。
  6. 输入和输出 hash160 被弹出并检查是否相等。
  7. 输入签名根据公钥进行验证。
  8. OP_TRUE 作为签名验证成功的结果被推送。

看看堆栈上发生了什么:

[]
[signature]
[signature, public_key]
[signature, public_key, public_key]
[signature, public_key, hash160(public_key)]
[signature, public_key, hash160(public_key), hash160(public_key)]
[signature, public_key]
[1]

最终堆栈持有 OP_TRUE,因此交易输入是合法的。在此过程中,满足了两个约束:

  1. 输入脚本中的公钥必须哈希到输出脚本中的比特币地址(步骤 6)。
  2. 签名必须对公钥有效(步骤 7)。

你可能认为单独的输入脚本足以进行签名验证,但你错了。我没有提到验证过程的第三个参数:消息!这将在接下来的关于交易的文章中讨论,供你参考,这将是一个棘手的话题。

顺便说一下,你是否也能看到知道私钥是否与未压缩或压缩公钥相关联的重要性?如果公钥和地址之间存在“压缩不匹配”,第一个约束将被打破。因此,你不能使用包含未压缩公钥的输入脚本来花费发送到压缩地址的比特币,反之亦然。

下一篇?

你已经了解到,比特币网络只接受所有可能脚本中的标准子集。P2PKH 脚本是区块链中最常见的标准脚本。输入和输出脚本共同形成验证脚本。矿工执行验证脚本以接受或拒绝交易。

下一篇文章中,我们将最终开始分析交易。你即将理解比特币的魔力。如果你喜欢这篇文章,请分享 。

我是 AI 翻译官,为大家转译优秀英文文章,如有翻译不通的地方,在这里修改,还请包涵~

点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Davide De Rosa
Davide De Rosa
江湖只有他的大名,没有他的介绍。