比特币脚本

区块链技术巴比特2017-11-25 06:47:17  阅读 -评论 0

本文译自比特币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 if [statements] [else [statements]]* endif 如果栈项元素值不为0,语句将被执行,栈项元素值被删除。 OP_NOTIF 100 0×64 if [statements] [else [statements]]* endif 如果栈项元素值为0,语句将被执行,栈项元素值被删除。 OP_ELSE 103 0×67 if [statements] [else [statements]]* endif 如果前述的OP_IF或 OP_NOTIF或OP_ELSE 未被执行,这些语句就会被执行;如果前述的OP_IF或 OP_NOTIF或OP_ELSE被执行,这些语句就不会被执行 OP_ENDIF 104 0×68 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 xn … x2 x1 x0 xn 把堆栈的第n个元素拷贝到栈顶 OP_ROLL 122 0x7a xn … x2 x1 x0 … 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 如果ab则输出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 … pub1 pub2 True / False 对于每个签名和公钥对,OP_CHECKSIG 都会被执行,如果公钥列得比签名多,一些公钥/签名对会失败。所有的签名要与公钥匹配。如果所有签名有效,输出1,否则返回0。因为存在BUG,一个未使用的外部值会从堆栈中删除。 OP_CHECKMULTISIGVERIFY 175 0xaf x sig1 sig2 … pub1 pub2 … 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 这些关键字被忽略 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值,注意:这类交易看起来很有趣,但并不安全,它们未包含任何签名,因而任何想花掉它们的交易能被其他的交易所代换,钱将被转到其他地址。

声明:链世界登载此文仅出于分享区块链知识,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。此文如侵犯到您的合法权益,请联系我们100@7234.cn

    参与讨论 (0 人参与讨论)

    相关推荐

    区块链投资趋势报告:巨头入场布局行业趋于成熟

    区块链投资趋势报告:巨头入场布局行业趋于成熟

    来自:https://mp.weixin.qq.com/s?__biz=MzI4NzIxOTY1NA==&amp;mid=2650632639&amp;idx=1&amp;sn=e6d1c29731d992a80410aaee82ec3ea6&amp;chksm=f3d8db16c4af520097e4a64a71b1d4743ac326b9f027

    重新发明货币

    重新发明货币

    一、货币的演化过程 先简单回顾一下人类货币的演化过程,大概有以下阶段: a. 1.0版本:自然货币(贝壳、牲口、金银……) 这个阶段,货币基于一般等价物的稀有性或者实用性,货币不可能出现人为操纵的超发。 b. 2.0版本:早期纸币、银票到本位纸币 当贸易量越来越大,实物货币太不方便了,而且大家发现其实并不在意货币本身有什么价值,在意的只是这么多的货币能不能交换到足够的物品,于是纸币这种信用货

    从比特币交易看欧洲央行虚拟货币分类

    从比特币交易看欧洲央行虚拟货币分类

      互联网对传统社会的颠覆从未停止,在其完成对信息流、商流、物流、资金流的初步改造之后,或将以虚拟货币的形式打破现有货币体系   4月18日,在中国极客张沈鹏创办的比特币交易平台(42BTC.com)上,比特币对人民币的平均交易价为576元。当天,该平台完成了100个比特币的交易量。仅仅过去一周,4月25日上午,比特币对人民币的平均交易价已达到906元。据42BTC网站统计:在过去的32个月

    欧洲央行-比特币报告

    3.1 比特币 3.1.1 基本特征          比特币可能是最成功的,也可能是最有争议的虚拟货币方案,由日本程序员中本聪(译者注:事实上,中本聪是不是日本人,甚至是不是单个人无从考证)在2009年设计并实现。该计划基于一个类似于BitTorrent的P2P网络。BitTorrent是互联网上著名的共享文件协议,应用在电影,游戏和音乐领域。比特币在全球层面上运作,可用于各类货币交易(虚

    彻底玩转比特币地址和私匙

    彻底玩转比特币地址和私匙

    比特币地址和私匙是所有比特币初学者面对的一大难题,再加上那一串超长的字符串,让人更是摸不到头脑。 现在编者以问答的形式,带你一步步的揭开比特币地址和私匙的面纱。 还不知道什么是比特币地址和私匙的同学请点这里 问题一、比特币钱包由什么组成? 答 我们知道,比特币地址和私匙组成了比特币钱包,而私匙则决定了比特币地址上比特币的归属。 地址和私匙 问题二、如果只记得私匙我们还能还原比特币地址么? 答

    用GO语言实现比特币算法

    用GO语言实现比特币算法

    本节的这个例子展示一点点高精度数学包math/big、一点点散列包hash、一点点加密包crypto,还有一点点测试包testing的知识。这里不介绍bitcoin协议和算法——尽管它们很有趣,而是试图指出,Go对多种操作系统的支持,是实现这种跨平台应用的理想语言。 位钱(bitcoin)是一种使用加密手段制作的分布式电子货币。它最初于1998年由Wei Dai提出,并由中本聪(Satoshi

    详解比特币的找零机制

    详解比特币的找零机制

    比特币的找零机制一直让人有些迷惑,明明只向一个地址发送了比特币为什么 blockchain 上面的显示的有时是1个地址对多个地址,有时是多个地址对1个地址,有时又显示多个地址对多个地址? 为什么比特币资深用户要提醒大家当比特币钱包交易100次以上时再次交易后要重新备份钱包,恢复以前的钱包备份有可能会遭遇损失? 是的,这一切都是因为比特币的找零(Change)机制。本文参考 Bitcoin的维

    玩转比特币客户端之一:C盘转移和加速下载

    玩转比特币客户端之一:C盘转移和加速下载

    C盘空间不足?交易数据下载速度太慢?别着急,乐享比特币教你轻松玩转比特币官方客户端。 所有新人开始接触比特币时做的第一件事情大多数是安装比特币的官方客户端。 安全起见大家最好直接访问官方发布渠道sourceforge的地址进行下载:http://sourceforge.net/projects/bitcoin/files/Bitcoin/ 该网页列出了各版本的官方比特币客户端,目前

    麦妖榜
    更新日期 2019-01-17
    排名用户贡献值
    1等待的宿命23695
    2BitettFan23632
    3六叶树20309
    4天下无双16192
    5lizhen00214782
    6区块大康14502
    7让时间淡忘14188
    8冷风大q11188
    9momo11174
    10linjm122710573
    返回顶部 ↑