Merge #8634: Add policy: null signature for failed CHECK(MULTI)SIG
e41bd44 Add policy: null signature for failed CHECK(MULTI)SIG (Johnson Lau)
This commit is contained in:
parent
b224c02090
commit
a75d6110ee
@ -38,6 +38,7 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
|
||||
SCRIPT_VERIFY_NULLDUMMY |
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
|
||||
SCRIPT_VERIFY_CLEANSTACK |
|
||||
SCRIPT_VERIFY_NULLFAIL |
|
||||
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
|
||||
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
|
||||
SCRIPT_VERIFY_LOW_S;
|
||||
|
@ -877,6 +877,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
}
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
||||
|
||||
if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
|
||||
return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
stack.push_back(fSuccess ? vchTrue : vchFalse);
|
||||
@ -906,6 +909,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
if (nOpCount > MAX_OPS_PER_SCRIPT)
|
||||
return set_error(serror, SCRIPT_ERR_OP_COUNT);
|
||||
int ikey = ++i;
|
||||
// ikey2 is the position of last non-signature item in the stack. Top stack item = 1.
|
||||
// With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails.
|
||||
int ikey2 = nKeysCount + 2;
|
||||
i += nKeysCount;
|
||||
if ((int)stack.size() < i)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
@ -960,8 +966,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
}
|
||||
|
||||
// Clean up stack of actual arguments
|
||||
while (i-- > 1)
|
||||
while (i-- > 1) {
|
||||
// If the operation failed, we require that all signatures must be empty vector
|
||||
if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size())
|
||||
return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
|
||||
if (ikey2 > 0)
|
||||
ikey2--;
|
||||
popstack(stack);
|
||||
}
|
||||
|
||||
// A bug causes CHECKMULTISIG to consume one extra argument
|
||||
// whose contents were not checked in any way.
|
||||
|
@ -86,6 +86,10 @@ enum
|
||||
//
|
||||
// See BIP112 for details
|
||||
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10),
|
||||
|
||||
// Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
|
||||
//
|
||||
SCRIPT_VERIFY_NULLFAIL = (1U << 14),
|
||||
};
|
||||
|
||||
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
|
||||
|
@ -63,6 +63,8 @@ const char* ScriptErrorString(const ScriptError serror)
|
||||
return "Non-canonical signature: S value is unnecessarily high";
|
||||
case SCRIPT_ERR_SIG_NULLDUMMY:
|
||||
return "Dummy CHECKMULTISIG argument must be zero";
|
||||
case SCRIPT_ERR_SIG_NULLFAIL:
|
||||
return "Signature must be zero for failed CHECK(MULTI)SIG operation";
|
||||
case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS:
|
||||
return "NOPx reserved for soft-fork upgrades";
|
||||
case SCRIPT_ERR_PUBKEYTYPE:
|
||||
|
@ -48,6 +48,7 @@ typedef enum ScriptError_t
|
||||
SCRIPT_ERR_SIG_NULLDUMMY,
|
||||
SCRIPT_ERR_PUBKEYTYPE,
|
||||
SCRIPT_ERR_CLEANSTACK,
|
||||
SCRIPT_ERR_SIG_NULLFAIL,
|
||||
|
||||
/* softfork safeness */
|
||||
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
|
||||
|
@ -1485,6 +1485,27 @@
|
||||
"OK",
|
||||
"BIP66 example 4, with DERSIG"
|
||||
],
|
||||
[
|
||||
"0x09 0x300602010102010101",
|
||||
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
|
||||
"DERSIG",
|
||||
"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",
|
||||
@ -1836,5 +1857,15 @@
|
||||
["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
|
||||
["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"]
|
||||
]
|
||||
|
@ -88,6 +88,7 @@ static ScriptErrorDesc script_errors[]={
|
||||
{SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"},
|
||||
{SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"},
|
||||
{SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"},
|
||||
{SCRIPT_ERR_SIG_NULLFAIL, "NULLFAIL"},
|
||||
{SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}
|
||||
};
|
||||
|
||||
|
@ -44,6 +44,7 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
|
||||
(string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY)
|
||||
(string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
||||
(string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK)
|
||||
(string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL)
|
||||
(string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
|
||||
(string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user