Index: src/script/interpreter.h =================================================================== --- src/script/interpreter.h +++ src/script/interpreter.h @@ -107,6 +107,11 @@ // Do we accept signature using SIGHASH_FORKID // SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16), + + + // Enable new opcodes activated from 15 May 2018 HF + // + SCRIPT_ENABLE_OPCODES0 = (1U << 17), }; bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, Index: src/script/interpreter.cpp =================================================================== --- src/script/interpreter.cpp +++ src/script/interpreter.cpp @@ -312,6 +312,7 @@ } int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; + bool fEnabledOpCodes0 = (flags & SCRIPT_ENABLE_OPCODES0) != 0; try { while (pc < pend) { @@ -332,10 +333,24 @@ return set_error(serror, SCRIPT_ERR_OP_COUNT); } - if (opcode == OP_INVERT || opcode == OP_2MUL || opcode == OP_2DIV || - opcode == OP_MUL || opcode == OP_LSHIFT || opcode == OP_RSHIFT) { - // Disabled opcodes. - return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); + // May 15 2018 HF activates AND, OR, XOR, DIV, MOD, CAT, and SPLIT + if (fEnabledOpCodes0) { + if (opcode == OP_INVERT || opcode == OP_2MUL || opcode == OP_2DIV || + opcode == OP_MUL || opcode == OP_LSHIFT || opcode == OP_RSHIFT) { + // Disabled opcodes. + return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); + } + } + else { + if (opcode == OP_CAT || opcode == OP_SPLIT || opcode == OP_BIN2NUM || + opcode == OP_NUM2BIN || 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. + return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); + } } if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { Index: src/test/op_code.cpp =================================================================== --- src/test/op_code.cpp +++ src/test/op_code.cpp @@ -84,7 +84,7 @@ BOOST_CHECK_EQUAL(stack==expected, true); } - /// OP_AND, OP_OR + /// OP_AND, OP_OR, OP_XOR void test_bitwiseop(const CScript& script, uint32_t flags) { //number of inputs @@ -170,7 +170,7 @@ } - /// OP_XOR tests + /// OP_XOR void test_xor(uint32_t flags) { CScript script; @@ -598,6 +598,42 @@ test_num2bin_bin2num(1,flags); //1 byte num2bin output } + + void test_disabled_opcode(opcodetype opcode, uint32_t flags) { + CScript script; + script << opcode; + test(script,stack_t{{}},flags,SCRIPT_ERR_DISABLED_OPCODE); + } + + void test_disabled_opcodes_before_may18_fork(uint32_t flags) { + assert((flags&SCRIPT_ENABLE_OPCODES0)==0); + test_disabled_opcode(OP_CAT,flags); + test_disabled_opcode(OP_SPLIT,flags); + test_disabled_opcode(OP_AND,flags); + test_disabled_opcode(OP_OR,flags); + test_disabled_opcode(OP_XOR,flags); + test_disabled_opcode(OP_DIV,flags); + test_disabled_opcode(OP_MOD,flags); + test_disabled_opcode(OP_NUM2BIN,flags); + test_disabled_opcode(OP_BIN2NUM,flags); + test_disabled_opcode(OP_INVERT,flags); + test_disabled_opcode(OP_2MUL,flags); + test_disabled_opcode(OP_2DIV,flags); + test_disabled_opcode(OP_MUL,flags); + test_disabled_opcode(OP_LSHIFT,flags); + test_disabled_opcode(OP_RSHIFT,flags); + } + + void test_disabled_opcodes_after_may18_fork(uint32_t flags) { + assert((flags&SCRIPT_ENABLE_OPCODES0)!=0); + test_disabled_opcode(OP_INVERT,flags); + test_disabled_opcode(OP_2MUL,flags); + test_disabled_opcode(OP_2DIV,flags); + test_disabled_opcode(OP_MUL,flags); + test_disabled_opcode(OP_LSHIFT,flags); + test_disabled_opcode(OP_RSHIFT,flags); + } + } /// Entry points @@ -605,88 +641,100 @@ BOOST_AUTO_TEST_SUITE(op_code) BOOST_AUTO_TEST_CASE(op_and) { - test_and(0); - test_and(STANDARD_SCRIPT_VERIFY_FLAGS); - test_and(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_and(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_and(SCRIPT_ENABLE_OPCODES0); + test_and(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_and(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_and(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_or) { - test_or(0); - test_or(STANDARD_SCRIPT_VERIFY_FLAGS); - test_or(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_or(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_or(SCRIPT_ENABLE_OPCODES0); + test_or(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_or(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_or(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_xor) { - test_xor(0); - test_xor(STANDARD_SCRIPT_VERIFY_FLAGS); - test_xor(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_xor(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_xor(SCRIPT_ENABLE_OPCODES0); + test_xor(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_xor(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_xor(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_div) { - test_div(0); - test_div(STANDARD_SCRIPT_VERIFY_FLAGS); - test_div(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_div(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_div(SCRIPT_ENABLE_OPCODES0); + test_div(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_div(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_div(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_mod) { - test_mod(0); - test_mod(STANDARD_SCRIPT_VERIFY_FLAGS); - test_mod(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_mod(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_mod(SCRIPT_ENABLE_OPCODES0); + test_mod(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_mod(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_mod(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_cat) { - test_cat(0); - test_cat(STANDARD_SCRIPT_VERIFY_FLAGS); - test_cat(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_cat(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_cat(SCRIPT_ENABLE_OPCODES0); + test_cat(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_cat(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_cat(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_split) { - test_split(0); - test_split(STANDARD_SCRIPT_VERIFY_FLAGS); - test_split(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_split(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_split(SCRIPT_ENABLE_OPCODES0); + test_split(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_split(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_split(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(cat_split) { - test_cat_split(0); - test_cat_split(STANDARD_SCRIPT_VERIFY_FLAGS); - test_cat_split(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_cat_split(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_cat_split(SCRIPT_ENABLE_OPCODES0); + test_cat_split(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_cat_split(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_cat_split(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_bin2num) { - test_bin2num(0); - test_bin2num(STANDARD_SCRIPT_VERIFY_FLAGS); - test_bin2num(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_bin2num(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_bin2num(SCRIPT_ENABLE_OPCODES0); + test_bin2num(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_bin2num(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_bin2num(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(op_num2bin) { - test_num2bin(0); - test_num2bin(STANDARD_SCRIPT_VERIFY_FLAGS); - test_num2bin(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_num2bin(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_num2bin(SCRIPT_ENABLE_OPCODES0); + test_num2bin(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_num2bin(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_num2bin(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(bin2num_num2bin) { - test_bin2num_num2bin(0); - test_bin2num_num2bin(STANDARD_SCRIPT_VERIFY_FLAGS); - test_bin2num_num2bin(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_bin2num_num2bin(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_bin2num_num2bin(SCRIPT_ENABLE_OPCODES0); + test_bin2num_num2bin(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_bin2num_num2bin(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_bin2num_num2bin(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_CASE(num2bin_bin2num) { - test_num2bin_bin2num(0); - test_num2bin_bin2num(STANDARD_SCRIPT_VERIFY_FLAGS); - test_num2bin_bin2num(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); - test_num2bin_bin2num(STANDARD_LOCKTIME_VERIFY_FLAGS); + test_num2bin_bin2num(SCRIPT_ENABLE_OPCODES0); + test_num2bin_bin2num(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0 | SCRIPT_ENABLE_OPCODES0); + test_num2bin_bin2num(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_num2bin_bin2num(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); +} + +BOOST_AUTO_TEST_CASE(disabled_opcodes) { + test_disabled_opcodes_before_may18_fork(0); + test_disabled_opcodes_before_may18_fork(STANDARD_SCRIPT_VERIFY_FLAGS); + test_disabled_opcodes_before_may18_fork(STANDARD_NOT_MANDATORY_VERIFY_FLAGS); + test_disabled_opcodes_before_may18_fork(STANDARD_LOCKTIME_VERIFY_FLAGS); + + test_disabled_opcodes_after_may18_fork(0|SCRIPT_ENABLE_OPCODES0); + test_disabled_opcodes_after_may18_fork(STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_disabled_opcodes_after_may18_fork(STANDARD_NOT_MANDATORY_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); + test_disabled_opcodes_after_may18_fork(STANDARD_LOCKTIME_VERIFY_FLAGS | SCRIPT_ENABLE_OPCODES0); } BOOST_AUTO_TEST_SUITE_END() Index: src/validation.cpp =================================================================== --- src/validation.cpp +++ src/validation.cpp @@ -1892,6 +1892,11 @@ flags |= SCRIPT_VERIFY_NULLFAIL; } + if (IsMonolithEnabled(config, pindex->pprev)) { + // When the May 15, 2018 HF is enabled, activate new opcodes. + flags |= SCRIPT_ENABLE_OPCODES0; + } + return flags; }