比特币交易脚本和脚本语言

比特币客户端通过执行一个用类Forth脚本语言编写的脚本验证比特币交易。锁定脚本被写入UTXO,同时它往往包含一个用同种脚本语言编写的签名。当一笔比特币交易被验证时,每一个输入值中的解锁脚本被与其对应的锁定脚本同时(互不干扰地)执行,从而查看这笔交易是否满足使用条件。

比特币交易脚本和脚本语言

如今,大多数经比特币网络处理的交易是以“Alice付给Bob”的形式存在的。同时,它们是以一种称为“P2PKH”(Pay-to-Public-Key-Hash)脚本为基础的。然而,通过使用脚本来锁定输出和解锁输入意味着通过使用编程语言,比特币交易可以包含无限数量的条件。当然,比特币交易并不限于“Alice付给Bob”的形式和模式。

这只是这个脚本语言可以表达的可能性的冰山一角。在这一节,我们将会全面展示比特币交易脚本语言的各个组成部分;同时,我们也会演示如何使用它去表达复杂的使用条件以及解锁脚本如何去满足这些花费条件。

比特币交易验证并不基于一个不变的模式,而是通过运行脚本语言来实现。这种语言可以表达出多到数不尽的条件变种。这也是比特币作为一种“可编程的货币”所拥有的权力。

脚本创建(锁定与解锁)

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

锁定脚本是一个放在一个输出值上的“障碍”,同时它明确了今后花费这笔输出的条件。由于锁定脚本往往含有一个公钥(即比特币地址),在历史上它曾被称作一个脚本公钥代码。由于认识到这种脚本技术存在着更为宽泛的可能性,文中我们将它称为一个“锁定脚本”。在大多数比特币应用源代码中,脚本公钥代码便是我们所说的锁定脚本。

解锁脚本是一个“解决”或满足被锁定脚本在一个输出上设定的花费条件的脚本,同时它将允许输出被消费。解锁脚本是每一笔比特币交易输出的一部分,而且往往含有一个被用户的比特币钱包(通过用户的私钥)生成的数字签名。由于解锁脚本常常包含一个数字签名,因此它曾被称作ScriptSig。在大多数比特币应用的源代码中,ScriptSig便是我们所说的解锁脚本。考虑到更宽泛的锁定脚本要求,我们将它称为“解锁脚本”。但并非所有解锁脚本都一定会包含签名。

每一个比特币客户端会通过同时执行锁定和解锁脚本来验证一笔交易。对于比特币交易中的每一个输入,验证软件会先检索输入所指向的UTXO。这个UTXO包含一个定义了花费条件的锁定脚本。接下来,验证软件会读取试图花费这个UTXO的输入中所包含的解锁脚本,并执行这两个脚本。

在先前的比特币客户端中,解锁和锁定脚本是以连锁的形式存在的,并且是被依次执行的。出于安全因素考虑,在2010年比特币开发者们修改了这个特性一因为存在“允许异常解锁脚本推送数据入栈并且污染锁定脚本”的漏洞。在当今的比特币世界中,这两个脚本是随着堆栈的传递被分别执行的,后续将会详细介绍。

首先,使用堆栈执行引擎执行解锁脚本。如果解锁脚本在执行过程中未报错(没有悬空操作符),主堆栈(非其它堆栈)将被复制,然后脚本将被执行。如果采用从解锁脚本处复制而来的数据执行锁定脚本的结果为真,那么解锁脚本就成功地满足了锁定脚本所设置的条件,因而,该输入是一个能使用该UTXO的有效授权。如果在执行完组合脚本后的结果不是真,那么输入就不是有效的,因为它并未能满足UTXO中所设置的使用该笔资金的条件。注意,UTXO是永久性地记录在区块链中的,因此它不会因一笔新交易所发起的无效尝试而变化或受影响。只有一笔有效的能准确满足UTXO条件的交易才会导致UTXO被标记为“已使用”,然后从有效的(未使用)UTXO集中所移除。

图5-1是最为常见类型的比特币交易(向公钥哈希进行一笔支付)的解锁和锁定脚本样本,该样本展示了在脚本验证之前将解锁脚本和锁定脚本串联而成的组合脚本。

image.png

脚本语言

比特币交易脚本语言,也称为脚本,是一种基于逆波兰表示法的基于堆栈的执行语言。如果这让您听起来似乎在胡言乱语,很有可能是您没学习过1960年的编程语言的缘故。脚本是一种非常简单的语言,这种语言被设计为能在有限的硬件上执行,这些硬件类似简单的嵌入式设备,如手持计算器。它仅需最少的处理即可,而且不能做许多现代编程语言可以做的事情。当涉及可编程的钱时,这是它的一个基于深思熟虑的安全特性。

比特币脚本语言被称为基于栈语言,因为它使用的数据结构被称为栈。栈是一个非常简单的数据结构,它可以被理解成为一堆卡片。栈允许两类操作:入栈和出栈。入栈是在栈顶部增加一个项目,出栈则是从栈顶部移除一个项目。

脚本语言通过从左至右地处理每个项目的方式执行脚本。数字(常数)被推送至堆栈,操作符向堆栈推送(或移除)一个或多个参数,对它们进行处理,甚至可能会向堆栈推送一个结果。例如,〇P_ADD将从堆栈移除两个项目,将二者相加,然后再将二者相加之和推送到堆栈。

条件操作符评估一项条件,产生一个真或假的结果。例如,〇P_EQUAL从堆栈移除两个项目,假如二者相等则推送真(表示为1),假如二者不等则推送为假(表示为0)。比特币交易脚本常含条件操作符,当一笔交易有效时,就会产生真的结果。

图片1.png

在图5-2中,脚本“23OP_ADD5OP_EQUAL”演示了算术加法操作符OP_ADD,该操作符将两个数字相加,然后把结果推送到堆栈,OP_EQUAL是验算之前的两数之和是否等于5。为了简化起见,前缀0P_在一步步的演示示例过程中将被省略。

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

7OP_ADD3OP_SUB1OP_ADD7OP_EQUAL


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

虽然大多数的解锁脚本都指向一个比特币地址或公钥,因而如果想要使用资金则需验证所有权,但脚本本身并不需要如此的复杂。任何解锁和锁定脚本的组合如果结果为真,则为有效。前面被我们用于说明脚本语言的简单算术运算同样也是一个有效的锁定脚本,该脚本能用于锁定交易输出。

使用部分算数运算示例脚本作用锁定脚本:

OP_ADD 5 OP_EQUAL

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

2

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

2 3 OP_ADD 5 OP_EQUAL

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

如果堆栈顶部的结果显示为真(标记为{0x01}),即为任何非零值或脚本执行后堆栈为空情形,则交易有效。如果堆栈顶部的结果显示为假(0字节空值,标记为{})或脚本执行被操作符禁止,如〇P_VERIFY、OP_RETURN,或有条件终止如OP_ENDIF,则交易无效。

图灵非完备性

比特币脚本语言包含许多操作,但都故意限定为一种重要的方式——没有循环或者复杂流控制功能以外的其他条件的流控制。这样就保证了脚本语言的图灵非完备性,这意味着脚本的复杂性有限,交易可执行的次数也可预见。脚本并不是一种通用语言,施加的这些限制确保该语言不被用于创造无限循环或其它类型的逻辑炸弹,这样的炸弹可以植入在一笔交易中,通过引起拒绝服务的方式攻击比特币网络。受限制的语言能防止交易激活机制被人当作薄弱环节而加以利用。

非主权验证

比特币交易脚本语言是无国家主权的,没有国家能凌驾于脚本之上,也没有国家会在脚本被执行后对其进行保存。所以需要执行脚本的所有信息都已包含在脚本中。可以预见的是,一个脚本能在任何系统上以相同的方式执行。如果您的系统对一个脚本进行验证,可以确信的是每一个比特币网络中的其他系统也将对其进行验证,这意味着一个有效的交易对每个人而言都是有效的,而且每一个人都明白这一点。这种对于结果的可预见性是比特币系统的一项重要良性特征。

玖壹区块链声明

加微信:469649885区块链培训教程
还可免费获取区块链培训班试学名额

分享:

扫一扫在手机阅读、分享本文

区块链评论

玖壹区块链培训

玖壹区块链培训学院简称(玖壹学院http://www.91xiubbs.com/)提供区块链技术培训资料、区块链开发培训视频教程等下载,不过网上自学区块链技术课程必然存在一些缺陷:遇到问题易卡壳、学习周期漫长、无针对性等。区块链培训机构现场面对面的讲授区块链培训课程可以让您和团队在最短时间内掌握正确、系统、高效的区块链实战技术。