Index: src/script/interpreter.cpp =================================================================== --- src/script/interpreter.cpp +++ src/script/interpreter.cpp @@ -91,10 +91,10 @@ return true; case OP_2MUL: - return true; + return false; case OP_2DIV: - return true; + return false; case OP_MUL: return true; @@ -132,6 +132,7 @@ ScriptError *serror) { static const CScriptNum bnZero(0); static const CScriptNum bnOne(1); + static const CScriptNum bnTwo(2); static const valtype vchFalse(0); static const valtype vchTrue(1, 1); @@ -689,6 +690,8 @@ // case OP_1ADD: case OP_1SUB: + case OP_2MUL: + case OP_2DIV: case OP_NEGATE: case OP_ABS: case OP_NOT: @@ -706,6 +709,12 @@ case OP_1SUB: bn -= bnOne; break; + case OP_2MUL: + bn = bn * bnTwo; + break; + case OP_2DIV: + bn = bn / bnTwo; + break; case OP_NEGATE: bn = -bn; break; Index: src/script/script.h =================================================================== --- src/script/script.h +++ src/script/script.h @@ -277,6 +277,13 @@ return operator/(rhs.m_value); } + inline CScriptNum operator*(const int64_t &rhs) const { + return CScriptNum(m_value * rhs); + } + inline CScriptNum operator*(const CScriptNum &rhs) const { + return operator*(rhs.m_value); + } + inline CScriptNum operator%(const int64_t &rhs) const { return CScriptNum(m_value % rhs); } Index: src/test/data/script_tests.json =================================================================== --- src/test/data/script_tests.json +++ src/test/data/script_tests.json @@ -931,9 +931,9 @@ ["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], ["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "INVERT disabled"], ["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], -["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "2MUL disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "2MUL enabled"], ["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], -["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "2DIV disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "2DIV enabled"], ["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], ["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "MUL disabled"], ["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], @@ -1035,6 +1035,35 @@ ["-2147483648 1", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["1 -2147483648", "MOD", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], +["2MUL"], +["2", "2MUL 4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["", "2MUL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "INVALID_STACK_OPERATION", "2MUL, not enough parameters"], +["2", "2MUL 4 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "simple 2MUL test"], +["0", "2MUL 0 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "0*2=0"], +["0x0180", "2MUL 0 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "(-0)*2=0"], +["1", "2MUL 2 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "1*2=2"], +["-2", "2MUL -4 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "simple 2MUL negative test"], +["-1", "2MUL -2 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "-1*2=-2"], +["2147483647", "2MUL 4294967294 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "boundary condition"], +["2147483648", "2MUL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "UNKNOWN_ERROR", "2MUL, parameter too large"], +["-2147483647", "2MUL -4294967294 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "boundary condition"], +["-2147483648", "2MUL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "UNKNOWN_ERROR", "2MUL, parameter too large"], + +["2DIV"], +["2", "2DIV 1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["", "2DIV", "P2SH,STRICTENC,MAGNETIC_OPCODES", "INVALID_STACK_OPERATION", "2DIV, not enough parameters"], +["2", "2DIV 1 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "simple 2DIV test"], +["0", "2DIV 0 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "0/2=0"], +["0x0180", "2DIV 0 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "(-0)/2=0"], +["-8", "2DIV -4 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "simple 2DIV negative test"], +["-2", "2DIV -1 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "-2/2=-1"], +["7", "2DIV 3 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "round towards zero"], +["-7", "2DIV -3 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "round towards zero"], +["2147483647", "2DIV 1073741823 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "boundary condition"], +["2147483648", "2DIV", "P2SH,STRICTENC,MAGNETIC_OPCODES", "UNKNOWN_ERROR", "2DIV, parameter too large"], +["-2147483647", "2DIV -1073741823 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "OK", "boundary condition"], +["-2147483648", "2DIV", "P2SH,STRICTENC,MAGNETIC_OPCODES", "UNKNOWN_ERROR", "2DIV, parameter too large"], + ["EQUAL"], ["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"], ["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"], @@ -1051,14 +1080,6 @@ ["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "disabled"], -["2MUL"], -["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 2MUL", "4 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "disabled"], - -["2DIV"], -["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], -["2 2DIV", "1 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "disabled"], - ["LSHIFT"], ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC,MAGNETIC_OPCODES", "DISABLED_OPCODE", "disabled"], Index: src/test/opcode_tests.cpp =================================================================== --- src/test/opcode_tests.cpp +++ src/test/opcode_tests.cpp @@ -30,7 +30,9 @@ for (uint32_t flags : flagset) { ScriptError err = SCRIPT_ERR_OK; stacktype stack{original_stack}; - bool r = EvalScript(stack, script, flags, sigchecker, &err); + bool r = + EvalScript(stack, script, flags | SCRIPT_ENABLE_MAGNETIC_OPCODES, + sigchecker, &err); BOOST_CHECK(r); BOOST_CHECK(stack == expected); } @@ -41,7 +43,8 @@ BaseSignatureChecker sigchecker; ScriptError err = SCRIPT_ERR_OK; stacktype stack{original_stack}; - bool r = EvalScript(stack, script, flags, sigchecker, &err); + bool r = EvalScript(stack, script, flags | SCRIPT_ENABLE_MAGNETIC_OPCODES, + sigchecker, &err); BOOST_CHECK(!r); BOOST_CHECK_EQUAL(err, expected_error); } @@ -71,6 +74,11 @@ CheckTestResultForAllFlags({a, b}, CScript() << op, {expected}); } +static void CheckUnaryOp(const valtype &a, opcodetype op, + const valtype &expected) { + CheckTestResultForAllFlags({a}, CScript() << op, {expected}); +} + static valtype NegativeValtype(const valtype &v) { valtype r(v); if (r.size() > 0) { @@ -769,4 +777,16 @@ {0xbb, 0xf0, 0x5d, 0x03}); } +BOOST_AUTO_TEST_CASE(mul2_div2_test) { + CheckUnaryOp({}, OP_2MUL, {}); + CheckUnaryOp({0x01}, OP_2MUL, {0x02}); + CheckUnaryOp({0x02}, OP_2MUL, {0x04}); + + CheckUnaryOp({}, OP_2DIV, {}); + CheckUnaryOp({0x01}, OP_2DIV, {}); + CheckUnaryOp({0x02}, OP_2DIV, {0x01}); + CheckUnaryOp({0x03}, OP_2DIV, {0x01}); + CheckUnaryOp({0x04}, OP_2DIV, {0x02}); +} + BOOST_AUTO_TEST_SUITE_END()