txscript: Implement ScriptVerifyNullFail
ScriptVerifyNullFail defines that signatures must be empty if a CHECKSIG or CHECKMULTISIG operation fails. This commit also enables ScriptVerifyNullFail at the mempool policy level.
This commit is contained in:
parent
153dca5c1e
commit
0efea24aa6
7 changed files with 53 additions and 1 deletions
|
@ -1492,6 +1492,20 @@
|
|||
"OK",
|
||||
"BIP66 example 4, with DERSIG, non-null DER-compliant signature"
|
||||
],
|
||||
[
|
||||
"0",
|
||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||
"DERSIG,NULLFAIL",
|
||||
"OK",
|
||||
"BIP66 example 4, with DERSIG and NULLFAIL"
|
||||
],
|
||||
[
|
||||
"0x09 0x300602010102010101",
|
||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||
"DERSIG,NULLFAIL",
|
||||
"NULLFAIL",
|
||||
"BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
|
||||
|
@ -1844,5 +1858,15 @@
|
|||
["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
|
||||
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
|
||||
|
||||
["NULLFAIL should cover all signatures and signatures only"],
|
||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
|
||||
["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
|
||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||
["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||
["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
|
||||
|
||||
["The End"]
|
||||
]
|
||||
|
|
|
@ -62,6 +62,10 @@ const (
|
|||
// push operator. This is both rules 3 and 4 of BIP0062.
|
||||
ScriptVerifyMinimalData
|
||||
|
||||
// ScriptVerifyNullFail defines that signatures must be empty if
|
||||
// a CHECKSIG or CHECKMULTISIG operation fails.
|
||||
ScriptVerifyNullFail
|
||||
|
||||
// ScriptVerifySigPushOnly defines that signature scripts must contain
|
||||
// only pushed data. This is rule 2 of BIP0062.
|
||||
ScriptVerifySigPushOnly
|
||||
|
|
|
@ -204,6 +204,11 @@ const (
|
|||
// single element.
|
||||
ErrCleanStack
|
||||
|
||||
// ErrNullFail is returned when the ScriptVerifyNullFail flag is
|
||||
// set and signatures are not empty on failed checksig or checkmultisig
|
||||
// operations.
|
||||
ErrNullFail
|
||||
|
||||
// -------------------------------
|
||||
// Failures related to soft forks.
|
||||
// -------------------------------
|
||||
|
@ -266,6 +271,7 @@ var errorCodeStrings = map[ErrorCode]string{
|
|||
ErrSigNullDummy: "ErrSigNullDummy",
|
||||
ErrPubKeyType: "ErrPubKeyType",
|
||||
ErrCleanStack: "ErrCleanStack",
|
||||
ErrNullFail: "ErrNullFail",
|
||||
ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs",
|
||||
ErrNegativeLockTime: "ErrNegativeLockTime",
|
||||
ErrUnsatisfiedLockTime: "ErrUnsatisfiedLockTime",
|
||||
|
|
|
@ -53,6 +53,7 @@ func TestErrorCodeStringer(t *testing.T) {
|
|||
{ErrSigNullDummy, "ErrSigNullDummy"},
|
||||
{ErrPubKeyType, "ErrPubKeyType"},
|
||||
{ErrCleanStack, "ErrCleanStack"},
|
||||
{ErrNullFail, "ErrNullFail"},
|
||||
{ErrDiscourageUpgradableNOPs, "ErrDiscourageUpgradableNOPs"},
|
||||
{ErrNegativeLockTime, "ErrNegativeLockTime"},
|
||||
{ErrUnsatisfiedLockTime, "ErrUnsatisfiedLockTime"},
|
||||
|
|
|
@ -2084,6 +2084,11 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
|
|||
valid = signature.Verify(hash, pubKey)
|
||||
}
|
||||
|
||||
if !valid && vm.hasFlag(ScriptVerifyNullFail) && len(sigBytes) > 0 {
|
||||
str := "signature not empty on failed checksig"
|
||||
return scriptError(ErrNullFail, str)
|
||||
}
|
||||
|
||||
vm.dstack.PushBool(valid)
|
||||
return nil
|
||||
}
|
||||
|
@ -2318,6 +2323,15 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
|
|||
}
|
||||
}
|
||||
|
||||
if !success && vm.hasFlag(ScriptVerifyNullFail) {
|
||||
for _, sig := range signatures {
|
||||
if len(sig.signature) > 0 {
|
||||
str := "not all signatures empty on failed checkmultisig"
|
||||
return scriptError(ErrNullFail, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vm.dstack.PushBool(success)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) {
|
|||
// Nothing.
|
||||
case "NULLDUMMY":
|
||||
flags |= ScriptStrictMultiSig
|
||||
case "NULLFAIL":
|
||||
flags |= ScriptVerifyNullFail
|
||||
case "P2SH":
|
||||
flags |= ScriptBip16
|
||||
case "SIGPUSHONLY":
|
||||
|
@ -191,7 +193,7 @@ func parseExpectedResult(expected string) ([]ErrorCode, error) {
|
|||
case "EQUALVERIFY":
|
||||
return []ErrorCode{ErrEqualVerify}, nil
|
||||
case "NULLFAIL":
|
||||
return []ErrorCode{ErrSigNullDummy}, nil
|
||||
return []ErrorCode{ErrNullFail}, nil
|
||||
case "SIG_HIGH_S":
|
||||
return []ErrorCode{ErrSigHighS}, nil
|
||||
case "SIG_HASHTYPE":
|
||||
|
|
|
@ -33,6 +33,7 @@ const (
|
|||
ScriptStrictMultiSig |
|
||||
ScriptDiscourageUpgradableNops |
|
||||
ScriptVerifyCleanStack |
|
||||
ScriptVerifyNullFail |
|
||||
ScriptVerifyCheckLockTimeVerify |
|
||||
ScriptVerifyCheckSequenceVerify |
|
||||
ScriptVerifyLowS
|
||||
|
|
Loading…
Reference in a new issue