diff options
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r-- | src/script/interpreter.cpp | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index cd73b88210..3625972ebf 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -5,7 +5,7 @@ #include "interpreter.h" -#include "core.h" +#include "core/transaction.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" @@ -157,6 +157,29 @@ bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) { return true; } +bool static CheckMinimalPush(const valtype& data, opcodetype opcode) { + if (data.size() == 0) { + // Could have used OP_0. + return opcode == OP_0; + } else if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) { + // Could have used OP_1 .. OP_16. + return opcode == OP_1 + (data[0] - 1); + } else if (data.size() == 1 && data[0] == 0x81) { + // Could have used OP_1NEGATE. + return opcode == OP_1NEGATE; + } else if (data.size() <= 75) { + // Could have used a direct push (opcode indicating number of bytes pushed + those bytes). + return opcode == data.size(); + } else if (data.size() <= 255) { + // Could have used OP_PUSHDATA. + return opcode == OP_PUSHDATA1; + } else if (data.size() <= 65535) { + // Could have used OP_PUSHDATA2. + return opcode == OP_PUSHDATA2; + } + return true; +} + bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker) { CScript::const_iterator pc = script.begin(); @@ -169,6 +192,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if (script.size() > 10000) return false; int nOpCount = 0; + bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; try { @@ -205,9 +229,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un opcode == OP_RSHIFT) return false; // Disabled opcodes. - if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) + if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { + if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) { + return false; + } stack.push_back(vchPushValue); - else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) + } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // @@ -234,6 +261,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // ( -- value) CScriptNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); + // The result of these opcodes should always be the minimal way to push the data + // they push, so no need for a CheckMinimalPush here. } break; @@ -458,7 +487,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return false; - int n = CScriptNum(stacktop(-1)).getint(); + int n = CScriptNum(stacktop(-1), fRequireMinimal).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) return false; @@ -557,7 +586,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (in -- out) if (stack.size() < 1) return false; - CScriptNum bn(stacktop(-1)); + CScriptNum bn(stacktop(-1), fRequireMinimal); switch (opcode) { case OP_1ADD: bn += bnOne; break; @@ -590,8 +619,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (x1 x2 -- out) if (stack.size() < 2) return false; - CScriptNum bn1(stacktop(-2)); - CScriptNum bn2(stacktop(-1)); + CScriptNum bn1(stacktop(-2), fRequireMinimal); + CScriptNum bn2(stacktop(-1), fRequireMinimal); CScriptNum bn(0); switch (opcode) { @@ -635,9 +664,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (x min max -- out) if (stack.size() < 3) return false; - CScriptNum bn1(stacktop(-3)); - CScriptNum bn2(stacktop(-2)); - CScriptNum bn3(stacktop(-1)); + CScriptNum bn1(stacktop(-3), fRequireMinimal); + CScriptNum bn2(stacktop(-2), fRequireMinimal); + CScriptNum bn3(stacktop(-1), fRequireMinimal); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); @@ -727,7 +756,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if ((int)stack.size() < i) return false; - int nKeysCount = CScriptNum(stacktop(-i)).getint(); + int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nKeysCount < 0 || nKeysCount > 20) return false; nOpCount += nKeysCount; @@ -738,7 +767,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if ((int)stack.size() < i) return false; - int nSigsCount = CScriptNum(stacktop(-i)).getint(); + int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return false; int isig = ++i; @@ -980,6 +1009,10 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker) { + if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { + return false; + } + vector<vector<unsigned char> > stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker)) return false; |