综述
本提案描述了改变比特币交易的验证规则,来修正与 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规则组成。
符号:
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至栈上:
S1L P1 CHECKSIG
0 S1L S2L 2 P1 P2 2 CHECKMULTISIG
这些脚本像以前一样返回FALSE至栈上:
0 P1 CHECKSIG
0 0 0 2 P1 P2 2 CHECKMULTISIG
在新规则执行后,先前的TRUE脚本将立即失败
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脚本将立即失败
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_CHECKSIGorOP_CHECKMULTISIG失败的脚本很少出现在主链上。从 V0.13.1 客户端开始,NULLFAIL 规则已经作为中继政策被强制执行。
当设计新脚本时,用户必须注意这些新规则。
实施
参考客户端的实现可以在下述网址获得:
https://github.com/bitcoin/bitcoin/blob/35fe0393f216aa6020fc929272118eade5628636/src/script/interpreter.cpp#L185
and
https://github.com/bitcoin/bitcoin/pull/8634
脚注
P2WPKH 的交易在 BIP141 中描述
请注意由于 v0.13.1 客户端中具体实现的细节,一些使用高 S 值的签名通过了LOW_S 检测。然而,这些签名肯定是无效的,由随后的 NULLFAIL 检测失败。
引用
https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki
本文由翻译,转载无需授权。
领取专属 10元无门槛券
私享最新 技术干货