请选择 进入手机版 | 继续访问电脑版
开启辅助访问
QQ登录|微信登录|登录 |立即注册

盖茨网区块链技术社区

比特币脚本解析

译者前言

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

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

正文

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

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

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

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

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

1关键字

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

True = 1并且False = 0

1.1常数

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

关键字

操作码

十六进制

输入

输出

描述

OP_0,OP_FALSE00×00一个字节空串被推到堆栈中(并非no-op操作,有一个元素压入堆栈)
N/A1-750×01-0x4b(特殊)数据下一个操作码字节是要被压入堆栈的数据
OP_PUSHDATA1760x4c(特殊)数据下一字节是要被压入堆栈的数据的长度
OP_PUSHDATA2770x4d(特殊)数据下两个字节是要被压入堆栈的数据的长度
OP_PUSHDATA4780x4e(特殊)数据下四个字节是要被压入堆栈的数据的长度
OP_1NEGATE790x4f-1数字-1被压入堆栈
OP_1,OP_TRUE810×511数字1被压入堆栈
OP_2-OP_1682-960×52-0×602-16与关键名相对应的数字被压入堆栈
1.2流程控制

关键字

操作码

十六进制

输入

输出

描述

OP_NOP970×61无任何操作
OP_IF990×63<expression> if [statements] [else [statements]]* endif如果栈项元素值不为0,语句将被执行,栈项元素值被删除。
OP_NOTIF1000×64<expression> if [statements] [else [statements]]* endif如果栈项元素值为0,语句将被执行,栈项元素值被删除。
OP_ELSE1030×67<expression> if [statements] [else [statements]]* endif如果前述的OP_IF或 OP_NOTIF或OP_ELSE 未被执行,这些语句就会被执行;如果前述的OP_IF或 OP_NOTIF或OP_ELSE被执行,这些语句就不会被执行
OP_ENDIF1040×68<expression> if [statements] [else [statements]]* endif结束if/else语言块
OP_VERIFY1050×69True / false无 / False如果栈项元素值非真,则标记交易无效。True会被删除,False不会被删除。
OP_RETURN1060x6a标记交易无效
1.3堆栈

关键字

操作码

十六进制

输入

输出

描述

OP_TOALTSTACK1070x6bx1(alt)x1把输入压入辅堆栈的项部,从主堆栈删除。
OP_FROMALTSTACK1080x6c(alt)x1x1把输入压入主堆栈的项部,从辅堆栈删除。
OP_IFDUP1150×73xx / x x如果栈项元素值不为0,复制该元素值
OP_DEPTH1160×74<堆栈大小>把堆栈元素个数压入堆栈
OP_DROP1170×75x删除栈顶元素
OP_DUP1180×76xx x复制栈顶元素
OP_NIP1190×77x1 x2x2删除栈顶的下一个元素
OP_OVER1200×78x1 x2x1 x2 x1复制栈顶的下一个元素到栈顶
OP_PICK1210×79xn … x2 x1 x0 <n>xn … x2 x1 x0 xn把堆栈的第n个元素拷贝到栈顶
OP_ROLL1220x7axn … x2 x1 x0 <n>… x2 x1 x0 xn把堆栈的第n个元素移动到栈顶
OP_ROT1230x7bx1 x2 x3x2 x3 x1栈顶的三个元素向左翻转
OP_SWAP1240x7cx1 x2x2 x1栈顶的两个元素交换
OP_TUCK1250x7dx1 x2x2 x1 x2把栈顶元素拷贝并插入到栈顶下一个元素之后。注意:原文为“插入到栈顶下一个元素之前”,可能有误,翻译时改为“之后”
OP_2DROP1090x6dx1 x2删除栈顶两个元素
OP_2DUP1100x6ex1 x2x1 x2 x1 x2复制栈顶两个元素
OP_3DUP1110x6fx1 x2 x3x1 x2 x3 x1 x2 x3复制栈顶三个元素
OP_2OVER1120×70x1 x2 x3 x4x1 x2 x3 x4 x1 x2把栈底的两个元素拷贝到栈顶
OP_2ROT1130×71x1 x2 x3 x4 x5 x6x3 x4 x5 x6 x1 x2以一对元素为单位,向左翻转。注意:原文大意“把第五和第六元素移动到栈顶”,明显有误
OP_2SWAP1140×72x1 x2 x3 x4x3 x4 x1 x2以一对元素为单位,交换栈顶的两对元素的位置。
1.4字符串

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

关键字

操作码

十六进制

输入

输出

描述

OP_CAT1260x7ex1 x2out连接两个字符串,已禁用
OP_SUBSTR1270x7fin begin sizeout返回字符串的一部分,已禁用
OP_LEFT1280×80in sizeout在一个字符串中保留左边指定长度的子串,已禁用
OP_RIGHT1290×81in sizeout在一个字符串中保留右边指定长度的子串,已禁用
OP_SIZE1300×82inin size把栈顶元素的字符串长度压入堆栈(无需弹出元素)
1.5位逻辑

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

关键字

操作码

十六进制

输入

输出

描述
OP_INVERT1310×83inout所有输入的位取反,已禁用.
OP_AND1320×84x1 x2out对输入的所有位进行布尔与运算,已禁用
OP_OR1330×85x1 x2out对输入的每一位进行布尔或运算,已禁用
OP_XOR1340×86x1 x2out对输入的每一位进行布尔异或运算,已禁用
OP_EQUAL1350×87x1 x2True / false如果输入的两个数相等,返回1,否则返回0。
OP_EQUALVERIFY1360×88x1 x2True / false与OP_EQUAL一样,之后运行OP_VERIFY 。
1.5算术逻辑

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

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

关键字

操作码

十六进制

输入

输出

描述
OP_1ADD1390x8binout输入值加1
OP_1SUB1400x8cinout输入值减1
OP_2MUL1410x8dinout输入值乘2,已禁用
OP_2DIV1420x8einout输入值除2,已禁用
OP_NEGATE1430x8finout输入值符号取反
OP_ABS1440×90inout输入值符号取正
OP_NOT1450×91inout如果输入值为0或1,则输出1或0;否则输出0。I
OP_0NOTEQUAL1460×92inout输入值为0输出0;否则输出1。
OP_ADD1470×93a bout输出a+b
OP_SUB1480×94a bout输出a-b
OP_MUL1490×95a bout输出a*b,已禁用
OP_DIV1500×96a bout输出a/b, 已禁用
OP_MOD1510×97a bout输出a/b的余数,已禁用
OP_LSHIFT1520×98a bout把a向左移动b位,保留符号,已禁用
OP_RSHIFT1530×99a bout把a向右移动b位,保留符号,已禁用
OP_BOOLAND1540x9aa bout如果a和b都不为0,输出1,否则输出0
OP_BOOLOR1550x9ba bout如果a或b不为0,输出1,否则输出0
OP_NUMEQUAL1560x9ca bout如果a=b则输出1,否则输出0。
OP_NUMEQUALVERIFY1570x9da bout与OP_NUMEQUAL一样,之后要运行OP_VERIFY
OP_NUMNOTEQUAL1580x9ea bout如果a!=b则输出1,否则输出0。
OP_LESSTHAN1590x9fa bout如果a<b则输出1,否则输出0。
OP_GREATERTHAN1600xa0a bout如果a>b则输出1,否则输出0。
OP_LESSTHANOREQUAL1610xa1a bout如果a<=b则输出1,否则输出0
OP_GREATERTHANOREQUAL1620xa2a bout如果a>=b则输出1,否则输出0
OP_MIN1630xa3a bout输出a,b中的最小值
OP_MAX1640xa4a bout输出a,b中的最大值
OP_WITHIN1650xa5x min maxout如果x在min和max之间,则输出1,否则输出
1.6加密

关键字

操作码

十六进制

输入

输出

描述

OP_RIPEMD1601660xa6inhash输入用RIPEMD-160算法HASH
OP_SHA11670xa7inhash输入用SHA-1算法HASH.
OP_SHA2561680xa8inhash输入用SHA-256算法HASH.
OP_HASH1601690xa9inhash输入被HASH两次,先用 SHA-256,再用 RIPEMD-160.
OP_HASH2561700xaainhash输入用SHA-256算法HASH两次.
OP_CODESEPARATOR1710xab所有签名检查只需匹配最近一次执行的OP_CODESEPARATOR 操作数据的签名即可。
OP_CHECKSIG1720xacsig pubkeyTrue / false全部交易的输出、输入和脚本(从最近执行的OP_CODESEPARATOR操作到最)都被HASH,OP_CHECKSIG使用的签名必须是该HASH值和公钥的有效签名,如果是真则返回1,否则返回0。
OP_CHECKSIGVERIFY1730xadsig pubkeyTrue / false与OP_CHECKSIG一样,但之后执行 OP_VERIFY
OP_CHECKMULTISIG1740xaex sig1 sig2 … <number of signatures> pub1 pub2 <number of public keys>True / False对于每个签名和公钥对,OP_CHECKSIG 都会被执行,如果公钥列得比签名多,一些公钥/签名对会失败。所有的签名要与公钥匹配。如果所有签名有效,输出1,否则返回0。因为存在BUG,一个未使用的外部值会从堆栈中删除。
OP_CHECKMULTISIGVERIFY1750xafx sig1 sig2 … <number of signatures> pub1 pub2 … <number of public keys>True / False与 OP_CHECKMULTISIG,一样,但是之后运行 OP_VERIFY。
1.7伪关键字

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

关键字

操作码

十六进制

描述

OP_PUBKEYHASH2530xfd表示公钥用OP_HASH160操作码HASH
OP_PUBKEY2540xfe表示与OP_CHECKSIG.兼容的一个公钥
OP_INVALIDOPCODE2550xff匹配任何未指定的操作码
1.8保留关键字

关键字

操作码

十六进制

描述

OP_RESERVED800×50交易无效,除非发生在未执行的OP_IF 分支
OP_VER980×62交易无效,除非发生在未执行的OP_IF 分支
OP_VERIF1010×65交易无效,即使发生在未执行的OP_IF 分支
OP_VERNOTIF1020×66交易无效,即使发生在未执行的OP_IF 分支
OP_RESERVED11370×89交易无效,除非发生在未执行的OP_IF 分支
OP_RESERVED21380x8a交易无效,除非发生在未执行的OP_IF 分支
OP_NOP1-OP_NOP10176-1850xb0-0xb9这些关键字被忽略
其实上诉关键字并未经常使用,常用的也就不到10个,后面会一一介绍。

2脚本

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

2.1支付到比特币地址的标准交易(pay-to-pubkey-hash)
  1. scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
复制代码
注意:scriptSig是消费交易的输入,而scriptPubKey是以前还未消费的交易的输出,例如:“可用”交易。以下是每个关键字的处理过程:

堆栈

脚本

描述

<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGscriptSig和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_CHECKSIGHASH栈顶元素
<sig> <pubKey> <pubHashA> <pubKeyHash>OP_EQUALVERIFY OP_CHECKSIG遇到常数,压入堆栈
<sig> <pubKey>OP_CHECKSIG检查两个栈顶元素是否相等
trueEmpty.用两个栈顶元素,检查签名是否正确。
2.2标准比特币产生交易(pay-to-pubkey)

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

  1. scriptPubKey: <pubKey> OP_CHECKSIGscriptSig: <sig>
复制代码

检查过程如下:

堆栈

脚本

描述

<sig><pubKey> P_CHECKSIGscriptSig和scriptPubKey联合
<sig> <pubKey>OP_CHECKSIG遇到常数,压入堆栈
true用两个栈顶元素,检查签名是否正确
2.3可证明的无法花掉/可删除的输出

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

  1.          scriptPubKey: OP_RETURN {zero or more ops}
复制代码

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


广阔的应用

利用区块链上的这一存储空间,发挥你的想象力,可以做很多事情。比如,编写一套自己的脚本协议,利用比特币网络发行TOKEN。事实上,很早就有人这么做了,而且以太坊协议原本是要建立在比特币网络上的。

目前又不少主流项目采用元数据功能在比特币区块链中进行资产的发行和转移活动,比如说合约币(CounterParty)和Omnilayer,最终能够达到证明特定的商品、资产、股票等所有权的目的。已经在比特币区块链中成功发行的资产包括BitCrystals、FoldingCoin和 Tether。 另外,公证通和BitProof通过结合区块链的不可更改性与元数据功能,确保特定文件的有效性和合理性。这是元数据应用最广的领域。 其它应用还包括数字艺术档案的访问权和版权以及区块链中信息的永久有效性。


限制

然而,由于比特币核心开发者认为 OP_RETURN 会导致用户在比特币网络上存储过多的非交易信息,可能影响比特币的正常使用,所以对unspendable transaction大小做了限制(最早是40字节,扩大到80字节,之后又缩小到40字节)。并且一笔交易最多只能包含有一个有OP_RETURN的output。这使得一些二层协议的项目转投其它主链。


2.4Anyone-Can-Spend输出

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

  1. scriptPubKey: (empty)
复制代码

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

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


例子

比特币交易
0x8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684

80b2c7e5118fdc996216bcf1e91f0c7f_70.png

我们可以看到第一个output被标志为Unspendable address,Type为空。然后我们可以看到具体内容

  1. OP_RETURN 636861726c6579206c6f766573206865696469
复制代码

0x36861726c6579206c6f766573206865696469经过UTF8-DECODER可以得到:

  1. charley loves heidi
复制代码


2 个回复

倒序浏览
admin  管理员 | 2018-5-3 09:58:11 | 显示全部楼层

主题 116|帖子 122|积分 30万

666666666666
admin  管理员 | 2018-5-3 09:59:16 | 显示全部楼层

主题 116|帖子 122|积分 30万


非常全面,不错不错

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则