Make STRICTENC invalid pubkeys fail the script rather than the opcode.
This turns STRICTENC turn into a softforking-safe change (even though it is not intended as a consensus rule), and as a result guarantee that using it for mempool validation only results in consensus-valid transactions in the mempool.
This commit is contained in:
@@ -207,9 +207,9 @@ bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, Sc
|
||||
return true;
|
||||
}
|
||||
|
||||
bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) {
|
||||
bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
|
||||
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) {
|
||||
return false;
|
||||
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -792,11 +792,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
// Drop the signature, since there's no way for a signature to sign itself
|
||||
scriptCode.FindAndDelete(CScript(vchSig));
|
||||
|
||||
if (!CheckSignatureEncoding(vchSig, flags, serror)) {
|
||||
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
|
||||
//serror is set
|
||||
return false;
|
||||
}
|
||||
bool fSuccess = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
@@ -855,13 +855,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
||||
valtype& vchSig = stacktop(-isig);
|
||||
valtype& vchPubKey = stacktop(-ikey);
|
||||
|
||||
if (!CheckSignatureEncoding(vchSig, flags, serror)) {
|
||||
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
|
||||
// serror is set
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check signature
|
||||
bool fOk = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode);
|
||||
|
||||
if (fOk) {
|
||||
isig++;
|
||||
|
||||
@@ -35,8 +35,8 @@ enum
|
||||
SCRIPT_VERIFY_P2SH = (1U << 0),
|
||||
|
||||
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
|
||||
// Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be
|
||||
// skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT).
|
||||
// Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure.
|
||||
// (softfork safe, but not used or intended as a consensus rule).
|
||||
SCRIPT_VERIFY_STRICTENC = (1U << 1),
|
||||
|
||||
// Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
|
||||
|
||||
@@ -61,6 +61,8 @@ const char* ScriptErrorString(const ScriptError serror)
|
||||
return "Dummy CHECKMULTISIG argument must be zero";
|
||||
case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS:
|
||||
return "NOPx reserved for soft-fork upgrades";
|
||||
case SCRIPT_ERR_PUBKEYTYPE:
|
||||
return "Public key is neither compressed or uncompressed";
|
||||
case SCRIPT_ERR_UNKNOWN_ERROR:
|
||||
case SCRIPT_ERR_ERROR_COUNT:
|
||||
default: break;
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef enum ScriptError_t
|
||||
SCRIPT_ERR_SIG_PUSHONLY,
|
||||
SCRIPT_ERR_SIG_HIGH_S,
|
||||
SCRIPT_ERR_SIG_NULLDUMMY,
|
||||
SCRIPT_ERR_PUBKEYTYPE,
|
||||
|
||||
/* softfork safeness */
|
||||
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
|
||||
|
||||
Reference in New Issue
Block a user