跳转到正文
buybitcoinsmart

术语表 /开发者参考

操作码

又称 Opcode、数据推入操作码、非数据推入操作码、比特币脚本操作码。

操作码是什么?
操作码(opcode)是 Bitcoin Script 中的单个字节,用于告知验证节点下一步该做什么:要么将数据压入堆栈,要么对堆栈中已有的数据执行一项操作。

Bitcoin Script 拥有固定的词汇表,共有256个可能的字节值,分为压入字面数据的操作码(opcode)和对已压入数据执行操作的操作码。传统(legacy)脚本最多只能执行201个执行操作的操作码,且大小不得超过10,000字节。对购买比特币的人来说,这套精简的词汇表正是钱包能在广播交易前报出手续费的原因,也是比特币没有给失控的合约漏洞留下可乘之机的原因。

运作方式

验证节点逐字节读取脚本,并在固定的表中查找每个字节。0x01 至0x4b 的值根本不是指令:每个值表示接下来的 N 个字节是字面数据,应放入堆栈,因此33字节的压缩公钥在脚本中表现为0x21 后面跟着公钥本身。另外三个压入代码 OP_PUSHDATA1、OP_PUSHDATA2 和 OP_PUSHDATA4 用于更长的数据项,而0x51 至0x60 的值则压入出现在签名阈值计数中的小整数1至16。

0x60 以上的值都是执行操作而不是携带数据,比特币计数的正是这些操作码。Taproot 之前的脚本最多可包含201个这类操作码,堆栈元素不得超过520字节,堆栈中的项目总数不得超过1,000个,脚本总大小不得超过10,000字节。这四个数字都出自 Bitcoin Core 的 script.h,并且都是共识规则,而不是节点运营者可以放宽的偏好。

表中列出了十五个操作码,但它们已经失效。OP_CAT、OP_MUL、OP_LSHIFT 以及另外十二个操作码在2010年因一个崩溃漏洞而被关闭,脚本只要包含其中任何一个就会失败,即使它位于一个永远不会执行的分支中。这些操作码从未被重新启用。这一项决定是比特币脚本比 "programmable" 一词让人预期的更为有限的最大原因。

Tapscript 重写了 Taproot 花费的记账方式。BIP-342自2021年11月的区块709,632起生效,取消了201条指令的上限和10,000字节的大小上限,并代之以签名预算:脚本每检查一个签名,交易就必须携带50个权重单位。它还把一段未定义的字节值变成了 OP_SUCCESS 代码,因此包含其中一个的脚本完全无需执行就是有效的。这是为未来升级特意留出的空间。

购买比特币时为何重要

操作码决定您的提币成本。传统输出用25字节写出围绕20字节哈希的四条执行指令;原生 SegWit 的对应写法是一个版本字节加一次压入,共22字节;Taproot 输出为34字节。由于 SegWit 把解锁部分移入见证数据,而见证数据的权重只有四分之一,花费 bech32 输出大约需要68个虚拟字节,而同一笔付款的传统版本大约需要148个。提币时只要交易所提供,就选择 bech32 或 bech32m,这几乎是本术语表中成本最低的决定。

操作码还决定您的签名设备实际能处理什么。只识别标准单密钥模板的硬件钱包,无法为带时间锁的保险库或不常见的策略共同签名,因此,如果您的计划中涉及继承规划或多重签名,请在购买设备之前而不是在比特币已存入之后,到评测中核实其对脚本的支持情况。

这种局限是一种安全属性,而不是缺陷。比特币脚本没有循环,无法读取另一笔交易,也没有在两次花费之间持续存在的状态,因此,合约在其作者从未考虑过的输入上仍然按预期运行,这种曾让可编程区块链流失数十亿美元的故障模式,在这里没有发生的余地。比特币的损失来自交易所、钓鱼攻击和丢失的备份,而不是脚本引擎出错。

实例:OP_NOP2 获得实际作用的那一天

OP_NOP2 曾是字节0xb1,什么也不做,是表中留作日后使用的十个带编号的空操作之一。BIP-65给了它一项任务:确认交易的锁定时间已过,否则使脚本失败。该规则自区块388,381起在2015年12月14日开始强制执行,此后这个操作码一直称为 OP_CHECKLOCKTIMEVERIFY。

关键在于,旧软件看到的仍然是一个什么也不做的字节,因此仍把新交易当作有效交易接受。只有升级后的节点才强制执行时间锁。这种不对称正是软分叉之所以“软”的原因,OP_NOP3 也走同一条路径,在2016年7月的区块419,328变成了 OP_CHECKSEQUENCEVERIFY。目前还剩八个预留的空操作位置,这是比特币在 Taproot 之前的规则下剩余升级空间的大部分,也是大量设计精力转向 Tapscript 所创建的 OP_SUCCESS 值的重要原因。

操作码 vs Bitcoin Script

Bitcoin Script 是语言,操作码是其词汇表中的一个词。在阅读关于比特币能做什么、不能做什么的说法时,这一区别很重要,因为近十年来几乎所有严肃的提案,都是提议定义一个新的操作码,而不是改变其周围的语言。OP_CHECKTEMPLATEVERIFY、OP_CAT 和 OP_CHECKSIGADD 各自只是一个字节、一项功能,关于契约(covenant)或保险库的公开争论,争的是某一个特定字节是否应被允许承载某种含义。新操作码出现时,堆栈、各项限制以及没有循环这一点都保持不变。

请勿混淆

常见问题

比特币能像以太坊那样运行智能合约吗?

不能,这是有意的设计。比特币脚本(Bitcoin Script)没有循环,也没有跨交易的持久存储,并且其算术和字符串操作码中有15个自2010年起已被禁用,因此一个脚本只能针对固定的支出条件回答“是”或“否”。

购买或持有比特币需要了解操作码吗?

不需要。钱包会为您生成脚本。只有在提币时选择地址格式,或设置多重签名时,操作码才值得了解,因为这两项决定都会改变所运行的操作码,以及支出所需的手续费。

比特币如何在不分裂区块链的情况下新增操作码?

做法是重新定义一个旧节点本来就会忽略的字节。OP_NOP2 和 OP_NOP3 就是这样在2015年和2016年成为两个时间锁操作码的,Tapscript 也在2021年为同一目的预留了一段新的 OP_SUCCESS 值。

接着阅读

相关术语

开发者参考中的更多术语

阅读本页英文版