术语表 /开发者参考
Bitcoin Script
又称比特币脚本。
- Bitcoin Script 是什么?
- 比特币脚本是每笔比特币输出所携带的一种基于栈的小型脚本语言,用于设定在这些比特币再次被花费之前,花费者必须满足的条件。
币并不是发送给某个人的。它们被锁定在一段简短的程序之后,而花费比特币就是提供数据,使该程序执行结束时栈顶为真值。该语言没有循环,也没有递归,传统脚本最多只能有10,000字节和201项操作,因此验证者始终知道运算会结束。这就是比特币从未出现过失控合约的原因。
运作方式
比特币脚本是一种从左到右读取的栈式机器,除此之外不做任何事。
数据推入栈中;操作从栈中弹出其参数,再把结果推回栈中。脚本没有变量,没有向后跳转,也无法读取正在验证的交易之外的任何内容。脚本在执行完毕且无错误、栈顶为真值时即为成功。
花费时有两部分相遇。被花费的输出带有锁,称为公钥脚本。花费它的输入带有证明,对较旧的输出称为签名脚本,对隔离见证输出称为见证。二者按先后顺序运行,栈在两者之间传递,绝不会拼接成一个程序。这一分离是早期引入的,因为当时发现,如果花费方能够向锁定一侧注入操作符,就可以改写花费条件。
比特币历史上最常见的脚本值得完整读一遍。一个 pay-to-public-key-hash 输出包含 OP_DUP、OP_HASH160、一个20字节的哈希、OP_EQUALVERIFY 和 OP_CHECKSIG。花费方提供一个签名和一个公钥。执行时先推入两者,复制公钥,把副本哈希为20字节,推入预期的哈希,比较两者,若不一致则中止,然后针对交易本身的序列化数据验证签名。共六个步骤,传统地址的全部安全性都建立在这六步之上。
这些限制是刻意设定的,也十分精确。传统脚本或 P2SH 脚本不得超过10,000字节或201项非推入操作。栈上的单个元素不得超过520字节。栈中不得容纳超过1,000个元素。单个 OP_CHECKMULTISIG 不得指定超过20个公钥。每一项上限的存在,都是为了无论有人写出什么脚本,验证一个区块的成本都保持有界。
该语言已经扩展过两次,方法是赋予保留的空操作码以实际含义。BIP65 在2015年12月定义了 OP_CHECKLOCKTIMEVERIFY,使输出可以在指定时间或区块高度之前拒绝被花费。BIP112 对 OP_CHECKSEQUENCEVERIFY 做了同样的事,该操作码自2016年7月的区块419,328起生效,增加了从币被确认时起计的相对时间锁。正是这两个操作码,使闪电网络通道、带截止期限的担保托管以及带时间锁的继承方案得以存在。
购买比特币时为何重要
您提币的地址是一种脚本类型,这一选择会体现在您下一笔手续费上。
花费一个传统 pay-to-public-key-hash 输入大约需要148虚拟字节。花费一个原生隔离见证输入大约需要68,因为 BIP141 引入的见证折扣按四分之一的费率计收见证数据,而 taproot 密钥路径花费则更小。在20 sat/vB 的费率下,这一差距就是小额提币的大部分成本,而且每次转移比特币都会重复发生。如果交易所允许您选择提币地址格式,选用较新的格式就是一项永久性的折扣。
脚本同样是多签金库的实质所在。2-of-3的安排就是一段脚本,指定三个公钥并要求两个签名,而某台设备能否如实显示并签署这样的脚本,本站的硬件钱包评测对此有直接讨论。任何基于时间锁的继承计划也是如此:只有仍有人持有该脚本,币才能找回,因此输出描述符(重建该脚本的纯文本配方)应与助记词一起纳入您的备份。
一项实用警告:当某个平台拒绝向您粘贴的地址发送时,原因几乎总是其提币代码无法构建该脚本类型,而不是您的地址有误。在转移您在意的余额之前,请先用少量资金测试任何不熟悉的地址格式。
1,840亿比特币漏洞与中本聪关闭的操作码
在2010年8月15日,区块74,638中包含一笔交易,创造了184,467,440,737.09551616比特币,分为两个输出,每个约922亿。
检查交易输出是否超过输入的代码使用定长有符号算术,而大到足以使该算术溢出的输出,其总和会变成负数,因此检查得以通过。大约五小时内出现了已修补的客户端,诚实链在高度74,691超过了问题链。这些币从未存在于人们实际使用的链上。
这一事件,加上字符串和算术操作中一系列相关漏洞,就是十五个操作码被永久禁用的原因:OP_CAT、OP_SUBSTR、OP_LEFT、OP_RIGHT、OP_INVERT、OP_AND、OP_OR、OP_XOR、OP_2MUL、OP_2DIV、OP_MUL、OP_DIV、OP_MOD、OP_LSHIFT 和 OP_RSHIFT。脚本中只要包含其中任何一个,该交易即无效,无论是否被执行。这次禁用是在时间压力下采取的粗糙手段,撤销其中一部分仍是正在进行的工作:BIP347 提议在 tapscript 中恢复 OP_CAT,那里较新的限制使其被滥用的难度大得多。
比特币脚本 vs tapscript
tapscript 是重新划定规则的比特币脚本,仅适用于 taproot 脚本路径花费之内。BIP342 取消了10,000字节的脚本大小上限和201项操作的上限,禁用了 OP_CHECKMULTISIG 和 OP_CHECKMULTISIGVERIFY,并增加 OP_CHECKSIGADD 作为替代,使多重签名策略可以批量验证。签名检查改为按预算计量而非计数:每个输入获得50加其见证序列化大小的预算,每次执行签名检查消耗其中的50。栈式机器相同,计量方式不同。
比特币脚本 vs 公钥脚本
比特币脚本是语言;公钥脚本是用该语言写成的一个程序。输出包含公钥脚本,即锁。花费它的输入包含签名脚本或见证,即钥匙。二者都是比特币脚本,而把其中任何一个简单地称为“脚本”,是阅读原始交易时最常见的混淆来源,因为这两半是分别求值的,而收到币时只有其中一半被承诺锁定。