aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohnson Lau <jl2012@xbt.hk>2018-04-27 03:56:29 +0800
committerJohnson Lau <jl2012@xbt.hk>2018-05-05 04:26:12 +0800
commit9dabfe49c066301ef75bcfcb089fd308366127c4 (patch)
tree9640b1303dc21c3dc68463833d9f34145a118b2e /src
parent627c3762ce5d8ce097f70c7fb52a3640246fae9b (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/policy/policy.h3
-rw-r--r--src/script/interpreter.cpp15
-rw-r--r--src/script/interpreter.h4
-rw-r--r--src/script/script_error.cpp4
-rw-r--r--src/script/script_error.h4
-rw-r--r--src/test/script_tests.cpp2
6 files changed, 29 insertions, 3 deletions
diff --git a/src/policy/policy.h b/src/policy/policy.h
index e4eda4b635..6ba3ba7450 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -63,7 +63,8 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VE
SCRIPT_VERIFY_LOW_S |
SCRIPT_VERIFY_WITNESS |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
- SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
+ SCRIPT_VERIFY_WITNESS_PUBKEYTYPE |
+ SCRIPT_VERIFY_CONST_SCRIPTCODE;
/** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index e0d193fa38..13f41a7cbf 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -336,6 +336,10 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& 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);
@@ -899,6 +903,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& 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;
}
@@ -919,7 +926,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
// Drop the signature in pre-segwit scripts but not segwit scripts
if (sigversion == SigVersion::BASE) {
- FindAndDelete(scriptCode, CScript(vchSig));
+ int found = FindAndDelete(scriptCode, 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)) {
@@ -983,7 +992,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
valtype& vchSig = stacktop(-isig-k);
if (sigversion == SigVersion::BASE) {
- FindAndDelete(scriptCode, CScript(vchSig));
+ int found = FindAndDelete(scriptCode, CScript(vchSig));
+ if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
+ return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);
}
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 50c747900a..2800473a68 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -111,6 +111,10 @@ enum
// Public keys in segregated witness scripts must be compressed
//
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15),
+
+ // Making OP_CODESEPARATOR and FindAndDelete fail any non-segwit scripts
+ //
+ SCRIPT_VERIFY_CONST_SCRIPTCODE = (1U << 16),
};
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index dbceb1f740..ceda740580 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -89,6 +89,10 @@ const char* ScriptErrorString(const ScriptError serror)
return "Witness provided for non-witness script";
case SCRIPT_ERR_WITNESS_PUBKEYTYPE:
return "Using non-compressed keys in segwit";
+ case SCRIPT_ERR_OP_CODESEPARATOR:
+ return "Using OP_CODESEPARATOR in non-witness script";
+ case SCRIPT_ERR_SIG_FINDANDDELETE:
+ return "Signature is found in scriptCode";
case SCRIPT_ERR_UNKNOWN_ERROR:
case SCRIPT_ERR_ERROR_COUNT:
default: break;
diff --git a/src/script/script_error.h b/src/script/script_error.h
index 3200e94707..6982a087f4 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -64,6 +64,10 @@ typedef enum ScriptError_t
SCRIPT_ERR_WITNESS_UNEXPECTED,
SCRIPT_ERR_WITNESS_PUBKEYTYPE,
+ /* Constant scriptCode */
+ SCRIPT_ERR_OP_CODESEPARATOR,
+ SCRIPT_ERR_SIG_FINDANDDELETE,
+
SCRIPT_ERR_ERROR_COUNT
} ScriptError;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 068f1e66f4..39cca90e83 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -97,6 +97,8 @@ static ScriptErrorDesc script_errors[]={
{SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"},
{SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"},
{SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"},
+ {SCRIPT_ERR_OP_CODESEPARATOR, "OP_CODESEPARATOR"},
+ {SCRIPT_ERR_SIG_FINDANDDELETE, "SIG_FINDANDDELETE"},
};
const char *FormatScriptError(ScriptError_t err)