aboutsummaryrefslogtreecommitdiff
path: root/src/script/interpreter.cpp
diff options
context:
space:
mode:
authorAnthony Towns <aj@erisian.com.au>2019-09-18 15:49:29 +1000
committerPieter Wuille <pieter.wuille@gmail.com>2019-11-07 09:12:26 -0800
commitd0e8f4d5d8ddaccb37f98b7989fb944081e41ab8 (patch)
tree0d639dc6cdd298e6bd7333f23353fb5805bbb5f7 /src/script/interpreter.cpp
parent89fb241c54fc85befacfa3703d8e21bf3b8a76eb (diff)
[refactor] interpreter: define interface for vfExec
Includes comments added by Pieter Wuille.
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r--src/script/interpreter.cpp30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 20fae2eebf..7a34c9c48d 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -278,6 +278,30 @@ int FindAndDelete(CScript& script, const CScript& b)
return nFound;
}
+namespace {
+/** A data type to abstract out the condition stack during script execution.
+ *
+ * Conceptually it acts like a vector of booleans, one for each level of nested
+ * IF/THEN/ELSE, indicating whether we're in the active or inactive branch of
+ * each.
+ *
+ * The elements on the stack cannot be observed individually; we only need to
+ * expose whether the stack is empty and whether or not any false values are
+ * present at all. To implement OP_ELSE, a toggle_top modifier is added, which
+ * flips the last value without returning it.
+ */
+class ConditionStack {
+private:
+ std::vector<bool> m_flags;
+public:
+ bool empty() { return m_flags.empty(); }
+ bool all_true() { return !std::count(m_flags.begin(), m_flags.end(), false); }
+ void push_back(bool f) { m_flags.push_back(f); }
+ void pop_back() { m_flags.pop_back(); }
+ void toggle_top() { m_flags.back() = !m_flags.back(); }
+};
+}
+
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);
@@ -293,7 +317,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
CScript::const_iterator pbegincodehash = script.begin();
opcodetype opcode;
valtype vchPushValue;
- std::vector<bool> vfExec;
+ ConditionStack vfExec;
std::vector<valtype> altstack;
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if (script.size() > MAX_SCRIPT_SIZE)
@@ -305,7 +329,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
while (pc < pend)
{
- bool fExec = !count(vfExec.begin(), vfExec.end(), false);
+ bool fExec = vfExec.all_true();
//
// Read instruction
@@ -494,7 +518,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
if (vfExec.empty())
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- vfExec.back() = !vfExec.back();
+ vfExec.toggle_top();
}
break;