aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/interpreter.cpp32
-rw-r--r--src/script/interpreter.h2
-rw-r--r--src/script/script.cpp52
-rw-r--r--src/script/script.h102
4 files changed, 88 insertions, 100 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 338e07e24e..e0d193fa38 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -250,6 +250,34 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
+int FindAndDelete(CScript& script, const CScript& b)
+{
+ int nFound = 0;
+ if (b.empty())
+ return nFound;
+ CScript result;
+ CScript::const_iterator pc = script.begin(), pc2 = script.begin(), end = script.end();
+ opcodetype opcode;
+ do
+ {
+ result.insert(result.end(), pc2, pc);
+ while (static_cast<size_t>(end - pc) >= b.size() && std::equal(b.begin(), b.end(), pc))
+ {
+ pc = pc + b.size();
+ ++nFound;
+ }
+ pc2 = pc;
+ }
+ while (script.GetOp(pc, opcode));
+
+ if (nFound > 0) {
+ result.insert(result.end(), pc2, end);
+ script = std::move(result);
+ }
+
+ return nFound;
+}
+
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
{
static const CScriptNum bnZero(0);
@@ -891,7 +919,7 @@ 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) {
- scriptCode.FindAndDelete(CScript(vchSig));
+ FindAndDelete(scriptCode, CScript(vchSig));
}
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
@@ -955,7 +983,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
valtype& vchSig = stacktop(-isig-k);
if (sigversion == SigVersion::BASE) {
- scriptCode.FindAndDelete(CScript(vchSig));
+ FindAndDelete(scriptCode, CScript(vchSig));
}
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 601a4a866d..50c747900a 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -189,4 +189,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
+int FindAndDelete(CScript& script, const CScript& b);
+
#endif // BITCOIN_SCRIPT_INTERPRETER_H
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 65e5405ebd..7f25d915a8 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -280,3 +280,55 @@ bool CScript::HasValidOps() const
}
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;
+}
diff --git a/src/script/script.h b/src/script/script.h
index 59ceff247c..d8b7c06013 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -385,6 +385,8 @@ private:
*/
typedef prevector<28, unsigned char> CScriptBase;
+bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet);
+
/** Serialized script, used inside transaction inputs and outputs */
class CScript : public CScriptBase
{
@@ -493,84 +495,16 @@ public:
}
- bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet)
- {
- // Wrapper so it can be called with either iterator or const_iterator
- const_iterator pc2 = pc;
- bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
- pc = begin() + (pc2 - begin());
- return fRet;
- }
-
- bool GetOp(iterator& pc, opcodetype& opcodeRet)
- {
- const_iterator pc2 = pc;
- bool fRet = GetOp2(pc2, opcodeRet, nullptr);
- pc = begin() + (pc2 - begin());
- return fRet;
- }
-
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
{
- return GetOp2(pc, opcodeRet, &vchRet);
+ return GetScriptOp(pc, end(), opcodeRet, &vchRet);
}
bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
{
- return GetOp2(pc, opcodeRet, nullptr);
+ return GetScriptOp(pc, end(), opcodeRet, nullptr);
}
- bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const
- {
- 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;
- }
/** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode)
@@ -588,34 +522,6 @@ public:
return (opcodetype)(OP_1+n-1);
}
- int FindAndDelete(const CScript& b)
- {
- int nFound = 0;
- if (b.empty())
- return nFound;
- CScript result;
- iterator pc = begin(), pc2 = begin();
- opcodetype opcode;
- do
- {
- result.insert(result.end(), pc2, pc);
- while (static_cast<size_t>(end() - pc) >= b.size() && std::equal(b.begin(), b.end(), pc))
- {
- pc = pc + b.size();
- ++nFound;
- }
- pc2 = pc;
- }
- while (GetOp(pc, opcode));
-
- if (nFound > 0) {
- result.insert(result.end(), pc2, end());
- *this = result;
- }
-
- return nFound;
- }
-
/**
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
* as 20 sigops. With pay-to-script-hash, that changed: