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

BIP-18 hashScriptCheck

与 BIP-16 协议相同,换的是一套说法:用 dataSig、scriptCheck、hashScriptCheck 三件套重新表述 P2SH,并主张把旧的 scriptSig 与 scriptPubKey 宣布为过时名目。本 BIP 目前处于已完成状态。

一、档案卡

档案卡
编号BIP-18
标题hashScriptCheck
作者Luke Dashjr <[email protected]>
指定日期2012-01-27
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Complete(已完成)
阅读版https://bips.dev/18
官方原文https://github.com/bitcoin/bips/blob/master/bip-0018.mediawiki

二、放在哪一族

P2SH 族里最特殊的一份:它不提出新协议,而是给 BIP-16 的同一套协议换一副术语骨架。

原文 Rationale 写得很直白:本提案取代 BIP-12 与 BIP-17(两者都是给脚本系统做扩展、让 scriptPubKey 把验证外包出去);同时也取代 BIP-16——因为 BIP-16“在协议上与本提案完全相同”,区别只是 BIP-16 给出了一种具体实现写法,且为了保持协议表述的一致性而没有宣布 scriptPubKey 过时;本提案则认为应当把旧名目正式废弃、新交易类型一律用新结构表达。

配套仍是同一组:应用场景来自 BIP-11 的 M-of-N 多签,地址格式用 BIP-13。读本页要抓住一句话:链上发生的事实与 BIP-16 是同一件,变的只是文档如何命名与组织这件事。

三、它要解决什么

动机部分与 BIP-16、BIP-17 相同:P2SH 的目的,是把提供赎回条件的责任从付款人转移到赎回人,让付款人用一个固定长度的 20 字节哈希(可扫 QR 码、可复制粘贴)为任意复杂的条件付款。

在此之上,本提案多解决一个“表述问题”:旧的交易结构里,输入端叫 scriptSig、输出端叫 scriptPubKey,两者都是“被执行的脚本”。而 P2SH 的实际结构已经不是这个形状了——输入端本质上是一包数据加上最后一段待检脚本,输出端本质上只是一个哈希承诺。继续套旧名字,会让规范读起来与实际验证流程对不上。因此本提案主张:旧名目宣布过时(客户端为兼容仍须支持,但新交易类型不再使用),改用三个新元素把结构说清楚。

四、规则本身

4.1 三个新元素

相应地:兼容客户端必须继续支持 scriptSig 与 scriptPubKey(原文用大写 MUST),但新交易类型不应再使用它们;付款的服务与个人暂时仍应支持旧的基于公钥的地址,收款方也可以继续生成使用旧地址。

4.2 hashScriptCheck 的精确编码

必须恰好编码为:

0xa9 0x14 (20-byte-hash-value) 0x87

旧(BIP-18 之前)的客户端可以把这串字节解释成一条熟悉的旧脚本:

OP_HASH160 [20-byte-hash-value] OP_EQUAL

——这正是 BIP-16 定义的 P2SH 输出形式,两份文档在字节层面严丝合缝的原因就在这里。若模板不精确匹配,或交易所在区块的时间戳早于 hashScriptCheck 激活日,则必须走向后兼容模式,仍按 scriptSig + scriptPubKey 验证。

4.3 有效条件

一笔符合 hashScriptCheck 的输入有效,当且仅当:

矿工还应拿 scriptCheck 去对照“标准交易”模板。单签例:scriptCheck 为 [pubkey] OP_CHECKSIG,dataSig 为 [signature] {[pubkey] OP_CHECKSIG},hashScriptCheck 为该脚本的 20 字节哈希。

4.4 签名操作计数与前向兼容

scriptCheck 的签名操作不沿用旧规则,改为与 BIP-16 相同的静态计数:OP_CHECKSIG 类计 1;被 OP_1 至 OP_16 紧邻在前的 OP_CHECKMULTISIG 类计 1 至 16;其他 OP_CHECKMULTISIG 类计 20;总上限仍为每区块 20,000 次,理由同为防恶意区块用海量签名验证拖住全网。

前向兼容上,hashScriptCheck 的前两字节指明所用哈希算法与长度;本提案只允许 Hash160,但给将来其他算法留了位置。

五、谁必须动

普通持币人 / 付款人:无区别于 BIP-16 的变化,只向短哈希付款。

钱包与服务开发者:用新结构组织 P2SH 交易(dataSig / scriptCheck / hashScriptCheck),同时必须继续支持旧的 scriptSig / scriptPubKey 交易与旧公钥地址,不能因“宣布过时”就拒绝旧格式。

全节点与矿工(共识层):按新模式验证符合模板的输出(哈希须对上、scriptCheck 须执行通过),并把 scriptCheck 对照标准交易模板;原文同样给出了与 BIP-16 相同的 1 确认攻击说明,评定成本高、实操难。

旧实现:通常把这类交易视为非标准,不转发、不打包;验证他人区块时只核对 scriptCheck 的哈希是否对得上,不做其余验证。

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

状态为 Complete(已完成):这是仓库给它的标注,与 BIP-16 的 Deployed 不同——本页不要读成“另有一套 P2SH 被单独部署过”。原文设计的部署安排本就与 BIP-16 共用同一套动员办法:矿工在 coinbase 写 “/P2SH/” 表态,2012 年 3 月 15 日检查此前 7 天区块,达 550 个则 4 月 1 日后全面验证;多数不支持则推迟乃至否决。P2SH 最终是按这一套安排、以 BIP-16 的定义激活的;本提案完成的,是把同一协议重新表述成一套更贴合实际结构的新术语。

常见误读:

“BIP-18 是和 BIP-16 不兼容的另一套 P2SH 协议。”

不对。原文 Rationale 明确说两者“在协议上完全相同”,分歧只在两点:是否给出某种具体实现写法、以及是否宣布 scriptPubKey 过时。把它当成第二套互斥协议,会误读整段 P2SH 之争——真正的机制之争在 BIP-16 与 BIP-17 之间。

七、延伸

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