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