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_INVERT || opcode == OP_2MUL || opcode == OP_2DIV || | ||||
| opcode == OP_NUM2BIN || opcode == OP_BIN2NUM || | opcode == OP_MUL || opcode == OP_LSHIFT || opcode == OP_RSHIFT) { | ||||
| opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || | |||||
| opcode == OP_XOR || opcode == OP_2MUL || opcode == OP_2DIV || | |||||
| opcode == OP_MUL || opcode == OP_DIV || opcode == OP_MOD || | |||||
| 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 (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); | ||||
| ▲ Show 20 Lines • Show All 424 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: { | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcodes. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| } 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 62 Lines • ▼ Show 20 Lines | try { | ||||
| break; | break; | ||||
| } | } | ||||
| popstack(stack); | popstack(stack); | ||||
| stack.push_back(bn.getvch()); | stack.push_back(bn.getvch()); | ||||
| } break; | } break; | ||||
| case OP_ADD: | case OP_ADD: | ||||
| case OP_SUB: | case OP_SUB: | ||||
| case OP_DIV: | |||||
| case OP_MOD: | |||||
| case OP_BOOLAND: | case OP_BOOLAND: | ||||
| case OP_BOOLOR: | case OP_BOOLOR: | ||||
| case OP_NUMEQUAL: | case OP_NUMEQUAL: | ||||
| case OP_NUMEQUALVERIFY: | case OP_NUMEQUALVERIFY: | ||||
| case OP_NUMNOTEQUAL: | case OP_NUMNOTEQUAL: | ||||
| case OP_LESSTHAN: | case OP_LESSTHAN: | ||||
| case OP_GREATERTHAN: | case OP_GREATERTHAN: | ||||
| case OP_LESSTHANOREQUAL: | case OP_LESSTHANOREQUAL: | ||||
| Show All 12 Lines | try { | ||||
| case OP_ADD: | case OP_ADD: | ||||
| bn = bn1 + bn2; | bn = bn1 + bn2; | ||||
| break; | break; | ||||
| case OP_SUB: | case OP_SUB: | ||||
| bn = bn1 - bn2; | bn = bn1 - bn2; | ||||
| break; | break; | ||||
| case OP_DIV: | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcode. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| break; | |||||
| case OP_MOD: | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcode. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| break; | |||||
| case OP_BOOLAND: | case OP_BOOLAND: | ||||
| bn = (bn1 != bnZero && bn2 != bnZero); | bn = (bn1 != bnZero && bn2 != bnZero); | ||||
| break; | break; | ||||
| case OP_BOOLOR: | case OP_BOOLOR: | ||||
| bn = (bn1 != bnZero || bn2 != bnZero); | bn = (bn1 != bnZero || bn2 != bnZero); | ||||
| break; | break; | ||||
| case OP_NUMEQUAL: | case OP_NUMEQUAL: | ||||
| bn = (bn1 == bn2); | bn = (bn1 == bn2); | ||||
| ▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | try { | ||||
| popstack(stack); | popstack(stack); | ||||
| } else { | } else { | ||||
| return set_error( | return set_error( | ||||
| serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); | serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); | ||||
| } | } | ||||
| } | } | ||||
| } break; | } break; | ||||
| // | |||||
| // Byte string operations | |||||
| // | |||||
| case OP_CAT: { | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcodes. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| } break; | |||||
| case OP_SPLIT: { | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcodes. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| } break; | |||||
| // | |||||
| // Conversion operations | |||||
| // | |||||
| case OP_BIN2NUM: { | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcodes. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| } break; | |||||
| case OP_NUM2BIN: { | |||||
| if (!fEnabledOpCodesMonolith) { | |||||
| // Disabled opcodes. | |||||
| return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); | |||||
| } | |||||
| } break; | |||||
| default: | default: | ||||
| return set_error(serror, SCRIPT_ERR_BAD_OPCODE); | return set_error(serror, SCRIPT_ERR_BAD_OPCODE); | ||||
| } | } | ||||
| // Size limits | // Size limits | ||||
| if (stack.size() + altstack.size() > 1000) { | if (stack.size() + altstack.size() > 1000) { | ||||
| return set_error(serror, SCRIPT_ERR_STACK_SIZE); | return set_error(serror, SCRIPT_ERR_STACK_SIZE); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 437 Lines • Show Last 20 Lines | |||||