diff --git a/src/Makefile.test.include b/src/Makefile.test.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -42,6 +42,7 @@ test/bswap_tests.cpp \ test/cashaddr_tests.cpp \ test/cashaddrenc_tests.cpp \ + test/checkdatasig_tests.cpp \ test/checkpoints_tests.cpp \ test/coins_tests.cpp \ test/compress_tests.cpp \ diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1044,6 +1044,10 @@ } } break; + case OP_CHECKDATASIG: + case OP_CHECKDATASIGVERIFY: + return set_error(serror, SCRIPT_ERR_BAD_OPCODE); + // // Byte string operations // diff --git a/src/script/script.h b/src/script/script.h --- a/src/script/script.h +++ b/src/script/script.h @@ -175,6 +175,10 @@ OP_NOP9 = 0xb8, OP_NOP10 = 0xb9, + // More crypto + OP_CHECKDATASIG = 0xba, + OP_CHECKDATASIGVERIFY = 0xbb, + // The first op_code value after all defined opcodes FIRST_UNDEFINED_OP_VALUE, diff --git a/src/script/script.cpp b/src/script/script.cpp --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -227,6 +227,10 @@ return "OP_CHECKMULTISIG"; case OP_CHECKMULTISIGVERIFY: return "OP_CHECKMULTISIGVERIFY"; + case OP_CHECKDATASIG: + return "OP_CHECKDATASIG"; + case OP_CHECKDATASIGVERIFY: + return "OP_CHECKDATASIGVERIFY"; // expansion case OP_NOP1: diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -58,6 +58,7 @@ bswap_tests.cpp cashaddr_tests.cpp cashaddrenc_tests.cpp + checkdatasig_tests.cpp checkpoints_tests.cpp coins_tests.cpp compress_tests.cpp diff --git a/src/test/checkdatasig_tests.cpp b/src/test/checkdatasig_tests.cpp new file mode 100644 --- /dev/null +++ b/src/test/checkdatasig_tests.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "test/test_bitcoin.h" + +#include "policy/policy.h" +#include "script/interpreter.h" + +#include + +#include + +typedef std::vector valtype; +typedef std::vector stacktype; + +BOOST_FIXTURE_TEST_SUITE(checkdatasig_tests, BasicTestingSetup) + +std::array flagset{ + {0, STANDARD_SCRIPT_VERIFY_FLAGS, MANDATORY_SCRIPT_VERIFY_FLAGS}}; + +/** + * General utility functions to check for script passing/failing. + */ +static void CheckTestResultForAllFlags(const stacktype &original_stack, + const CScript &script, + const stacktype &expected) { + BaseSignatureChecker sigchecker; + + for (uint32_t flags : flagset) { + // Make sure that opcodes are disabled. + ScriptError err = SCRIPT_ERR_OK; + stacktype stack{original_stack}; + bool r = EvalScript(stack, script, flags, sigchecker, &err); + BOOST_CHECK(!r); + BOOST_CHECK_EQUAL(err, SCRIPT_ERR_BAD_OPCODE); + } +} + +BOOST_AUTO_TEST_CASE(checkdatasig_test) { + CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIG, {}); + CheckTestResultForAllFlags({}, CScript() << OP_CHECKDATASIGVERIFY, {}); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -240,9 +240,9 @@ ["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discouraged NOPs are allowed if not executed"], -["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], -["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], -["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF CHECKDATASIG ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF CHECKDATASIGVERIFY ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], +["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], ["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], ["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"], @@ -1066,9 +1066,9 @@ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], ["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], -["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], -["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF CHECKDATASIG ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF CHECKDATASIGVERIFY ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], +["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes >= FIRST_UNDEFINED_OP_VALUE invalid if executed"], ["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], ["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"], @@ -1189,7 +1189,7 @@ ["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"], ["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"], ["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"], -["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == FIRST_UNDEFINED_OP_VALUE"], +["1","0xbc", "P2SH,STRICTENC", "BAD_OPCODE", "0xbc == FIRST_UNDEFINED_OP_VALUE"], ["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], ["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"], diff --git a/src/test/monolith_opcodes.cpp b/src/test/monolith_opcodes.cpp --- a/src/test/monolith_opcodes.cpp +++ b/src/test/monolith_opcodes.cpp @@ -14,11 +14,11 @@ typedef std::vector valtype; typedef std::vector stacktype; +BOOST_FIXTURE_TEST_SUITE(monolith_opcodes_tests, BasicTestingSetup) + std::array flagset{ {0, STANDARD_SCRIPT_VERIFY_FLAGS, MANDATORY_SCRIPT_VERIFY_FLAGS}}; -BOOST_FIXTURE_TEST_SUITE(monolith_opcodes_tests, BasicTestingSetup) - /** * General utility functions to check for script passing/failing. */ diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -228,6 +228,8 @@ OP_CHECKSIGVERIFY = CScriptOp(0xad) OP_CHECKMULTISIG = CScriptOp(0xae) OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf) +OP_CHECKDATASIG = CScriptOp(0xba) +OP_CHECKDATASIGVERIFY = CScriptOp(0xbb) # expansion OP_NOP1 = CScriptOp(0xb0) @@ -356,6 +358,8 @@ OP_CHECKSIGVERIFY, OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, + OP_CHECKDATASIG, + OP_CHECKDATASIGVERIFY, OP_NOP1, OP_CHECKLOCKTIMEVERIFY, @@ -476,6 +480,8 @@ OP_CHECKSIGVERIFY: 'OP_CHECKSIGVERIFY', OP_CHECKMULTISIG: 'OP_CHECKMULTISIG', OP_CHECKMULTISIGVERIFY: 'OP_CHECKMULTISIGVERIFY', + OP_CHECKDATASIG: 'OP_CHECKDATASIG', + OP_CHECKDATASIGVERIFY: 'OP_CHECKDATASIGVERIFY', OP_NOP1: 'OP_NOP1', OP_CHECKLOCKTIMEVERIFY: 'OP_CHECKLOCKTIMEVERIFY', OP_CHECKSEQUENCEVERIFY: 'OP_CHECKSEQUENCEVERIFY', @@ -595,6 +601,8 @@ 'OP_CHECKSIGVERIFY': OP_CHECKSIGVERIFY, 'OP_CHECKMULTISIG': OP_CHECKMULTISIG, 'OP_CHECKMULTISIGVERIFY': OP_CHECKMULTISIGVERIFY, + 'OP_CHECKDATASIG': OP_CHECKDATASIG, + 'OP_CHECKDATASIGVERIFY': OP_CHECKDATASIGVERIFY, 'OP_NOP1': OP_NOP1, 'OP_CHECKLOCKTIMEVERIFY': OP_CHECKLOCKTIMEVERIFY, 'OP_CHECKSEQUENCEVERIFY': OP_CHECKSEQUENCEVERIFY,