区块链

比特币的交易脚本执行过程解析

2018-05-10  本文已影响33人  DavieKong

比特币交易脚本语言,称为脚本,是一种类似Forth的逆波兰表达式的基于堆栈的执行语言。在UTXO上的锁定脚本和解锁脚本都以此脚本语言编写。 当一笔比特币交易被验证时,每一个输入值中的解锁脚本与其对应的锁定脚本同时 (互不干扰地)执行,以确定这笔交易是否满足支付条件。
他是一个安全的,非图灵完备的语言,目前,大多数经比特币网络处理的交易是以“Alice付给Bob”的形式存在,并基于一种称为“P2PKH”(Pay-toPublic-Key-Hash)脚本。但是,比特币交易不局限于“支付给Bob的比特币地址”的脚本。事实上,锁定脚本可以被编写成表达各种复杂的情况。为了理解这些更为复杂的脚本,我们必须首先了解交易脚本和脚本语言的基础知识。

图灵非完备性

比特币脚本语言包含许多操作码,但都故意限定为一种重要的模式——除了有条件的流控制以外,没有循环或复杂流控制能力。这样就保证了脚本语言的图灵非完备性,这意味着脚本有限的复杂性和可预见的执行次数。脚本并不是一种通用语言,这些限制确保该语言不被用于创造无限循环或其它类型的逻辑炸弹,这样的炸弹可以植入在一笔交易中,引起针对比特币网络的“拒绝服务”攻击。记住,每一笔交易都会被网络中的全节点验证,受限制的语言能防止交易验证机制被作为一个漏洞而加以利用。
二以太坊使用的solidity是一个图灵完备的语言,它为了防止大量的程序执行给网络带来巨大压力的做法是使用 Gas,合约的执行需要消耗Gas,Gas不够或者消耗完了,合约就不能执行了。

脚本构建

比特币的交易验证引擎依赖于两类脚本来验证比特币交易:锁定脚本和解锁脚本。

锁定脚本是一个放置在输出上面的花费条件:它指定了今后花费这笔输出必须要满足的条件。 由于锁定脚本往往含有一个公钥或比特币地址(公钥哈希值),在历史上它曾被称为脚本公钥(scriptPubKey)。由于认识到这种脚本技术存在着更为广泛的可能性,在本书中,我们将它称为“锁定脚本”(locking script)。在大多数比特币应用程序中,我们所称的“锁定脚本”将以scriptPubKey的形式出现在源代码中。您还将看到被称为见证脚本(witness script)的锁定脚本(参见[隔离见证]章节),或者更一般地说,它是一个加密难题(cryptographic puzzle)。 这些术语在不同的抽象层次上都意味着同样的东西。

解锁脚本是一个“解决”或满足被锁定脚本在一个输出上设定的花费条件的脚本,它将允许输出被消费。解锁脚本是每一笔比特币交易输入的一部分,而且往往含有一个由用户的比特币钱包(通过用户的私钥)生成的数字签名。由于解锁脚本常常包含一个数字签名,因此它曾被称作ScriptSig。在大多数比特币应用的源代码中,ScriptSig便是我们所说的解锁脚本。你也会看到解锁脚本被称作“见证”(witness 参见[隔离见证]章节)。在本书中,我们将它称为“解锁脚本”,用以承认锁定脚本的需求有更广的范围。但并非所有解锁脚本都一定会包含签名。

每一个比特币验证节点会通过同时执行锁定和解锁脚本来验证一笔交易。每个输入都包含一个解锁脚本,并引用了之前存在的UTXO。 验证软件将复制解锁脚本,检索输入所引用的UTXO,并从该UTXO复制锁定脚本。 然后依次执行解锁和锁定脚本。 如果解锁脚本满足锁定脚本条件,则输入有效(请参阅单独执行解锁和锁定脚本部分)。 所有输入都是独立验证的,作为交易总体验证的一部分。

请注意,UTXO被永久地记录在区块链中,因此是不变的,并且不受在新交易中引用失败的尝试的影响。 只有正确满足输出条件的有效交易才能将输出视为“开销来源”,继而该输出将被从未花费的交易输出集(UTXO set)中删除。

下图是最常见类型的比特币交易(P2PKH:对公钥哈希的付款)的解锁和锁定脚本的示例,显示了在脚本验证之前从解锁和锁定脚本的并置产生的组合脚本:


image.png

脚本执行堆栈

比特币的脚本语言被称为基于堆栈的语言,因为它使用一种被称为堆栈的数据结构。堆栈是一个非常简单的数据结构,可以被视为一叠卡片。栈允许两个操作:push和pop(推送和弹出)。 Push(推送)在堆栈顶部添加一个项目。 Pop(弹出)从堆栈中删除最顶端的项。栈上的操作只能作用于栈最顶端项目。堆栈数据结构也被称为“后进先出”( Last-In-First-Out)或 “LIFO” 队列。

脚本语言通过从左到右处理每个项目来执行脚本。数字(数据常量)被推到堆栈上。操作码(Operators)从堆栈中推送或弹出一个或多个参数,对其进行操作,并可能将结果推送到堆栈上。例如,操作码 OP_ADD 将从堆栈中弹出两个项目,添加它们,并将结果的总和推送到堆栈上。

条件操作码(Conditional operators)对一个条件进行评估,产生一个 TRUE 或 FALSE 的布尔结果(boolean result)。例如, OP_EQUAL 从堆栈中弹出两个项目,如果它们相等,则推送为 TRUE(由数字1表示),否则推送为 FALSE(由数字0表示)。比特币交易脚本通常包含条件操作码,以便它们可以产生用来表示有效交易的 TRUE 结果。

一个简单的脚本

现在让我们将学到的关于脚本和堆栈的知识应用到一些简单的例子中。

如图6-4,在比特币的脚本验证中,执行简单的数学运算时,脚本“ 2 3 OPADD 5 OP_EQUAL ”演示了算术加法操作码 OP_ADD ,该操作码将两个数字相加,然后把结果推送到堆栈, 后面的条件操作符 OP_EQUAL 是验算之前的两数之和是否等于 5 。为了简化起见,前缀OP在一步步的演示过程中将被省略。有关可用脚本操作码和函数的更多详细信息,请参见[交易脚本]。


image.png

尽管绝大多数解锁脚本都指向一个公钥哈希值(本质上就是比特币地址),因此如果想要使用资金则需验证所有权,但脚本本身并不需要如此复杂。任何解锁和锁定脚本的组合如果结果为真(TRUE),则为有效。前面被我们用于说明脚本语言的简单算术操作码同样也是一个有效的锁定脚本,该脚本能用于锁定交易输出。

使用部分算术操作码脚本作为锁定脚本的示例:

3 OP_ADD 5 OP_EQUAL

该脚本能被以如下解锁脚本为输入的一笔交易所满足:

2

验证软件将锁定和解锁脚本组合起来,结果脚本是:

2 3 OP_ADD 5 OP_EQUAL

正如在上图中所看到的,当脚本被执行时,结果是OP_TRUE,交易有效。不仅该笔交易的输出锁定脚本有效,同时UTXO也能被任何知晓这个运算技巧(知道是数字2)的人所使用。

小贴士:如果堆栈顶部的结果显示为TRUE(标记为{{0x01}}),即为任何非零值,或脚本执行后堆栈为空情形,则交易有效。如果堆栈顶部的结果显示为FALSE(0字节空值,标记为{{}})或脚本执行被操作码明确禁止,如OP_VERIFY、 OP_RETURN,或有条件终止如OP_ENDIF,则交易无效。详见[tx_script_ops]相关内容。

以下是一个稍微复杂一点的脚本,它用于计算 2+7-3+1 。注意,当脚本在同一行包含多个操作码时,堆栈允许一个操作码的结果由于下一个操作码执行。

2 7 OP_ADD 3 OP_SUB 1 OP_ADD 7 OP_EQUAL

请试着用纸笔自行演算脚本,当脚本执行完毕时,你会在堆栈得到正确的结果。

P2PKH(Pay-to-Public-Key-Hash)

比特币网络处理的大多数交易花费的都是由“付款至公钥哈希”(或P2PKH)脚本锁定的输出,这些输出都含有一个锁定脚本,将输入锁定为一个公钥哈希值,即我们常说的比特币地址。由P2PKH脚本锁定的输出可以通过提供一个公钥和由相应私钥创建的数字签名来解锁(使用)。参见数字签名ECDSA相关内容。

例如,我们可以再次回顾一下Alice向Bob咖啡馆支付的案例。Alice下达了向Bob咖啡馆的比特币地址支付0.015比特币的支付指令,该笔交易的输出内容为以下形式的锁定脚本:

OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

脚本中的 Cafe Public Key Hash 即为咖啡馆的比特币地址,但该地址不是基于Base58Check编码。事实上,大多数比特币地址的公钥哈希值都显示为十六进制码,而不是大家所熟知的以1开头的基于Bsase58Check编码的比特币地址。

上述锁定脚本相应的解锁脚本是:

<Cafe Signature> <Cafe Public Key>

将两个脚本结合起来可以形成如下组合验证脚本:

<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160
<Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

只有当解锁脚本与锁定脚本的设定条件相匹配时,执行组合验证脚本时才会显示结果为真(TRUE)。换句话说,只有当解锁脚本得到了咖啡馆的有效签名,交易执行结果才会被通过(结果为真),该有效签名是从与公钥哈希相匹配的咖啡馆的私钥中所获取的。 图6-5和图6-6(分两部分)显示了组合脚本一步步检验交易有效性的过程。


交易脚本语言操作符,常量和符号

表1.脚本压入堆栈


image.png

表2.有条件的流控制的操作符


image.png

表3.时间锁操作符


image.png

表4.堆栈操作符


image.png

表5.字符串接操作


表6.二进制算术和条件


image.png

表7.数值操作


表8.加密和散列操作


image.png

表9.非操作符


image.png

表10.仅供内部使用的保留关键字


image.png
上一篇下一篇

猜你喜欢

热点阅读