|
|
|
@ -16,6 +16,7 @@ static const CBigNum bnZero(0);
|
|
|
|
|
static const CBigNum bnOne(1);
|
|
|
|
|
static const CBigNum bnFalse(0);
|
|
|
|
|
static const CBigNum bnTrue(1);
|
|
|
|
|
static const size_t nMaxNumSize = 258;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CastToBool(const valtype& vch)
|
|
|
|
@ -53,8 +54,12 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
vector<valtype> altstack;
|
|
|
|
|
if (pvStackRet)
|
|
|
|
|
pvStackRet->clear();
|
|
|
|
|
if (script.size() > 20000)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
while (pc < pend)
|
|
|
|
|
{
|
|
|
|
|
bool fExec = !count(vfExec.begin(), vfExec.end(), false);
|
|
|
|
@ -66,6 +71,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
valtype vchPushValue;
|
|
|
|
|
if (!script.GetOp(pc, opcode, vchPushValue))
|
|
|
|
|
return false;
|
|
|
|
|
if (vchPushValue.size() > 5000)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (fExec && opcode <= OP_PUSHDATA4)
|
|
|
|
|
stack.push_back(vchPushValue);
|
|
|
|
@ -104,19 +111,20 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
// Control
|
|
|
|
|
//
|
|
|
|
|
case OP_NOP:
|
|
|
|
|
case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5:
|
|
|
|
|
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_VER:
|
|
|
|
|
case OP_VERIF:
|
|
|
|
|
case OP_VERNOTIF:
|
|
|
|
|
{
|
|
|
|
|
CBigNum bn(VERSION);
|
|
|
|
|
stack.push_back(bn.getvch());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_IF:
|
|
|
|
|
case OP_NOTIF:
|
|
|
|
|
case OP_VERIF:
|
|
|
|
|
case OP_VERNOTIF:
|
|
|
|
|
{
|
|
|
|
|
// <expression> if [statements] [else [statements]] endif
|
|
|
|
|
bool fValue = false;
|
|
|
|
@ -125,11 +133,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (stack.size() < 1)
|
|
|
|
|
return false;
|
|
|
|
|
valtype& vch = stacktop(-1);
|
|
|
|
|
if (opcode == OP_VERIF || opcode == OP_VERNOTIF)
|
|
|
|
|
fValue = (CBigNum(VERSION) >= CBigNum(vch));
|
|
|
|
|
else
|
|
|
|
|
fValue = CastToBool(vch);
|
|
|
|
|
if (opcode == OP_NOTIF || opcode == OP_VERNOTIF)
|
|
|
|
|
if (opcode == OP_NOTIF)
|
|
|
|
|
fValue = !fValue;
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
}
|
|
|
|
@ -163,13 +168,13 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (fValue)
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_RETURN:
|
|
|
|
|
{
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -383,6 +388,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
valtype& vch2 = stacktop(-1);
|
|
|
|
|
vch1.insert(vch1.end(), vch2.begin(), vch2.end());
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
if (stacktop(-1).size() > 5000)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -504,7 +511,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (fEqual)
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -525,6 +532,8 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
// (in -- out)
|
|
|
|
|
if (stack.size() < 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (stacktop(-1).size() > nMaxNumSize)
|
|
|
|
|
return false;
|
|
|
|
|
CBigNum bn(stacktop(-1));
|
|
|
|
|
switch (opcode)
|
|
|
|
|
{
|
|
|
|
@ -564,6 +573,9 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
// (x1 x2 -- out)
|
|
|
|
|
if (stack.size() < 2)
|
|
|
|
|
return false;
|
|
|
|
|
if (stacktop(-2).size() > nMaxNumSize ||
|
|
|
|
|
stacktop(-1).size() > nMaxNumSize)
|
|
|
|
|
return false;
|
|
|
|
|
CBigNum bn1(stacktop(-2));
|
|
|
|
|
CBigNum bn2(stacktop(-1));
|
|
|
|
|
CBigNum bn;
|
|
|
|
@ -593,13 +605,13 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_LSHIFT:
|
|
|
|
|
if (bn2 < bnZero)
|
|
|
|
|
if (bn2 < bnZero || bn2 > CBigNum(2048))
|
|
|
|
|
return false;
|
|
|
|
|
bn = bn1 << bn2.getulong();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_RSHIFT:
|
|
|
|
|
if (bn2 < bnZero)
|
|
|
|
|
if (bn2 < bnZero || bn2 > CBigNum(2048))
|
|
|
|
|
return false;
|
|
|
|
|
bn = bn1 >> bn2.getulong();
|
|
|
|
|
break;
|
|
|
|
@ -625,7 +637,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (CastToBool(stacktop(-1)))
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -635,6 +647,10 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
// (x min max -- out)
|
|
|
|
|
if (stack.size() < 3)
|
|
|
|
|
return false;
|
|
|
|
|
if (stacktop(-3).size() > nMaxNumSize ||
|
|
|
|
|
stacktop(-2).size() > nMaxNumSize ||
|
|
|
|
|
stacktop(-1).size() > nMaxNumSize)
|
|
|
|
|
return false;
|
|
|
|
|
CBigNum bn1(stacktop(-3));
|
|
|
|
|
CBigNum bn2(stacktop(-2));
|
|
|
|
|
CBigNum bn3(stacktop(-1));
|
|
|
|
@ -719,7 +735,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (fSuccess)
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -789,7 +805,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
if (fSuccess)
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else
|
|
|
|
|
pc = pend;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -797,8 +813,20 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Size limits
|
|
|
|
|
if (stack.size() + altstack.size() > 1000)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!vfExec.empty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (pvStackRet)
|
|
|
|
|
*pvStackRet = stack;
|
|
|
|
|