diff options
Diffstat (limited to 'src/script/script.cpp')
-rw-r--r-- | src/script/script.cpp | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/src/script/script.cpp b/src/script/script.cpp index 9f4741b1cd..0666a385d1 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -1,14 +1,11 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "script.h" +#include <script/script.h> -#include "tinyformat.h" -#include "utilstrencodings.h" - -using namespace std; +#include <util/strencodings.h> const char* GetOpName(opcodetype opcode) { @@ -143,11 +140,6 @@ const char* GetOpName(opcodetype opcode) case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; - // Note: - // The template matching params OP_SMALLINTEGER/etc are defined in opcodetype enum - // as kind of implementation hack, they are *NOT* real opcodes. If found in real - // Script, just let the default: case deal with them. - default: return "OP_UNKNOWN"; } @@ -186,18 +178,18 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const // get the last item that the scriptSig // pushes onto the stack: const_iterator pc = scriptSig.begin(); - vector<unsigned char> data; + std::vector<unsigned char> vData; while (pc < scriptSig.end()) { opcodetype opcode; - if (!scriptSig.GetOp(pc, opcode, data)) + if (!scriptSig.GetOp(pc, opcode, vData)) return 0; if (opcode > OP_16) return 0; } /// ... and return its opcount: - CScript subscript(data.begin(), data.end()); + CScript subscript(vData.begin(), vData.end()); return subscript.GetSigOpCount(true); } @@ -269,3 +261,68 @@ std::string CScriptWitness::ToString() const } return ret + ")"; } + +bool CScript::HasValidOps() const +{ + CScript::const_iterator it = begin(); + while (it < end()) { + opcodetype opcode; + std::vector<unsigned char> item; + if (!GetOp(it, opcode, item) || opcode > MAX_OPCODE || item.size() > MAX_SCRIPT_ELEMENT_SIZE) { + return false; + } + } + return true; +} + +bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) +{ + opcodeRet = OP_INVALIDOPCODE; + if (pvchRet) + pvchRet->clear(); + if (pc >= end) + return false; + + // Read instruction + if (end - pc < 1) + return false; + unsigned int opcode = *pc++; + + // Immediate operand + if (opcode <= OP_PUSHDATA4) + { + unsigned int nSize = 0; + if (opcode < OP_PUSHDATA1) + { + nSize = opcode; + } + else if (opcode == OP_PUSHDATA1) + { + if (end - pc < 1) + return false; + nSize = *pc++; + } + else if (opcode == OP_PUSHDATA2) + { + if (end - pc < 2) + return false; + nSize = ReadLE16(&pc[0]); + pc += 2; + } + else if (opcode == OP_PUSHDATA4) + { + if (end - pc < 4) + return false; + nSize = ReadLE32(&pc[0]); + pc += 4; + } + if (end - pc < 0 || (unsigned int)(end - pc) < nSize) + return false; + if (pvchRet) + pvchRet->assign(pc, pc + nSize); + pc += nSize; + } + + opcodeRet = static_cast<opcodetype>(opcode); + return true; +} |