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

BIP-347 Tapscript 中的 OP_CAT

提出在 Tapscript 中重新启用 OP_CAT,把栈顶两个值拼接成一个,以补上 Tapscript 缺少的一种通用拼接能力。本 BIP 目前处于已完成状态。

一、档案卡

档案卡
编号BIP-347
标题OP_CAT in Tapscript
作者Ethan Heilman <[email protected]>
Armin Sabouri <[email protected]>
指定日期2023-12-11
讨论日期2023-10-21
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Complete(已完成)
依赖BIP-340、BIP-341、BIP-342
阅读版https://bips.dev/347
官方原文https://github.com/bitcoin/bips/blob/master/bip-0347.mediawiki

二、放在哪一族

Tapscript 能力扩展族,也是“恢复早期被禁用操作码”这一脉。本 BIP 只做一件事:把拼接操作带回 Tapscript,因此它依赖 Taproot 的整套基础:

BIP-340:Schnorr 签名

BIP-341:Taproot 输出结构

BIP-342:Tapscript 验证规则;本 BIP 正是走它留下的 OP_SUCCESSx 软分叉升级路径

它常与同批的小原语一起被讨论,如 BIP-348(OP_CHECKSIGFROMSTACK):原文列举的若干用法——比如在脚本内拼出待验签的数据再验签、构造默克尔树——靠的是 CAT 的拼接加上哈希与验签类操作码配合。原文还专门比较了它与金库的关系:按 Andrew Poelstra 的构造,OP_CAT 本身即足以在比特币上搭出金库(vault),与 BIP-345 的专用金库操作码是两种不同路线。

三、它要解决什么

Tapscript 没有一种通用的办法把栈上的两个值拼起来。这看似小事,却卡住了整整一类构造:脚本无法自己拼装并计算默克尔树及其他哈希数据结构,表达能力因此受限。

原文列举了 OP_CAT 能解锁或大幅简化的用途(非穷尽):

历史背景:OP_CAT 在早期比特币里本来就有,2010 年被一个提交连同另外 15 个操作码一并禁用。流传的说法是它可被用来构造求值时内存占用随脚本长度指数膨胀的脚本——例如把 1 字节值反复 OP_DUP、OP_CAT 四十次。本 BIP 的回应是:Tapscript 已强制栈元素最大 520 字节,这个口子在今天的规则下不存在了。

四、规则本身

4.1 语义

OP_CAT 执行时:

失败条件只有两个:栈上不足两个值;或拼接结果超过脚本元素最大尺寸 520 字节。

4.2 激活方式

以软分叉方式重定义 Tapscript 操作码 OP_SUCCESS126(十进制 126、十六进制 0x7e)为 OP_CAT。特意选 126,是因为这正是 OP_CAT 当年被禁用前使用的操作码值,沿用旧值避免多一层混淆。升级机制走 BIP-342 预留的 OP_SUCCESSx 路径。

原文还说明了一个取舍:本 BIP 不借机改动 520 字节的栈元素上限——是否放大这个上限,应当与是否重新启用 CAT 分开决策,本 BIP 对此不持立场。

4.3 适用范围

只改 Tapscript。在非 Tapscript 脚本里使用 OP_CAT,仍然触发 SCRIPT_ERR_DISABLED_OPCODE(禁用操作码错误),与今天完全一样。

参考实现只有十来行,与 2010 年被禁用前的原实现基本相同,差别只在上限:原文实现把结果大小上限从当年的 5000 字节收紧为今天的 520 字节(MAX_SCRIPT_ELEMENT_SIZE)。

五、谁必须动

普通持币人:无直接动作。地址、钱包格式都不因此改变。

钱包与脚本开发者:是直接使用者。用 CAT 拼装数据时要守住 520 字节上限,脚本设计要按拼接后尺寸核算;在它真正激活之前,任何含 OP_CAT 的 Tapscript 都不能按新语义在主网花费。

全节点与矿工:若将来部署,这是一次共识软分叉:节点把 OP_SUCCESS126 按 CAT 语义验证,并执行 520 字节上限。不升级的旧节点按 OP_SUCCESS 旧语义直接放行——这是软分叉的兼容方式。

共识层:改动严格限于 Tapscript 语境;传统脚本与 SegWit v0 脚本中的 OP_CAT 仍是禁用操作码。

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

状态为 Complete(已完成):按现行 BIP 流程,这表示规范本身已写完、定稿——原文变更日志记有 1.0.0 版于 2026-03-01 标记为 complete。但 Complete 不是 Deployed:原文通篇以“将通过软分叉激活”的口吻写 OP_SUCCESS126 的重定义,是否、何时在主网激活,不由这份文档决定,要另行走部署流程并得到节点与经济多数的采用。在激活之前,主网上的 OP_SUCCESS126 仍只是“见之即通过”的占位操作码。

常见误读:

“OP_CAT 状态已完成,就是已经在比特币主网上线了。”

不对。Complete 只说明文档定稿。它与 BIP-11 那样的 Deployed(已部署、网络在实际执行)是两个状态。把“规范完成”读成“功能上线”,会误判今天能写什么样的 Tapscript——今天在主网认真用 OP_CAT 构造的脚本,并不会按 CAT 语义被验证。

七、延伸

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