@@ -278,6 +278,30 @@ int FindAndDelete(CScript& script, const CScript& b)
278
278
return nFound;
279
279
}
280
280
281
+ namespace {
282
+ /* * A data type to abstract out the condition stack during script execution.
283
+ *
284
+ * Conceptually it acts like a vector of booleans, one for each level of nested
285
+ * IF/THEN/ELSE, indicating whether we're in the active or inactive branch of
286
+ * each.
287
+ *
288
+ * The elements on the stack cannot be observed individually; we only need to
289
+ * expose whether the stack is empty and whether or not any false values are
290
+ * present at all. To implement OP_ELSE, a toggle_top modifier is added, which
291
+ * flips the last value without returning it.
292
+ */
293
+ class ConditionStack {
294
+ private:
295
+ std::vector<bool > m_flags;
296
+ public:
297
+ bool empty () { return m_flags.empty (); }
298
+ bool all_true () { return !std::count (m_flags.begin (), m_flags.end (), false ); }
299
+ void push_back (bool f) { m_flags.push_back (f); }
300
+ void pop_back () { m_flags.pop_back (); }
301
+ void toggle_top () { m_flags.back () = !m_flags.back (); }
302
+ };
303
+ }
304
+
281
305
bool EvalScript (std::vector<std::vector<unsigned char > >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
282
306
{
283
307
static const CScriptNum bnZero (0 );
@@ -293,7 +317,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
293
317
CScript::const_iterator pbegincodehash = script.begin ();
294
318
opcodetype opcode;
295
319
valtype vchPushValue;
296
- std::vector< bool > vfExec;
320
+ ConditionStack vfExec;
297
321
std::vector<valtype> altstack;
298
322
set_error (serror, SCRIPT_ERR_UNKNOWN_ERROR);
299
323
if (script.size () > MAX_SCRIPT_SIZE)
@@ -305,7 +329,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
305
329
{
306
330
while (pc < pend)
307
331
{
308
- bool fExec = ! count ( vfExec.begin (), vfExec. end (), false );
332
+ bool fExec = vfExec.all_true ( );
309
333
310
334
//
311
335
// Read instruction
@@ -494,7 +518,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
494
518
{
495
519
if (vfExec.empty ())
496
520
return set_error (serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
497
- vfExec.back () = !vfExec. back ();
521
+ vfExec.toggle_top ();
498
522
}
499
523
break ;
500
524
0 commit comments