Skip to content
On this page

比特币指令集

本文主要译自比特币 wiki

##约定

  • 数字是小端编码,也就是遵循英特尔处理器的规则
  • 整数的编码规则是最高位表示付好,对于一个字节的整数,0x81表示-1,0x80表示负0,0x03 表示3,0x83表示-3
  • 0表示 False, 其他表示 True

常数指令

名字指令十六进制输入输出描述
OP_000X00nothingnothing在站上放置一个空数组
N/A1-750x01-0x4bspecialdata指令支出后面有多少字节数据需要放置到栈上,比如03 01 02 03,03意味着后面有三个字节的数据01 02 03 需要放置到栈上,01 02 03就是执行后的栈顶数据
OP_PUSHDATA1760x4cspecial数据输入输出长度均不固定,0x4c 后面的第一个字节表示后面数据的长度比如以下指令 0x4c020102,执行完以后,栈顶为01 02
OP_PUSHDATA2770x4dspecial数据输入输出长度均不固定,0x4d 后面的两个字节表示后面数据的长度比如以下指令 0x4d00010001....ff,执行完以后,栈顶为0001....feff, 栈顶有256字节的数据,这些数据分别是00...ff
OP_PUSHDATA4780x4especial数据输入输出长度均不固定,0x4e 后面的四个字节表示后面数据的长度比如以下指令 0x4e000000010001....ff,其中4e 后面的00000001表示长度为2^24字节, 目前应该用不到,因为这远超出了一块的大小,是不允许的
OP_1NEGATIVE790X4F-1将数值-1放在栈顶,比特币的虚拟机是多少位的?
OP_1,OP_TRUE810x511将数值1放在栈顶
OP_2-OP_1682-960X52-0X602-16将数值2-16放置在栈顶

流程控制

名字指令十六进制输入输出描述
OP_NOP970x61就是一般的 nop 指令
OP_IF990X63True/false<expression> if [statements] [else [statements1]] endif移除栈顶,如果为真, statements 将会被执行
OP_NOTIF1000X64True/false<expression> notif [statements] [else [statements1]] endif移除栈顶,如果为假, statements 将会被执行
OP_ELSE1030X67True/false<expression> notif [statements] [else [statements1]] endif移除栈顶,如果为假, statements1 将会被执行
OP_ENDIF1040X68True/false<expression> notif [statements] [else [statements1]] endif主要用来标记if语句的结束
OP_verify1050X69True/false空移除栈顶,如果为假,交易直接标记为失败,为真,继续执行指令.
OP_RETURN1060x6a交易失败虚拟机执行到此,标记交易失败.因此如果一个交易的输出有 OP_RETURN, 那么意味着这是一个永远有效的 UTXO,谁也无法花费. 可以将此 UTXO value设置为0,用来记录一些特殊数据
OP_IF OP_ELSE示例

 假设初始栈,自顶向下

graph TD
A[栈底部
ff
fe
fd
]

指令如下: OP_1 OP_IF OP_2 OP_3 OP_ELSE OP_4 OP_5 OP_ENDIF 我们一步一步来看一下栈和指令的变化

1. OP_1

栈:

graph TD
A[栈底部
ff
fe
fd
1]

指令: OP_IF OP_2 OP_3 OP_ELSE OP_4 OP_5 OP_ENDIF

2. OP_IF

栈:

graph TD
A[栈底部
ff
fe
fd]

指令: OP_2 OP_3 OP_ELSE OP_4 OP_5 OP_ENDIF

因为条件为真,因此执行 OP_2 OP_3这两条语句,不执行 OP_4 OP_5.

3. OP_2 OP_3

栈:

graph TD
A[栈底部
ff
fe
fd
2
3]

指令: OP_ELSE OP_4 OP_5 OP_ENDIF

4. OP_2 OP_3

栈:

graph TD
A[栈底部
ff
fe
fd
2
3]

指令: 空 因为执行了 OP_IF else 模块不执行.

栈相关指令

名字指令十六进制输入输出描述
OP_TOALTSTACK1070x6bx1(alt)x1移动主栈栈顶数据到附加栈, 完全不清楚为什么比特币执行会有两个栈,在什么地方用呢
OP_FROMALTSTACK1080x6c(alt)x1x1移动附加栈栈顶数据到主栈
OP_IFDUP1150x73xx/xx如果 x 非0,栈上会有两份 x, 否则 什么都不做(栈不变化)
OP_DEPTH1160x74栈高度将栈上有多少数据信息放到栈顶
OP_DROP1170x75x丢弃栈顶数据
OP_DUP1180x76xx x复制栈顶数据
OP_NIP1190x77x1 x2x2 移除栈顶上面的一项
OP_OVER1200x78x1 x2x1 x2 x1复制栈第二项到栈顶
OP_PICK1210x79xn...x2 x1 x0 <n>xn ... x2 x1 x0 xn复制栈第 n 项到栈顶,这个 n 最大可以多大呢?
OP_ROLL1220x7axn... x2 x1 <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_2OVER1120x70x1 x2 x3 x4x1 x2 x3 x4 x1 x2复制栈第三第四项到栈顶
OP_2ROT1130x71x1 x2 x3 x4 x5 x6x3 x4 x5 x6 x1 x2移动栈第第五第六项到栈顶
OP_2SWAP1140x72x1 x2 x3 x4x3 x4 x1 x2交换栈顶一对数据

关于栈描述,栈是按照从左至右表示栈底到栈顶. 以OP_2ROT 为例, 输入: x1 x2 x3 x4 x5 x6 栈顶是 x6,第二项是 x5,以此类推,第六项是 x1 执行完输出为: x3 x4 x5 x6 x1 x2 栈顶是 x2,第二项是x1,以此类推,第六项是x3

字符串相关指令

名字指令描述
OP_CAT126已禁用,碰到此指令,交易直接失败
OP_SUBSTR127已禁用,碰到此指令,交易直接失败
OP_LEFT128已禁用,碰到此指令,交易直接失败
OP_RIGHT129已禁用,碰到此指令,交易直接失败
OP_SIZE130将栈上字符串的长度放到栈顶(不会弹出字符串)

位运算

名字指令十六进制输入输出描述
OP_INVERT1310x83已禁用,碰到此指令,交易直接失败
OP_AND1320x84已禁用,碰到此指令,交易直接失败
OP_OR1330x85已禁用,碰到此指令,交易直接失败
OP_XOR1340x86已禁用,碰到此指令,交易直接失败
OP_EQUAL1350x87x1 x2TRUE/false弹出栈顶两个数据,如果相等,放置1到栈顶,否则放置0到栈顶
OP_EQUALVERIFY1360x88x1 x2弹出栈顶两个数据,如果不等,交易直接失败,否则什么都不做.

算术运算

比特币不再支持乘除运算,碰到这样的指令,必须失败.这些指令就不列出了. 这些指令包括乘法指令(OP_MUL,OP_2MUL),除法指令(OP_DIV,OP_2DIV,OP_MOD),移位指令( OP_LSHIFT,OP_RSHIFT)

名字指令十六进制输入输出描述
OP_1ADD1390x8bxx+1栈顶数据加1
OP_1SUB1400x8cxx-1栈顶数据减1
OP_NEGATE1430x8fx-x符号取反
OP_ABS1440x90xabs(x)求栈顶的绝对值,弹出 x, 压入 x 的绝对值
OP_NOT1450x91xnot(x)x 转换位逻辑真假,然后取反,比如3,相当于真, not 以后为0
OP_0NOTEQUAL1460x92inout返回0,如果输入为0,否则1. 这条指令看不懂什么意思,怎么用
OP_ADD1470x93a ba+b求和
OP_SUB1480x94a ba-b求差
OP_BOOLAND1540x9aa ba && b如果 a b 都不是""(空字符串),输出为1,否则为0
OP_BOOLOR1550x9ba ba or b如果 a 或者 b 不是"",输出为1,否则为0
OP_NUMEQUAL1560x9ca ba==b弹出a,b 如果相等,放置1到栈顶,否则放置0
OP_NUMEQUALVERIFY1570x9da bnothing/fail如果 a,b 不等,交易失败,否则什么都不做
OP_NUMNOTEQUAL1580x9ea ba!=b如果 a,b 不等,栈顶放1,否则放0
OP_LESSTHAN1590x9fa ba<ba 是否小于 b
OP_GREATERTHAN1600xa0a ba>ba 是否大于 b
OP_LESSTHANOREQUAL1610xa1a ba<=ba 是否小于等于 b
OP_GREATERTHANOREQUAL1620xa2a ba>=ba 是否大于等于 b
OP_MIN1630xa3a ba<b?a:b弹出 a,b ,然后在栈顶放较小的
OP_MAX1640xa4a ba>b?a:b弹出 a,b,然后放较大的
OP_WITHIN1650xa5x a btrue/false弹出 x,a,b,如果 x 介于 a,b 之间,放1,否则放0

密码学指令

名字指令十六进制输入输出描述
OP_RIPEMD1601660xa6inhashhash=RIPEMD160(in), 问题是如何知道 in 的长度是多少呢?怎么界定?
OP_SHA11670xa7inhash求sha1.
OP_SHA2561680xa8inhash求sha256
OP_HASH1601690xa9inhashripemd160(sha256(in))
OP_HASH2561700xaainhashsha256(sha256(in))
OP_CODESEPARATOR1710xabNothingNothing代码数据分隔符.
OP_CHECKSIG1720xacsig pubkeyTrue / false弹出 signature,pubkey, 验证两者是否匹配. 至于签名内容包含什么,可以参考我另一篇博客比特币 解锁脚本signature script 包含了那些东西
OP_CHECKSIGVERIFY1730xadsig pubkeyNothing / fail和前一条指令功能相同,如果验证为假,那么交易直接失败
OP_CHECKMULTISIG1740xaex sig1 sig2 ... pub1 pub2True / False多重签名验证 , 弹出的数据根据 n/m 来确定.
OP_CHECKMULTISIGVERIFY1750xafx sig1 sig2 ... pub1 pub2 ...Nothing / fail先做OP_CHECKMULTISIG, 然后执行OP_VERIFY

LockTime

名字指令十六进制输入输出描述
OP_CHECKLOCKTIMEVERIFY (previously OP_NOP2)1770xb1xx / fail基本功能就是为了阻止 TxOut 只能在某个绝对块数之后被花出,比如30000 OP_CHECKLOCKTIMEVERIFY DROP ...表示30000块之后后续脚本才有可能成功,否则必定失败. 详细功能参考 BIP 0065.
OP_CHECKSEQUENCEVERIFY (previously OP_NOP3)1780xb2xx / fail使用 TxIn中的 nSequence 中的作为相对块数,表示只能在花费的那个UTXO 被挖矿nSequence块以后才能花费那个 UTXO.详细参考 BIP 0112.

关于OP_CHECKLOCKTIMEVERIFY的一个示例

    IF
        <now + 3 months> CHECKLOCKTIMEVERIFY DROP
        <Lenny's pubkey> CHECKSIGVERIFY
        1
    ELSE
        2
    ENDIF
    <Alice's pubkey> <Bob's pubkey> 2 CHECKMULTISIG

上面的脚本中< now+3 months> 就是一个从现在起,推算出来的一个绝对块数,比如现在是5000000块,那么三个月以后就是5012960块

那么解锁脚本是什么呢,有两种情况 一种是三个月以后,使用Alice或者 Bob 的签名,加上 Lenny 的签名 一种是随时用Alice和 Bob 的签名

#####第一种情况,解锁脚本是

0 <Alice/Bob's signature> <Lenny's signature> 1

解锁脚本从左到右一次压栈,

  1. 1表示走上面的分支
  2. 验证是否是三个月以后了
  3. 第一个 CHECKSIGVERIFY验证Lenny的签名是否正确
  4. 第二个CHECKMULTISIG输入是 0 <Alice/Bob's signature> 1 <Alice's pubkey> <Bob's pubkey> 2 CHECKMULTISIG ,因此随便 Alice/Bob 的一个有效签名都可以花费该 UTXO
第二种情况解锁脚本
0 <Alice's signature> <Bob's signature> 0
  1. 0表示走下面的分支
  2. 也就是一个2-2的多重签名验证,因此需要 Alice/Bob 都签名才可以.

OP_CHECKSEQUENCEVERIFY解释

 IF
        2 <Alice's pubkey> <Bob's pubkey> <Escrow's pubkey> 3 CHECKMULTISIG
ELSE
    "30d" CHECKSEQUENCEVERIFY DROP
    <Alice's pubkey> CHECKSIG
ENDIF

如果走2-3多重签名,随时可以花费,但是如果走下面的分支,则需要等30天(这个30天是从被引用的 UTXO 被打包算起)以后.这里面主要是涉及到一个可以引用还未打包的交易机制.30天以后,只要用 Alice 的签名就可以解锁.