综述
本提案描述了改变比特币交易的验证规则,来修正与ECDSA签名编码有关的交易延展性。
动机
签名延展性指的是:网络中的任何中继节点,不需要获取对应交易的私钥, 而修改该交易签名的能力。对于非SW交易,签名延展性将改变txid,将使所有未确认的子交易失效。即使SW交易(BIP141)的txid是非第三方延展的,但这种延展性的vector仍然将改变wtxid,并且可能降低紧凑型区块的中继效率(BIP152)。
自从严格的DER签名实施后,ECDSA签名中还有两个已知的延展性来源:
- ECDSA自身的签名延展性:ECDSA签名是自身具有延展性,因为内部S的负值(模曲线顺序)不会使签名无效。
- 无效签名的延展性:如果采用OP_CHECKSIG 或OP_CHECKMULTISIG 的签名验证失败,一个false将被返回到栈上,并且脚本验证将继续执行。无效签名可以使用任何值,只要这些值遵循BIP66 中描述的所有规则。
本提案定义了新的规则来修正上述提到的延展性。
规则
为了修正签名编码的延展性,接下来的新规则被应用到当下的隔离验证和隔离验证脚本。
LOW_S
新规则要求ECDSA签名内的S的值最大是曲线半径除以2(实际上将该值限制在其下半部分范围内)。每个使用了OP_CHECKSIG1,OP_CHECKSIGVERIFY,OP_CHECKMULTISIG,OP_CHECKMULTISIGVERIFY操作码的签名,同时该签名采用了ECDSA验证,则必须使用一个介于0x1和0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,并且采用严格DER编码的S值。
如果传递给ECDSA验证的签名没有通过LOW_S 检查,并且是一个非空的字节数组,则整个脚本评估立即失败。
在签名中一个高S值可以平滑的被S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S 替换。
NULLFAIL
如果一个OP_CHECKSIG试图向栈上返回一个false值,那我们要求对应的签名必须是一个空的字节数组。
如果一个OP_CHECKMULTISIG试图向栈上返回一个false,我们要求传输到OP_CHECKMULTISIG的所有签名必须是空的字节数组,即使由于过早的签名验证中断而可能导致一些签名处理被跳过。
否则,整个脚本评估立即失败。
示例
接下来的示例由LOW_S和NULLFAIL2 规则组成。
符号:
代码语言:javascript复制CO : curve order = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
HCO : half curve order = CO / 2 = 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0
P1, P2 : valid, serialized, public keys
S1L, S2L : valid low S value signatures using respective keys P1 and P2 (1 ≤ S ≤ HCO)
S1H, S2H : signatures with high S value (otherwise valid) using respective keys P1 and P2 (HCO < S < CO)
F : any BIP66-compliant non-empty byte array but not a valid signature
这些脚本像以前一样返回TRUE至栈上:
代码语言:javascript复制S1L P1 CHECKSIG
0 S1L S2L 2 P1 P2 2 CHECKMULTISIG
这些脚本像以前一样返回FALSE至栈上:
代码语言:javascript复制0 P1 CHECKSIG
0 0 0 2 P1 P2 2 CHECKMULTISIG
在新规则执行后,先前的TRUE脚本将立即失败
代码语言:javascript复制S1H P1 CHECKSIG
0 S1H S2L 2 P1 P2 2 CHECKMULTISIG
0 S1L S2H 2 P1 P2 2 CHECKMULTISIG
0 S1H S2H 2 P1 P2 2 CHECKMULTISIG
在新规则执行后,先前的TRUE脚本将立即失败
代码语言:javascript复制 F P1 CHECKSIG
0 S2L S1L 2 P1 P2 2 CHECKMULTISIG
0 S1L F 2 P1 P2 2 CHECKMULTISIG
0 F S2L 2 P1 P2 2 CHECKMULTISIG
0 S1L 0 2 P1 P2 2 CHECKMULTISIG
0 0 S2L 2 P1 P2 2 CHECKMULTISIG
0 F 0 2 P1 P2 2 CHECKMULTISIG
0 0 F 2 P1 P2 2 CHECKMULTISIG
部署:
该BIP将通过BIP9(版本位)进行部署。
比特币主网络中,BIP9的开始时间是:midnight TBD UTC(纪元时间戳TBD),BIP的结束时间是:midnight TBD UTC(纪元时间戳TBD)。
比特币测试网络中,BIP9的开始时间是:midnight TBD UTC(纪元时间戳TBD),BIP的结束时间是:midnight TBD UTC(纪元时间戳TBD)。
兼容性
从v0.9.0,客户端已产生了LOW_S兼容性脚本,并且从v0.11.1客户端开始,LOW_S规则已经作为中继策略被强制执行。截止2016年8月,违反上述规则的交易很少被添加至主链中。对于实际使用的所有scriptPubKey 类型,非兼容性的签名可以平滑的被转换为兼容性,所以这些新规则并没有任何导致任何功能的丢失。
使用 OP_CHECKSIG or OP_CHECKMULTISIG失败的脚本很少出现在主链上。从v0.13.1客户端开始,NULLFAIL 规则已经作为中继政策被强制执行。
当设计新脚本时,用户必须注意这些新规则。
实施
参考客户端的实现可以在下述网址获得:github/interpreter.cpp 和 github/pull
脚注
- P2WPKH的交易在BIP141中描述
- 请注意由于v0.13.1客户端中具体实现的细节,一些使用高S值的签名通过了LOW_S检测。然而,这些签名肯定是无效的,由随后的NULLFAIL检测失败。
引用
BIP146原文 : https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki ECDSA博文 : http://www.instructables.com/id/Understanding-how-ECDSA-protects-your-data/
本文由 Copernicus团队 姚永芯
翻译,转载无需授权。