协议演进 / BIP/比特币改进提案 / BIP-12

BIP-12 OP_EVAL

提出新操作码 OP_EVAL:执行栈顶数据所代表的脚本,让收款方凭脚本哈希决定日后如何花费收款——这是 P2SH 的最初设计,最终未按此方案部署。本 BIP 目前处于已关闭状态。

一、档案卡

档案卡
编号BIP-12
标题OP_EVAL
作者Gavin Andresen <[email protected]>
指定日期2011-10-18
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Closed(已关闭)
阅读版https://bips.dev/12
官方原文https://github.com/bitcoin/bips/blob/master/bip-0012.mediawiki

二、放在哪一族

P2SH(pay-to-script-hash)设计竞赛的最初一案。BIP-13 在参见中把 BIP-12 标为 “the original P2SH design”;后来实际部署的是 BIP-16 的方案,另一竞争设计是 BIP-17 的 OP_CHECKHASHVERIFY。

它与 BIP-11 是同一时期的姊妹提案:BIP-11 先把多签定为标准交易,BIP-12 则试图更进一步,让任意复杂脚本都能藏进一个哈希里收款。读它是为了理解 P2SH 为什么最终没有选“执行数据”这条路。

三、它要解决什么

动机只有一句:启用“端到端”的安全钱包,以及向托管交易或其他复杂交易付款的方式,同时对旧客户端与旧矿工保持向后兼容。

问题在于旧有模式:付款方在付款时就必须知道这笔钱日后该如何赎回的全部细节。若收款条件是复杂的多签或托管脚本,付款方要构造冗长的脚本,体积与手续费成本也都压在付款一侧。

BIP-12 想把方向倒过来:由收款方指定日后花费这笔钱所需的交易类型,付款方只面对一个脚本哈希和一种新地址。

四、规则本身

4.1 OP_EVAL 的语义

OP_EVAL 重新定义既有的 OP_NOP1 操作码,执行时:

4.2 新的标准交易类型

与操作码配套,定义一种会被客户端转发、会被矿工打包的标准锁定脚本:

DUP HASH160 {20-byte-hash-value} EQUALVERIFY OP_EVAL

其解锁脚本为:

...signatures... {serialized script}

即赎回时给出签名与被序列化的脚本本身,节点先核对脚本的哈希与锁定脚本中的哈希一致,再用 OP_EVAL 执行该脚本。只有当这个被序列化的脚本本身属于标准交易类型之一时,花费 OP_EVAL 输出的交易才算标准交易。

4.3 设计理由

原文同时如实记录了主要反对意见:OP_EVAL 增加了复杂度,而“复杂度是安全的敌人”;把数据当代码执行,在历史上一直是安全漏洞的来源。作者的回应是:既有的比特币脚本系统本就在把作为数据传输的 scriptPubKey 交给每个实现去解释,OP_EVAL 只是移动了被解释的数据所在的位置,是否因此更不安全可以争论。

4.4 向后兼容与上线安排

因为 OP_EVAL 占用的是 OP_NOP1,旧客户端与旧矿工会把它当空操作:它们只核对序列化脚本的哈希是否正确,不做签名检查,哈希对了交易就算有效——这是它“出乎意料地向后兼容”的原因,也是风险所在。旧客户端在 OP_EVAL 交易被打包进区块之前会忽略它及其后续交易。

要避免恶意 OP_EVAL 交易造成链分裂,须小心处理两种新旧判断相反的情形:对新客户端无效、对旧客户端有效的,以及反过来的。为此原文安排:

原文还给出了一种针对旧客户端的 1 确认攻击:攻击者造一笔旧客户端看来有效、新客户端看来无效的 OP_EVAL 交易,再接一笔花掉它并付给受害者的标准交易,自行挖出包含两笔交易的区块;受害者若接受 1 确认付款,该区块被网络覆盖后两笔交易一并作废,攻击得手。原文认为这种攻击代价高(攻击者要挖一个明知会被作废的区块)、实施难(高价值交易本就不应只等 1 确认)。

五、谁必须动

普通持币人/付款方:只需知道收款方的脚本哈希与新地址,不必了解赎回脚本的细节。

收款方与钱包开发者:构造序列化脚本、在花费时随签名一并给出,并承担复杂脚本带来的体积与手续费成本。

全节点与矿工:需要升级以按新语义解释 OP_NOP1、执行被求值的脚本,并遵守 4.4 的过渡期安排与矿工信号约定;未升级者仍按空操作处理。

共识层:这是一次软分叉式的共识改动——新操作码重定义旧的 NOP 操作码,旧软件看到的交易仍“有效”,只是校验更弱。

六、现在算不算数,以及一个常见误读

状态为 Closed:OP_EVAL 没有按本 BIP 的方案部署上线。其文件头没有 Superseded-By 字段;P2SH 这一目标后来由 BIP-16 的方案实现并激活,BIP-13 则为其定义了沿用至今的地址格式。本 BIP 留下的价值是记录了落选方案的完整设计与争论——尤其是“把数据当代码执行”的安全顾虑,这正是它最终没被选中的语境。

常见误读:

“P2SH 就是用 OP_EVAL 实现的,BIP-12 是已激活的 P2SH 规范。”

不对。BIP-12 只是 P2SH 的原始设计案,状态 Closed;真正部署的 P2SH 是 BIP-16,它不需要新操作码,走的是让节点对特定脚本模板做额外校验的路子。两者要解决的问题相同,机制完全不同。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。