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

BIP-143 v0 见证程序的交易签名验证

为 0 版见证程序定义新的交易摘要算法,减少验签时的重复哈希,并让签名承诺所花输入的金额。本 BIP 目前处于已激活状态。

一、档案卡

档案卡
编号BIP-143
标题Transaction Signature Verification for Version 0 Witness Program
作者Johnson Lau <[email protected]>, Pieter Wuille <[email protected]>
指定日期2016-01-03
层级Consensus (soft fork)(共识(软分叉))
类型Specification(规范类)
状态Deployed(已激活)
阅读版https://bips.dev/143
官方原文https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

二、放在哪一族

隔离见证(SegWit)共识族的核心配套文档之一。BIP-141 定义见证的共识层结构,本篇紧随其后,专门规定 0 版见证程序里的签名到底对什么数据负责。

同族关系:

BIP-141:隔离见证(共识层),本篇随它一同部署

BIP-144:隔离见证(对等服务),管见证数据怎么在节点间传输

BIP-147:处理哑栈元素可锻性,与本篇同属 segwit 部署包

再往后,Taproot 的签名摘要另由 BIP-342 一系规定,不沿用本篇算法;本篇只管 0 版见证程序。

三、它要解决什么

原有脚本系统的签名摘要算法(SignatureHash)有两个原文明确指出的弱点。

3.1 哈希量随交易规模平方增长

每验一个签名,都要把交易的一个子集序列化后做双重 SHA256,哈希量与交易大小成正比;一笔交易里签名操作(sigops)越多,整体验签成本按 O(n²) 增长。原文举例:普通 1 MB 区块在 2015 年的一般电脑上约 2 秒可验完,而一笔含 5569 个 sigops 的 1 MB 交易可能要 25 秒。这类构造会拖慢全网验证。

3.2 签名不承诺输入金额

原算法不把“这个输入花了多少钱”算进摘要。在线节点可以自己去查被花输出的金额,但离线签名设备(冷钱包、硬件钱包)不知道金额,就算不出确切的花费与手续费;要补这个信息,又得把整笔被花交易搬进来,与轻量、气隙(air-gapped)设备的目标相冲突。

在原脚本系统里直接修这两点,要么是硬分叉,要么只能对新操作码做软分叉且限制很多。隔离见证软分叉恰好提供了一个干净的切口:可以为见证程序另定一套脚本语义,未升级节点仍把这类输出看作“任何人可花”,不破坏原系统。

四、规则本身

4.1 新摘要的十个字段

新算法只适用于 0 版见证程序中的签名操作。摘要是对下列序列化结果做双重 SHA256:

  1. 交易的 nVersion(4 字节小端);
  2. hashPrevouts(32 字节);
  3. hashSequence(32 字节);
  4. 当前输入的 outpoint(32 字节哈希 + 4 字节小端);
  5. 当前输入的 scriptCode;
  6. 本输入所花输出的金额(8 字节小端);
  7. 当前输入的 nSequence(4 字节小端);
  8. hashOutputs(32 字节);
  9. 交易的 nLocktime(4 字节小端);
  10. 签名的 sighash 类型(4 字节小端)。

其中第 6 项是关键新增:所有 sighash 类型都承诺本输入的金额。若有人给冷钱包喂了假金额,签出的签名会无效,资金不会因此丢失。

4.2 三个可复用的中间哈希

hashPrevouts、hashSequence、hashOutputs 先按 sighash 标志算好,同一交易的不同输入可以复用:

靠这层复用,整笔交易的哈希复杂度从 O(n²) 降到 O(n)。

4.3 与原算法的语义差异

sighash 类型的语义总体不变,但原文列明几处调整:

scriptCode 的取法也分两种:P2WPKH 时固定为 0x1976a914{20 字节公钥哈希}88ac,即等价的传统 P2PKH 脚本;P2WSH 时为 witnessScript 本身(按 CTxOut 中的脚本格式序列化),含 OP_CODESEPARATOR 时按上条规则截取。

4.4 公钥类型限制(策略层)

作为默认策略,P2WPKH 与 P2WSH 只接受压缩公钥:传入签名操作的每个公钥首字节必须为 0x02 或 0x03、长度必须为 33 字节,不合规的交易默认不转发、不打包。原文同时警告:这是为未来软分叉做准备,用户不得在 0 版见证程序中使用未压缩公钥,以免将来资金受损。

4.5 部署方式

原文写明:本提案随隔离见证软分叉(BIP-141)一同部署。

五、谁必须动

普通持币人:不必单独做什么。使用 SegWit 钱包时,签名由钱包按新算法生成即可;注意不要在 0 版见证程序中使用未压缩公钥。

钱包开发者:花费 v0 见证输出时,必须实现本篇的十项摘要算法,正确处理三个中间哈希在不同 sighash 标志下的取值,并把输入金额纳入签名;离线签名设备尤其要按新算法核对金额与手续费。

全节点与矿工:升级后按新算法验证见证程序中的签名;未升级节点看不到、也不验证见证数据,会把见证程序一律当作任何人可花。

共识层:本篇是软分叉的一部分,只对 0 版见证程序重新定义签名验证;原脚本系统的摘要算法原样保留,不受影响。

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

状态为 Deployed,中文状态记为已激活。它是隔离见证共识规则的组成部分:今天任何一笔 P2WPKH、P2WSH 花费,节点验签时用的都是这套摘要算法。原文未逐项列出各软件的实现情况,本页不另行臆测。

常见误读:

“BIP-143 把全网的签名算法都换掉了。”

不对。它只适用于 0 版见证程序内的签名操作;传统非见证输入仍用原有 SignatureHash 算法。两套算法并存,按输入类型分别适用——这正是它能以软分叉方式落地的原因。

七、延伸

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