|
|
|
@ -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;
|
|
|
|
|
|
|
|
|
|