比特币脚本

栏目:比特币高阶 作者:btcer 评论:0 点击: 3,177 次

本文译自比特币WIKI:https://en.bitcoin.it/wiki/Script

译者:申屠青春 深圳大学ATR国防科技重点实验室博士 新浪微博 @我看比特币

注意:本文可随意转发,请留下译者信息,如果觉得本文对你有用,请给译者捐赠,以便翻译更多比特币的核心资料。捐赠地址:1faVxBp2KmST98p3tJjx2MQP98JLLnF2Q

译者前言

比特币在国内已经众所周知,但是技术研究并未有效开展,大部分人处于知道和了解程度,目前比特圈中许多人对比特币能做什么,同样了解不多。一个重要原因是大多数比特币核心资料都是英文,很少有人能静心看完如此繁杂的英文资料。本人博士论文的研究方向是比特币,在研究其英文技术的同时,拟对一些重要资料进行翻译,让更多的圈内人对比特币有更多的理解。

本文主题是比特币脚本,脚本是形成交易的基础,具有重要作用,不懂脚本就不懂交易。

正文

比特币在交易中使用脚本系统,与FORTH(一种编译语言)一样,脚本是简单的、基于堆栈的、并且从左向右处理,它特意设计成非图灵完整,没有LOOP语句。

一个脚本本质上是众多指令的列表,这些指令记录在每个交易中,交易的接收者想花掉发送给他的比特币,这些指令就是描述接收者是如何获得这些比特币的。一个典型的发送比特币到目标地址D的脚本,要求接收者提供以下两个条件,才能花掉发给他的比特币:

(1)一个公钥,当进行HASH生成比特币地址时,生成的地址是嵌入在脚本中的目标地址D,并且

(2)一个签名,证明接收者保存与上述公钥相对应的私钥。

脚本可以灵活改变花掉比特币的条件,举个例子,脚本系统可能会同时要求两个私钥、或几个私钥、或无需任何私钥等等。

如果联合脚本中未导致失败并且堆栈顶元素为真(非零),表明交易有效。原先发送币的一方,控制脚本运行,以便比特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到输入区。

堆栈保存着字节向量,当用作数字时,字节向量被解释成小尾序的变长整数,最重要的位决定整数的正负号。这样0×81代表-1,0×80是0的另外一种表示方式(称之为负0)。正0用一个NULL长度向量表示。字节向量可以解析为布尔值,这里False表示为0,True表示为非0。

1关键字

以下是脚本的所有关键字列表(命令/函数),一些更复杂的操作码已被禁用,不再考虑,因为钱包客户在这些操作码的程序实现上可能有BUG,如果某个交易使用了这些操作码,将会使比特币块链产生分叉。

True = 1并且False = 0

1.1常数

当我们说脚本的时候,经常省略了这些把数字压入堆栈的关键字。

关键字

操作码

十六进制

输入

输出

描述

OP_0,OP_FALSE

0

0×00

一个字节空串被推到堆栈中(并非no-op操作,有一个元素压入堆栈)

N/A

1-75

0×01-0x4b

(特殊)

数据

下一个操作码字节是要被压入堆栈的数据

OP_PUSHDATA1

76

0x4c

(特殊)

数据

下一字节是要被压入堆栈的数据的长度

OP_PUSHDATA2

77

0x4d

(特殊)

数据

下两个字节是要被压入堆栈的数据的长度

OP_PUSHDATA4

78

0x4e

(特殊)

数据

下四个字节是要被压入堆栈的数据的长度

OP_1NEGATE

79

0x4f

-1

数字-1被压入堆栈

OP_1,OP_TRUE

81

0×51

1

数字1被压入堆栈

OP_2-OP_16

82-96

0×52-0×60

2-16

与关键名相对应的数字被压入堆栈

1.2流程控制

关键字

操作码

十六进制

输入

输出

描述

OP_NOP

97

0×61

无任何操作

OP_IF

99

0×63

<expression> if [statements] [else [statements]]* endif

如果栈项元素值不为0,语句将被执行,栈项元素值被删除。

OP_NOTIF

100

0×64

<expression> if [statements] [else [statements]]* endif

如果栈项元素值为0,语句将被执行,栈项元素值被删除。

OP_ELSE

103

0×67

<expression> if [statements] [else [statements]]* endif

如果前述的OP_IF或 OP_NOTIF或OP_ELSE 未被执行,这些语句就会被执行;如果前述的OP_IF或 OP_NOTIF或OP_ELSE被执行,这些语句就不会被执行

OP_ENDIF

104

0×68

<expression> if [statements] [else [statements]]* endif

结束if/else语言块

OP_VERIFY

105

0×69

True / false

无 / False

如果栈项元素值非真,则标记交易无效。True会被删除,False不会被删除。

OP_RETURN

106

0x6a

标记交易无效

1.3堆栈

关键字

操作码

十六进制

输入

输出

描述

OP_TOALTSTACK

107

0x6b

x1

(alt)x1

把输入压入辅堆栈的项部,从主堆栈删除。

OP_FROMALTSTACK

108

0x6c

(alt)x1

x1

把输入压入主堆栈的项部,从辅堆栈删除。

OP_IFDUP

115

0×73

x

x / x x

如果栈项元素值不为0,复制该元素值

OP_DEPTH

116

0×74

<堆栈大小>

把堆栈元素个数压入堆栈

OP_DROP

117

0×75

x

删除栈顶元素

OP_DUP

118

0×76

x

x x

复制栈顶元素

OP_NIP

119

0×77

x1 x2

x2

删除栈顶的下一个元素

OP_OVER

120

0×78

x1 x2

x1 x2 x1

复制栈顶的下一个元素到栈顶

OP_PICK

121

0×79

xn … x2 x1 x0 <n>

xn … x2 x1 x0 xn

把堆栈的第n个元素拷贝到栈顶

OP_ROLL

122

0x7a

xn … x2 x1 x0 <n>

… x2 x1 x0 xn

把堆栈的第n个元素移动到栈顶

OP_ROT

123

0x7b

x1 x2 x3

x2 x3 x1

栈顶的三个元素向左翻转

OP_SWAP

124

0x7c

x1 x2

x2 x1

栈顶的两个元素交换

OP_TUCK

125

0x7d

x1 x2

x2 x1 x2

把栈顶元素拷贝并插入到栈顶下一个元素之后。注意:原文为“插入到栈顶下一个元素之前”,可能有误,翻译时改为“之后”

OP_2DROP

109

0x6d

x1 x2

删除栈顶两个元素

OP_2DUP

110

0x6e

x1 x2

x1 x2 x1 x2

复制栈顶两个元素

OP_3DUP

111

0x6f

x1 x2 x3

x1 x2 x3 x1 x2 x3

复制栈顶三个元素

OP_2OVER

112

0×70

x1 x2 x3 x4

x1 x2 x3 x4 x1 x2

把栈底的两个元素拷贝到栈顶

OP_2ROT

113

0×71

x1 x2 x3 x4 x5 x6

x3 x4 x5 x6 x1 x2

以一对元素为单位,向左翻转。注意:原文大意“把第五和第六元素移动到栈顶”,明显有误

OP_2SWAP

114

0×72

x1 x2 x3 x4

x3 x4 x1 x2

以一对元素为单位,交换栈顶的两对元素的位置。

1.4字符串

如果标记为已禁用的操作码出现在交易中,必须终止和失败返回。

关键字

操作码

十六进制

输入

输出

描述

OP_CAT

126

0x7e

x1 x2

out

连接两个字符串,已禁用

OP_SUBSTR

127

0x7f

in begin size

out

返回字符串的一部分,已禁用

OP_LEFT

128

0×80

in size

out

在一个字符串中保留左边指定长度的子串,已禁用

OP_RIGHT

129

0×81

in size

out

在一个字符串中保留右边指定长度的子串,已禁用

OP_SIZE

130

0×82

in

in size

把栈顶元素的字符串长度压入堆栈(无需弹出元素)

1.5位逻辑

如果标记为已禁用的操作码出现在交易中,必须终止和失败返回。

关键字

操作码

十六进制

输入

输出

描述

OP_INVERT

131

0×83

in

out

所有输入的位取反,已禁用.

OP_AND

132

0×84

x1 x2

out

对输入的所有位进行布尔与运算,已禁用

OP_OR

133

0×85

x1 x2

out

对输入的每一位进行布尔或运算,已禁用

OP_XOR

134

0×86

x1 x2

out

对输入的每一位进行布尔异或运算,已禁用

OP_EQUAL

135

0×87

x1 x2

True / false

如果输入的两个数相等,返回1,否则返回0。

OP_EQUALVERIFY

136

0×88

x1 x2

True / false

与OP_EQUAL一样,之后运行OP_VERIFY 。

1.5算术逻辑

注意:算术逻辑的输入限于有符号32位长整数,但输出有可能会溢出。

如果任何命令的输入值长度超过4字节,脚本必须中止和失败返回。如果标记为已禁用的操作码出现在交易中,也必须终止和失败返回

关键字

操作码

十六进制

输入

输出

描述

OP_1ADD

139

0x8b

in

out

输入值加1

OP_1SUB

140

0x8c

in

out

输入值减1

OP_2MUL

141

0x8d

in

out

输入值乘2,已禁用

OP_2DIV

142

0x8e

in

out

输入值除2,已禁用

OP_NEGATE

143

0x8f

in

out

输入值符号取反

OP_ABS

144

0×90

in

out

输入值符号取正

OP_NOT

145

0×91

in

out

如果输入值为0或1,则输出1或0;否则输出0。I

OP_0NOTEQUAL

146

0×92

in

out

输入值为0输出0;否则输出1。

OP_ADD

147

0×93

a b

out

输出a+b

OP_SUB

148

0×94

a b

out

输出a-b

OP_MUL

149

0×95

a b

out

输出a*b,已禁用

OP_DIV

150

0×96

a b

out

输出a/b, 已禁用

OP_MOD

151

0×97

a b

out

输出a/b的余数,已禁用

OP_LSHIFT

152

0×98

a b

out

把a向左移动b位,保留符号,已禁用

OP_RSHIFT

153

0×99

a b

out

把a向右移动b位,保留符号,已禁用

OP_BOOLAND

154

0x9a

a b

out

如果a和b都不为0,输出1,否则输出0

OP_BOOLOR

155

0x9b

a b

out

如果a或b不为0,输出1,否则输出0

OP_NUMEQUAL

156

0x9c

a b

out

如果a=b则输出1,否则输出0。

OP_NUMEQUALVERIFY

157

0x9d

a b

out

与OP_NUMEQUAL一样,之后要运行OP_VERIFY

OP_NUMNOTEQUAL

158

0x9e

a b

out

如果a!=b则输出1,否则输出0。

OP_LESSTHAN

159

0x9f

a b

out

如果a<b则输出1,否则输出0。

OP_GREATERTHAN

160

0xa0

a b

out

如果a>b则输出1,否则输出0。

OP_LESSTHANOREQUAL

161

0xa1

a b

out

如果a<=b则输出1,否则输出0

OP_GREATERTHANOREQUAL

162

0xa2

a b

out

如果a>=b则输出1,否则输出0

OP_MIN

163

0xa3

a b

out

输出a,b中的最小值

OP_MAX

164

0xa4

a b

out

输出a,b中的最大值

OP_WITHIN

165

0xa5

x min max

out

如果x在min和max之间,则输出1,否则输出

1.6加密

关键字

操作码

十六进制

输入

输出

描述

OP_RIPEMD160

166

0xa6

in

hash

输入用RIPEMD-160算法HASH

OP_SHA1

167

0xa7

in

hash

输入用SHA-1算法HASH.

OP_SHA256

168

0xa8

in

hash

输入用SHA-256算法HASH.

OP_HASH160

169

0xa9

in

hash

输入被HASH两次,先用 SHA-256,再用 RIPEMD-160.

OP_HASH256

170

0xaa

in

hash

输入用SHA-256算法HASH两次.

OP_CODESEPARATOR

171

0xab

所有签名检查只需匹配最近一次执行的OP_CODESEPARATOR 操作数据的签名即可。

OP_CHECKSIG

172

0xac

sig pubkey

True / false

全部交易的输出、输入和脚本(从最近执行的OP_CODESEPARATOR操作到最)都被HASH,OP_CHECKSIG使用的签名必须是该HASH值和公钥的有效签名,如果是真则返回1,否则返回0。

OP_CHECKSIGVERIFY

173

0xad

sig pubkey

True / false

与OP_CHECKSIG一样,但之后执行 OP_VERIFY

OP_CHECKMULTISIG

174

0xae

x sig1 sig2 … <number of signatures> pub1 pub2 <number of public keys>

True / False

对于每个签名和公钥对,OP_CHECKSIG 都会被执行,如果公钥列得比签名多,一些公钥/签名对会失败。所有的签名要与公钥匹配。如果所有签名有效,输出1,否则返回0。因为存在BUG,一个未使用的外部值会从堆栈中删除。

OP_CHECKMULTISIGVERIFY

175

0xaf

x sig1 sig2 … <number of signatures> pub1 pub2 … <number of public keys>

True / False

与 OP_CHECKMULTISIG,一样,但是之后运行 OP_VERIFY。

1.7伪关键字

这些关键字仅供内部使用,用辅助进行交易匹配,如果使用在实际的交易中则是无效的。

关键字

操作码

十六进制

描述

OP_PUBKEYHASH

253

0xfd

表示公钥用OP_HASH160操作码HASH

OP_PUBKEY

254

0xfe

表示与OP_CHECKSIG.兼容的一个公钥

OP_INVALIDOPCODE

255

0xff

匹配任何未指定的操作码

1.8保留关键字

关键字

操作码

十六进制

描述

OP_RESERVED

80

0×50

交易无效,除非发生在未执行的OP_IF 分支

OP_VER

98

0×62

交易无效,除非发生在未执行的OP_IF 分支

OP_VERIF

101

0×65

交易无效,即使发生在未执行的OP_IF 分支

OP_VERNOTIF

102

0×66

交易无效,即使发生在未执行的OP_IF 分支

OP_RESERVED1

137

0×89

交易无效,除非发生在未执行的OP_IF 分支

OP_RESERVED2

138

0x8a

交易无效,除非发生在未执行的OP_IF 分支

OP_NOP1-OP_NOP10

176-185

0xb0-0xb9

这些关键字被忽略

更多比特币知识请访问我的网站
学习比特币studybtc.com

2脚本

以下是有趣的脚本列表,记住:所有的常数实际上都使用上述的数据压栈命令。注意:有小部分的标准脚本形式可以在节点之间转播,在块链中的非标准脚本会被接受,但是节点不会转播。

2.1支付到比特币地址的标准交易(pay-to-pubkey-hash)

scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

scriptSig: <sig> <pubKey>

演示一下脚本在是如何在网络中传播的,以下是原始scriptPubKey:

76       A9             14

OP_DUP OP_HASH160    Bytes to push

89 AB CD EF AB BA AB BA AB BA AB BA AB BA AB BA AB BA AB BA

                          Data to push

88                AC

OP_EQUALVERIFY OP_CHECKSIG

注意:scriptSig是消费交易的输入,而scriptPubKey是以前还未消费的交易的输出,例如:“可用”交易。以下是每个关键字的处理过程:

堆栈

脚本

描述

<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

scriptSig和scriptPubKey 联合

<sig> <pubKey>

OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

遇到常数,压入堆栈

<sig> <pubKey> <pubKey>

OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

复制栈顶元素

<sig> <pubKey> <pubHashA>

<pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

HASH栈顶元素

<sig> <pubKey> <pubHashA> <pubKeyHash>

OP_EQUALVERIFY OP_CHECKSIG

遇到常数,压入堆栈

<sig> <pubKey>

OP_CHECKSIG

检查两个栈顶元素是否相等

true

Empty.

用两个栈顶元素,检查签名是否正确。

2.2标准比特币产生交易(pay-to-pubkey)

OP_CHECKSIG直接用来检查签名,而非先对公钥HASH再检查。默认情况下,使用这种形式产生比特币,交易中的scriptPubKey被认为是向用户支付,这种交易形式的缺点是预先要知道整个公钥,意味着更长的支付地址,并且它降低了ECDSA签名算法的安全性。比特币客户端

scriptPubKey: <pubKey> OP_CHECKSIG

scriptSig: <sig>

检查过程如下:

堆栈

脚本

描述

<sig><pubKey> P_CHECKSIG

scriptSig和scriptPubKey联合

<sig> <pubKey>

OP_CHECKSIG

遇到常数,压入堆栈

true

用两个栈顶元素,检查签名是否正确

2.3可证明的无法花掉/可删除的输出

标记一个交易为可证明无法花掉的标准方法,是提供如下一个scriptPubKey:

         scriptPubKey: OP_RETURN {zero or more ops}

     OP_RETURN立即标记脚本无效,如果没有scriptSig存在,有可能花掉那个输出。这样,如果还没有被花掉,输出会立即从UTXO(Unspent Transaction Output,未花费的交易输出)集合中被删除,eb31ca1a4cbd97c2770983164d7560d2d03276ae1aee26f12d7c2c6424252f29是一个例子,它只有一个0值输出,这样就把所有0.125BTC费用给挖到该交易的矿工,未将之加入UTXO集合。你也可以使用OP_RETURN在一个没有数据的交易上添加数据,而且该数据可以从未在UTXO集合出现,正如我们在交易1a2e22a717d626fc5db363582007c46924ae6b28319f07cb1b907776bd8293fc所看到的。P2Pool在它创建的比特币产生块中,通过共享块链的HASH输出做到这点,

注意,该机制还不是一个标准交易类型,因而不会被主网络上的节点所转发。学习比特币

2.4Anyone-Can-Spend输出

相反,交易可以被任何人花掉,脚本如下:

scriptPubKey: (empty)

scriptSig: OP_TRUE

一些软件把交易改成这样,可作为除交易费外另一种向矿工捐赠的方法,任何挖到这个交易的矿工把这些币发回他们的地址,就能得到额外的费用,这种机制将来可以用在诚实契约上,即以一种可证明的方式奉献资金。

当前Anyone-Can-Spend输出被认为是非标准交易,不会在P2P网络中传播。

2.5猜谜交易

交易a4bfa8ab6435ae5f25dae9d89e4eb67dfa94283ca751f393c1ddc5a837bbc31b是一个有趣的谜语:

scriptPubKey: OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL

scriptSig:

要把这个交易花掉,你需要找到一些数据,这些数据的两次HASH值等于给定的HASH值。

堆栈

脚本

描述

Empty.

<data> OP_HASH256 <given_hash> OP_EQUAL

 

<data>

OP_HASH256 <given_hash> OP_EQUAL

把scriptSig数据压入堆栈

<data_hash>

<given_hash> OP_EQUAL

对数据进行HASH

<data_hash> <given_hash>

OP_EQUAL

把 given_hash入栈

true

Empty.

匹配两个HASH值是否为真

这个交易已经被09f691b2263260e71f363d1db51ff3100d285956a40cc0e4f8c8c2c4a80559b1成功花掉,所需的数据就是创世块,给定的HASH就是创世块的HASH值,注意:这类交易看起来很有趣,但并不安全,它们未包含任何签名,因而任何想花掉它们的交易能被其他的交易所代换,钱将被转到其他地址。



0

声明: 本文由( btcer )原创编译,转载请保留链接: 比特币脚本

比特币脚本:等您坐沙发呢!

发表评论


    分享到:
11.5K

若觉得本站内容对您有用,欢迎随手打赏

地址 1EwvVKfHm34h8bzKTx8NjT8nHjsRrjGhvm

比特币常用网址:
交易查询(国外):http://blockchain.info/
交易查询(国内):http://qukuai.com
中文维基:https://zh-cn.bitcoin.it/
BTC客户端:http://bitcoin.org/en/choose-your-wallet
行情汇总:http://z.btc123.com/

"In computing we trust."
我们信任计算

什么是比特币?比特币™ (BitCoin)是一种P2P形式的虚拟货币。点对点的传输意味着一个去中心化的支付系统。比特币不依靠特定货币机构发行,它通过特定算法的大量计算产生,比特币经济使用整个P2P网络中众多节点构成的分布式数据库来确认并记录所有的交易行为。P2P的去中心化特性与算法本身可以确保无法通过大量制造比特币来人为操控币值。基于密码学的设计可以使比特币只能被真实的拥有者转移或支付。这同样确保了货币所有权与流通交易的匿名性。