《区块链开发指南》一一1.4 脚本系统-阿里云开发者社区

开发者社区> 华章计算机> 正文

《区块链开发指南》一一1.4 脚本系统

简介:
+关注继续查看

本节书摘来自华章计算机《区块链开发指南》一书中的第1章,第1.4节,作者:申屠青春 主编 宋 波 张 鹏 汪晓明 季宙栋 左川民 编著更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.4 脚本系统

比特币在交易中使用脚本系统,与FORTH(一种编译语言)一样,脚本是简单的、基于堆栈的,并且是从左向右处理的,它特意设计成非图灵完整的形式,没有LOOP语句。
一个脚本本质上是众多指令的列表,这些指令记录在每个交易中,若交易的接收者想花掉发送给他的比特币,那么这些指令就是描述接收者是如何获得这些比特币的。一个典型的发送比特币到目标地址D的脚本,要求接收者提供以下两个条件,才能花掉发给他的比特币:
1)一个公钥,当进行散列生成比特币地址时,生成的地址是嵌入在脚本中的目标地址D。
2)一个签名,用于证明接收者保存了与上述公钥相对应的私钥。
脚本可以灵活地改变花掉比特币的条件,举个例子,脚本系统可能会同时要求两个私钥或几个私钥,或者无需任何私钥等。
如果联合脚本中未导致失败并且堆栈顶元素为真(非零),则表明交易有效。原先发送币的一方,控制脚本运行,以便比特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到输入区。
堆栈保存着字节向量,当用作数字时,字节向量被解释成小尾序的变长整数,最重要的位用于决定整数的正负号。比如,0x81代表-1,0x80则是0的另外一种表示方式(称之为负0)。正0用一个NULL长度向量表示。字节向量可以解析为布尔值,这里False表示为0,True表示为非0。
1.4.1 脚本特点
表1-4至表1-12是脚本的所有关键字列表(命令/函数),一些更复杂的操作码已被禁用,不再考虑,因为钱包客户在这些操作码的程序实现上可能有Bug,如果某个交易使用了这些操作码,那么其将会使比特币块链产生分叉。我们提到脚本的时候,通常省略了这些把数字压入堆栈的关键字。
image

image
image

image

image

image

算术逻辑的输入仅限于有符号32位长整数,但输出有可能会溢出。如果任何命令的输入值其长度超过4字节,那么脚本必须中止和失败返回。如果在交易中出现了标记为已禁用的操作码,也必须终止和失败返回。
image
image

image

image

1.4.2 脚本运行过程
在这里,我们先讨论单输入单输出的比特币交易,因为这样描述起来更为方便,而且不会影响对脚本的理解,以下面的一个交易Hash值为例:
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
这是一个单输入单输出交易,下面来看下我们要关注的数据。
Hash:

9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1

对于输入交易,需要关注如下值。
前导输入的Hash:

437b95ae15f87c7a8ab4f51db5d3c877b972ef92f26fbc6d3c4663d1bc750149
输```  
入脚本scriptSig:

3045022100efe12e2584bbd346bccfe67fd50a54191e4f45f945e3853658284358d9c062ad02200121e00b6297c0874650d00b786971f5b4601e32b3f81afa9f9f8108e93c752201038b29d4fbbd12619d45c84c83cb4330337ab1b1a3737250f29cec679d7551148a

对于输出交易,需要关注如下值。
转账金额:0.05010000 btc
输出脚本scriptPubKey:

OP_DUP OP_HASH160 be10f0a78f5ac63e8746f7f2e62a5663eed05788 OP_EQUALVERIFY OP_CHECKSIG

假设Alice是转账发送者,Bob是接受者。那么输入交易表明了Alice要动用的比特币的来源,交易输出表明了Alice要转账的数额和转账对象——Bob。那么,有读者可能会问,数据中的输入脚本和输出脚本是不是就是题和解?答对了一半!
在Bitcoin Wiki中提到:原先发送币的一方,控制脚本运行,以便比特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到输入区。
换句话说,在一个交易中,输出脚本是数学题,输入脚本是题解,但不是这道数学题的题解。我开始看Wiki的时候,在这里遇到了一些障碍,没法理解输入脚本和输出脚本的联系。但是在考虑到交易间的关系之后,就明白了。
假设有这么一系列交易,如图1-7所示。

图![image](https://yqfile.alicdn.com/0b71bb6f7f88c33b4bdc1f475be8ce7b5e11243b.png)
1-7 三对交易示范图
那么,这一系列交易具有如下特征。
三个交易都是单输入单输出交易。
每个输入交易输出交易中,都包含对应的脚本。
交易a为Alice转账给Bob;交易b为Bob转账给Carol;交易c为Carol转账给Dave。
当前交易的输入都引用前一个交易的输出,如交易b的输入就是引用交易a的输出。
按照之前的说法,交易a中的输出脚本就是Alice为Bob出的数学题。那么,Bob想要引用交易a输出交易的比特币,就要解开这道数学题。题解是在交易b的输入脚本里给出的!Bob解开了这道题,获得了奖金,然后在交易b中为Carol出一道数学题,等待Carol来解……
所以说,在图1-8中相同颜色的输出和输入才是一对题和解。
![image](https://yqfile.alicdn.com/3c9c39e7970b8c365ba92e83651c0448c6e55485.png)

图1-8 输入输出一一对应图
**1.4.3 脚本操作码解读**
要理解比特币脚本,先要了解堆栈,这是一个后进先出(Last In First Out)的容器,脚本系统对数据的操作都是通过它完成的。比特币脚本系统中有两个堆栈:主堆栈和副堆栈,一般来说主要使用主堆栈。下面就来列举几个简单的例子,看下指令是如何对堆栈进行操作的。
常数入栈:指把一段常数压入到堆栈中,这个常数成为栈顶元素,如图1-9所示。
OP_DUP:复制栈顶元素,如图1-10所示。
![image](https://yqfile.alicdn.com/f8cd6edb4af042c98ec4c262f9576eb92ea8de74.png)
        
    图1-9 常数入栈    图1-10 复制栈顶元素
OP_EQUALVERIFY:用于检查栈顶两个元素是否相等,如图1-11所示。
**1.4.4 脚本执行过程**
Alice在转账给Bob的时候,输出交易中给出了Bob的钱包地址(等价于公钥Hash),当Bob想要转账给Carol的时候,他要证明自己拥有与这个钱包地址对应的私钥,所以在输入交易中给出了自己的公钥及使用私钥对交易的签名。下面来看个实例。

交易a:?
9c50cee8d50e273100987bb12ec46208cb04a1d5b68c9bea84fd4a04854b5eb1
交易b:?
62fadb313b74854a818de4b4c0dc2e2049282b28ec88091a9497321203fb016e

交易b中有一个输入交易引用了交易a的输出交易,它们的脚本是一对题与解。
题:交易a的输出脚本,若干个脚本指令和转账接收方的公钥Hash。

OP_DUPOP_HASH160be10f0a78f5ac63e8746f7f2e62a5663eed05788OP_EQUALVERIFY OP_CHECKSIG

解:交易b的输入脚本,这么一长串只是两个元素,签名和公钥(sig & pubkey)。

3046022100ba1427639c9f67f2ca1088d0140318a98cb1e84f604dc90ae00ed7a5f9c61cab02210094233d018f2f014a5864c9e0795f13735780cafd51b950f503534a6af246aca301 03a63ab88e75116b313c6de384496328df2656156b8ac48c75505cd20a4890f5ab

下面来看下这两段脚本是如何执行完成解题过程的。
首先执行的是输入脚本。因为脚本是从左向右执行的,那么先入栈的是签名,随后是公钥。接着,执行的是输出脚本。从左向右执行,第一个指令是OP_DUP——复制栈顶元素(如图1-12所示)。
OP_HASH160用于计算栈顶元素Hash,得到pubkeyhash,如图1-13所示。
然后将输出脚本中的公钥Hash入栈,为了与前面计算中所得到的Hash区别开来,这里称它为pubkeyhash',如图1-14所示。
![image](https://yqfile.alicdn.com/17ff1a4e5781efa8a9cc3f8c87c42a3d913d3af8.png)

OP_EQUALVERIFY则会检查栈顶前两个元素是否相等,如果相等则继续执行,否则中断执行,返回失败,如图1-15所示。
OP_CHECKSIG使用栈顶前两个元素执行签名校验操作,如果相等,则返回成功,否则返回失败,如图1-16所示。
![image](https://yqfile.alicdn.com/b552582ed5a1a721dff201d2cf22fb0b8fbb5874.png)
        
    图1-15 检查Hash值是否相等    图1-16 返回结果
这样一串指令执行下来,就可以验证这道数学题是否做对了,也就是说,验明了想要花费钱包地址中比特币的人是否拥有对应的私钥。上面的执行过程是可以在脚本模拟器中进行的,并且能够看到每一步执行的状态。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
FTP定时批量下载文件(SHELL脚本及使用方法 ) (转)--good
#/bin/bash URL="http://192.168.5.100/xxx.php" check() { RESULT=$(curl -s $URL) echo $RESULT if [ "$RESULT" -eq "1111" ...
1390 0
脚本开发转载链接汇总
1.python3api文档官方站点 http://docs.python.org/py3k/
565 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
11944 0
C++程序中嵌入Ruby脚本系统
Ruby,一种为简单快捷面向对象编程(面向对象程序设计)而创的脚本语言,由日本人松本行弘(まつもとゆきひろ,英译:Yukihiro Matsumoto,外号matz)开发,遵守GPL协议和Ruby License。
1270 0
使用Express3.0实现<Node.js开发指南>中的微博系统
特别说明:本实例仅在windows xp sp3系统下测试通过(其它系统未经过测试)。 这本书,之前有评论过,但之前并不清楚express2.x与3.x会有如此大的差异,导致在写例子的过程中痛苦不已。
814 0
105_《Delphi5应用系统开发高级指南》
《Delphi5应用系统开发高级指南》 Delphi 教程 系列书籍 (105) 《Delphi5应用系统开发高级指南》 网友(邦)整理 EMail: shuaihj@163.
1390 0
10059
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载