diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 82c8302be..d8b5eccdb 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -485,6 +485,12 @@ bool EvalScript(vector >& stack, const CScript& script, un if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); valtype& vch = stacktop(-1); + if (flags & SCRIPT_VERIFY_MINIMALIF) { + if (vch.size() > 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + if (vch.size() == 1 && vch[0] != 1) + return set_error(serror, SCRIPT_ERR_MINIMALIF); + } fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 79a7b093e..55d1fc3ef 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -82,15 +82,19 @@ enum // See BIP65 for details. SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), - // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. - // (softfork safe) - SCRIPT_VERIFY_DERKEY = (1U << 10), + // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. + // (softfork safe) + SCRIPT_VERIFY_DERKEY = (1U << 10), // support CHECKSEQUENCEVERIFY opcode // // See BIP112 for details SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), + // Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector + // + SCRIPT_VERIFY_MINIMALIF = (1U << 13), + // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed // SCRIPT_VERIFY_NULLFAIL = (1U << 14), diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index c06bce023..9ae757527 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -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_MINIMALIF: + return "OP_IF/NOTIF argument must be minimal"; case SCRIPT_ERR_SIG_NULLFAIL: return "Signature must be zero for failed CHECK(MULTI)SIG operation"; case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: diff --git a/src/script/script_error.h b/src/script/script_error.h index c3a31cb33..342b481dc 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -39,7 +39,7 @@ typedef enum ScriptError_t SCRIPT_ERR_NEGATIVE_LOCKTIME, SCRIPT_ERR_UNSATISFIED_LOCKTIME, - /* BIP62 */ + /* Malleability */ SCRIPT_ERR_SIG_HASHTYPE, SCRIPT_ERR_SIG_DER, SCRIPT_ERR_MINIMALDATA, @@ -48,13 +48,14 @@ typedef enum ScriptError_t SCRIPT_ERR_SIG_NULLDUMMY, SCRIPT_ERR_PUBKEYTYPE, SCRIPT_ERR_CLEANSTACK, + SCRIPT_ERR_MINIMALIF, SCRIPT_ERR_SIG_NULLFAIL, /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, - - /* count acks */ - SCRIPT_ERR_COUNT_ACKS_INVALID_PARAM, + + /* count acks */ + SCRIPT_ERR_COUNT_ACKS_INVALID_PARAM, SCRIPT_ERR_ERROR_COUNT } ScriptError; diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d9195bf34..57704e5da 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -44,6 +44,7 @@ static std::map 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("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF) (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY);