Changeset View
Changeset View
Standalone View
Standalone View
src/script/interpreter.cpp
Show First 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | bool EvalScript(std::vector<valtype> &stack, const CScript &script, | ||||
std::vector<bool> vfExec; | std::vector<bool> vfExec; | ||||
std::vector<valtype> altstack; | std::vector<valtype> altstack; | ||||
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); | set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); | ||||
if (script.size() > MAX_SCRIPT_SIZE) { | if (script.size() > MAX_SCRIPT_SIZE) { | ||||
return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); | return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); | ||||
} | } | ||||
int nOpCount = 0; | int nOpCount = 0; | ||||
bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; | bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; | ||||
bool fEnabledOpCodesMonolith = | |||||
(flags & SCRIPT_ENABLE_OPCODES_MONOLITH) != 0; | |||||
try { | try { | ||||
while (pc < pend) { | while (pc < pend) { | ||||
bool fExec = !count(vfExec.begin(), vfExec.end(), false); | bool fExec = !count(vfExec.begin(), vfExec.end(), false); | ||||
// | // | ||||
// Read instruction | // Read instruction | ||||
// | // | ||||
if (!script.GetOp(pc, opcode, vchPushValue)) { | if (!script.GetOp(pc, opcode, vchPushValue)) { | ||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE); | return set_error(serror, SCRIPT_ERR_BAD_OPCODE); | ||||
} | } | ||||
if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) { | if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) { | ||||
return set_error(serror, SCRIPT_ERR_PUSH_SIZE); | return set_error(serror, SCRIPT_ERR_PUSH_SIZE); | ||||
} | } | ||||
// Note how OP_RESERVED does not count towards the opcode limit. | // Note how OP_RESERVED does not count towards the opcode limit. | ||||
if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) { | if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) { | ||||
return set_error(serror, SCRIPT_ERR_OP_COUNT); | return set_error(serror, SCRIPT_ERR_OP_COUNT); | ||||
} | } | ||||
if (opcode == OP_CAT || opcode == OP_SPLIT || | if (opcode == OP_CAT || opcode == OP_SPLIT || | ||||
opcode == OP_NUM2BIN || opcode == OP_BIN2NUM || | opcode == OP_NUM2BIN || opcode == OP_BIN2NUM || | ||||
opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || | opcode == OP_INVERT || opcode == OP_2MUL || opcode == OP_2DIV || | ||||
opcode == OP_XOR || opcode == OP_2MUL || opcode == OP_2DIV || | |||||
opcode == OP_MUL || opcode == OP_DIV || opcode == OP_MOD || | opcode == OP_MUL || opcode == OP_DIV || opcode == OP_MOD || | ||||
opcode == OP_LSHIFT || opcode == OP_RSHIFT) { | opcode == OP_LSHIFT || opcode == OP_RSHIFT) { | ||||
// Disabled opcodes. | // Disabled opcodes. | ||||
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | ||||
} | } | ||||
// if not monolith protocol upgrade (May 2018) then still disabled | |||||
if (!fEnabledOpCodesMonolith && | |||||
(opcode == OP_AND || opcode == OP_XOR || opcode == OP_OR)) { | |||||
// Disabled opcodes. | |||||
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
} | |||||
if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { | if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { | ||||
if (fRequireMinimal && | if (fRequireMinimal && | ||||
!CheckMinimalPush(vchPushValue, opcode)) { | !CheckMinimalPush(vchPushValue, opcode)) { | ||||
return set_error(serror, SCRIPT_ERR_MINIMALDATA); | return set_error(serror, SCRIPT_ERR_MINIMALDATA); | ||||
} | } | ||||
stack.push_back(vchPushValue); | stack.push_back(vchPushValue); | ||||
} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) | } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) | ||||
switch (opcode) { | switch (opcode) { | ||||
▲ Show 20 Lines • Show All 420 Lines • ▼ Show 20 Lines | try { | ||||
} | } | ||||
CScriptNum bn(stacktop(-1).size()); | CScriptNum bn(stacktop(-1).size()); | ||||
stack.push_back(bn.getvch()); | stack.push_back(bn.getvch()); | ||||
} break; | } break; | ||||
// | // | ||||
// Bitwise logic | // Bitwise logic | ||||
// | // | ||||
case OP_AND: | |||||
case OP_OR: | |||||
case OP_XOR: { | |||||
// (x1 x2 - out) | |||||
if (stack.size() < 2) { | |||||
return set_error( | |||||
serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | |||||
} | |||||
valtype &vch1 = stacktop(-2); | |||||
valtype &vch2 = stacktop(-1); | |||||
// throw error if inputs are not the same size | |||||
if (vch1.size() != vch2.size()) { | |||||
return set_error( | |||||
serror, SCRIPT_ERR_INVALID_BITWISE_OPERATION); | |||||
} | |||||
switch (opcode) { | |||||
case OP_AND: | |||||
for (auto it = vch1.begin(); it != vch1.end(); | |||||
++it) { | |||||
auto i = std::distance(vch1.begin(), it); | |||||
*it &= vch2[i]; | |||||
} | |||||
break; | |||||
case OP_OR: | |||||
for (auto it = vch1.begin(); it != vch1.end(); | |||||
++it) { | |||||
auto i = std::distance(vch1.begin(), it); | |||||
*it |= vch2[i]; | |||||
} | |||||
break; | |||||
case OP_XOR: | |||||
for (auto it = vch1.begin(); it != vch1.end(); | |||||
++it) { | |||||
auto i = std::distance(vch1.begin(), it); | |||||
*it ^= vch2[i]; | |||||
} | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
stack.pop_back(); | |||||
} break; | |||||
case OP_EQUAL: | case OP_EQUAL: | ||||
case OP_EQUALVERIFY: | case OP_EQUALVERIFY: | ||||
// case OP_NOTEQUAL: // use OP_NUMNOTEQUAL | // case OP_NOTEQUAL: // use OP_NUMNOTEQUAL | ||||
{ | { | ||||
// (x1 x2 - bool) | // (x1 x2 - bool) | ||||
if (stack.size() < 2) { | if (stack.size() < 2) { | ||||
return set_error( | return set_error( | ||||
serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | serror, SCRIPT_ERR_INVALID_STACK_OPERATION); | ||||
▲ Show 20 Lines • Show All 836 Lines • Show Last 20 Lines |