From d353dd121be0bf2a525e4bbea2b4ada2954d2b15 Mon Sep 17 00:00:00 2001 From: Johnson Lau Date: Fri, 27 Apr 2018 03:56:29 +0800 Subject: Add constant scriptCode policy in non-segwit scripts This disables OP_CODESEPARATOR in non-segwit scripts (even in an unexecuted branch), and makes a positive FindAndDelete result invalid. This ensures that the scriptCode serialized in SignatureHash() is always the same as the script passing to the EvalScript. Github-Pull: #11423 Rebased-From: 9dabfe49c066301ef75bcfcb089fd308366127c4 --- src/script/interpreter.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/script/interpreter.cpp') diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 2cdff7ee57..8b26caef5d 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -306,6 +306,10 @@ bool EvalScript(std::vector >& stack, const CScript& opcode == OP_RSHIFT) return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes. + // With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR in non-segwit script is rejected even in an unexecuted branch + if (opcode == OP_CODESEPARATOR && sigversion == SIGVERSION_BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE)) + return set_error(serror, SCRIPT_ERR_OP_CODESEPARATOR); + if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) { return set_error(serror, SCRIPT_ERR_MINIMALDATA); @@ -869,6 +873,9 @@ bool EvalScript(std::vector >& stack, const CScript& case OP_CODESEPARATOR: { + // If SCRIPT_VERIFY_CONST_SCRIPTCODE flag is set, use of OP_CODESEPARATOR is rejected in pre-segwit + // script, even in an unexecuted branch (this is checked above the opcode case statement). + // Hash starts after the code separator pbegincodehash = pc; } @@ -889,7 +896,9 @@ bool EvalScript(std::vector >& stack, const CScript& // Drop the signature in pre-segwit scripts but not segwit scripts if (sigversion == SIGVERSION_BASE) { - scriptCode.FindAndDelete(CScript(vchSig)); + int found = scriptCode.FindAndDelete(CScript(vchSig)); + if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE)) + return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE); } if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) { @@ -953,7 +962,9 @@ bool EvalScript(std::vector >& stack, const CScript& { valtype& vchSig = stacktop(-isig-k); if (sigversion == SIGVERSION_BASE) { - scriptCode.FindAndDelete(CScript(vchSig)); + int found = scriptCode.FindAndDelete(CScript(vchSig)); + if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE)) + return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE); } } -- cgit v1.2.3