diff --git a/src/Makefile.test.include b/src/Makefile.test.include --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -58,6 +58,7 @@ test/mempool_tests.cpp \ test/merkle_tests.cpp \ test/miner_tests.cpp \ + test/monolith_opcodes_string.cpp \ test/multisig_tests.cpp \ test/net_tests.cpp \ test/netbase_tests.cpp \ diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -298,10 +298,10 @@ if (fEnabledOpCodesMonolith) { switch (opcode) { case OP_CAT: - return true; + return false; case OP_SPLIT: - return true; + return false; case OP_BIN2NUM: return true; @@ -1238,6 +1238,65 @@ } } break; + // + // Byte string operations + // + case OP_CAT: { + // (x1 x2 -- out) + if (stack.size() < 2) { + return set_error( + serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + } + valtype &vch1 = stacktop(-2); + valtype &vch2 = stacktop(-1); + if (vch1.size() + vch2.size() > + MAX_SCRIPT_ELEMENT_SIZE) { + return set_error(serror, SCRIPT_ERR_PUSH_SIZE); + } + vch1.insert(vch1.end(), vch2.begin(), vch2.end()); + popstack(stack); + } break; + + case OP_SPLIT: { + // (in position -- x1 x2) + if (stack.size() < 2) { + return set_error( + serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + } + valtype vch = stacktop(-2); + int64_t nPosition = + CScriptNum(stacktop(-1), fRequireMinimal).getint(); + + // if nPosition is less than 0 or is larger than the + // input then throw error + if (nPosition < 0 || + static_cast(nPosition) > vch.size()) { + return set_error(serror, + SCRIPT_ERR_INVALID_SPLIT_RANGE); + } + + popstack(stack); + popstack(stack); + + // initialize outputs + if (nPosition == 0) { + stack.push_back(valtype()); + stack.push_back(vch); + } else if (static_cast(nPosition) == + vch.size()) { + stack.push_back(vch); + stack.push_back(valtype()); + } else { + valtype vchOut1, vchOut2; + vchOut1.insert(vchOut1.end(), vch.begin(), + vch.begin() + nPosition); + vchOut2.insert(vchOut2.end(), + vch.begin() + nPosition, vch.end()); + stack.emplace_back(move(vchOut1)); + stack.emplace_back(move(vchOut2)); + } + } break; + default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } diff --git a/src/script/script_error.h b/src/script/script_error.h --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -20,6 +20,9 @@ SCRIPT_ERR_SIG_COUNT, SCRIPT_ERR_PUBKEY_COUNT, + /* Operands checks */ + SCRIPT_ERR_INVALID_SPLIT_RANGE, + /* Failed verify operations */ SCRIPT_ERR_VERIFY, SCRIPT_ERR_EQUALVERIFY, diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -34,6 +34,8 @@ return "Signature count negative or greater than pubkey count"; case SCRIPT_ERR_PUBKEY_COUNT: return "Pubkey count negative or limit exceeded"; + case SCRIPT_ERR_INVALID_SPLIT_RANGE: + return "Invalid OP_SPLIT range"; case SCRIPT_ERR_BAD_OPCODE: return "Opcode missing or not understood"; case SCRIPT_ERR_DISABLED_OPCODE: diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -35,6 +35,7 @@ mempool_tests.cpp merkle_tests.cpp miner_tests.cpp + monolith_opcodes_string.cpp multisig_tests.cpp net_tests.cpp netbase_tests.cpp 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 @@ -818,13 +818,61 @@ ["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], -["'a' 'b'", "CAT", "P2SH,STRICTENC,MONOLITH_OPCODES", "DISABLED_OPCODE", "CAT disabled"], +["'ab' 'a' 'b'", "CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], ["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], -["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC,MONOLITH_OPCODES", "DISABLED_OPCODE", "CAT disabled"], -["'abc' 1 1", "SPLIT", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], -["'abc' 1 1", "SPLIT", "P2SH,STRICTENC,MONOLITH_OPCODES", "DISABLED_OPCODE", "SPLIT disabled"], -["'abc' 1 1 0", "IF SPLIT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], -["'abc' 1 1 0", "IF SPLIT ELSE 1 ENDIF", "P2SH,STRICTENC,MONOLITH_OPCODES", "DISABLED_OPCODE", "SPLIT disabled"], +["'ab' 'a' 'b' 1", "IF CAT ELSE 1 ENDIF EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +["'ab' 'a' 'b'", "CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +["'ab' 'a' 'b' 1", "IF CAT ELSE 1 ENDIF EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +[ + "'a' 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", + "CAT", + "P2SH,STRICTENC,MONOLITH_OPCODES", "PUSH_SIZE", "CAT errors properly" +], +[ + "'' 'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh'", + "CAT", + "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT null works" +], +[ "'zngyivniryrgefgnvqwfwqplmramujzilzyrsdvinxfkfmuowdpuzycnzbupwwpzrfxsbyrhdlsyixyzysodseayvvrtbsfxtikrjwkbduulrjyjlwlaigomhyohsukawdwbrpuacdijzzgxhataguajvuopuktvtklwhsxqvzzfttpdgnxtnbpsiqecxurlczqmoxznlsuejvneiyejetcxlblzrydscnrbydnqytorstjtuzlbbtbyzfiniuehbisqnqhvexylhohjiyiknzgjowvobsrwcxyfowqcvakgdolwpltfcxtrhuysrrvtprzpsucgogsjapdkrbobpxccqgkdumskaleycwsbkabdkuukqiyizceduplmauszwjdzptvmthxocwrignxjogxsvrsjrrlecvdmazlpfkgmskiqqitrevuwiisvpxvkeypzaqjwwiozvmahmtvtjpbolwrymvzfstopzcexalirwbbcqgjvfjfuirrcnlgcfyqnafhh' ''", + "CAT", + "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT null and maxlength element works in other direction" +], +["'a' 0", "CAT 'a' EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT with null produces a"], +["0 'a'", "CAT 'a' EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT with null produces a"], +["0 0", "CAT 0 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT with null with null produces null"], +["0 0", "CAT DEPTH 1 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "Stack depth correct"], +["'a'", "CAT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "Not enough operands"], +["", "CAT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "Not enough operands"], + + +["'abc' 1", "SPLIT", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], +["'a' 'abc' 1", "SPLIT DROP EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT enabled"], +["'abc' 1 0", "IF SPLIT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SPLIT disabled"], +["'a' 'abc' 1 1", "IF SPLIT ELSE 1 ENDIF DROP EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT enabled"], +["'bc' 'abc' 1", "SPLIT SWAP DROP EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT enabled"], +["'bc' 'abc' 1 1", "IF SPLIT ELSE 1 ENDIF SWAP DROP EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT enabled"], + +["1", "SPLIT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "SPLIT errors property on invalid stack"], +["1 'ab'", "SPLIT", "P2SH,STRICTENC,MONOLITH_OPCODES", "SPLIT_RANGE", "SPLIT errors property on invalid range"], +["'abcd' 'abcd'", "2 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT + SPLIT works"], +["'abcd' 'abcd'", "0 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT + SPLIT works"], +["'abcd' 'abcd'", "4 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT + SPLIT works"], +["'abcd' 'abcd'", "5 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "SPLIT_RANGE", "SPLIT on invalid index"], +["'abcd' 'abcd'", "-5 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "SPLIT_RANGE", "SPLIT on invalid index"], +["'ab' 0", "SPLIT 'ab' EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT at zero outputs empty array and original element"], +["'ab' 2", "SPLIT 0 EQUALVERIFY 'ab' EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT at zero outputs original element and empty array"], +["0 0", "SPLIT 0 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT OP_0 at zero outputs two empty arrays"], +["0 0", "SPLIT CAT 0 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT two empty arrays outputs a single empty array"], + +["0x02 0x0041", "1 SPLIT CAT 0x02 0x0041 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT + CAT of padded array works"], +["0x02 0x0000", "1 SPLIT CAT 0x02 0x0000 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "SPLIT + CAT of zero array works"], + +["0 0", "SPLIT DEPTH 2 EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "Stack depth correct"], +["1", "SPLIT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "Not enough operands"], +["", "SPLIT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "Not enough operands"], + +["'ba'", "CAT", "P2SH,STRICTENC,MONOLITH_OPCODES", "INVALID_STACK_OPERATION", "CAT fails correctly"], + ["'abc' 2 0", "IF NUM2BIN ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "NUM2BIN disabled"], ["'abc' 2 0", "IF NUM2BIN ELSE 1 ENDIF", "P2SH,STRICTENC,MONOLITH_OPCODES", "DISABLED_OPCODE", "NUM2BIN disabled"], ["'abc' 2 0", "IF BIN2NUM ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "BIN2NUM disabled"], diff --git a/src/test/monolith_opcodes_string.cpp b/src/test/monolith_opcodes_string.cpp new file mode 100644 --- /dev/null +++ b/src/test/monolith_opcodes_string.cpp @@ -0,0 +1,205 @@ +// Copyright (c) 2011-2018 The Bitcoin Cash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "script/script.h" +#include "script/interpreter.h" +#include "policy/policy.h" +#include +#include + +using namespace std; + +namespace { + +typedef std::vector valtype; +typedef std::vector stacktype; + +std::array flagset{0, + STANDARD_SCRIPT_VERIFY_FLAGS, + MANDATORY_SCRIPT_VERIFY_FLAGS}; + +static void CheckOpError(uint32_t flags, const stacktype &original_stack, + const CScript& script, ScriptError expected_error) { + BaseSignatureChecker sigchecker; + + ScriptError err = SCRIPT_ERR_OK; + stacktype stack{original_stack}; + bool r = EvalScript(stack, script, + flags | SCRIPT_ENABLE_MONOLITH_OPCODES, sigchecker, + &err); + BOOST_CHECK(!r); + BOOST_CHECK_EQUAL(err, expected_error); +} + +static void CheckOpError(const stacktype &original_stack, + const CScript& script, ScriptError expected_error) { + for (uint32_t flags : flagset) { + CheckOpError(flags, original_stack, script, expected_error); + } +} + +static void CheckOpError(const valtype& a, const CScript& script, + ScriptError expected_error) { + CheckOpError(stacktype{a}, script, expected_error); +} + +static void CheckOpError(const valtype& a, const valtype& b, const CScript& script, + ScriptError expected_error) { + CheckOpError(stacktype{a,b}, script, expected_error); +} + +////////////////////// methods which expect success. + +static void CheckOp(uint32_t flags, const stacktype original_stack, const CScript& script, + const stacktype &expected_stack) { + BaseSignatureChecker sigchecker; + + ScriptError err = SCRIPT_ERR_OK; + stacktype stack{original_stack}; + bool r = EvalScript(stack, script, + flags | SCRIPT_ENABLE_MONOLITH_OPCODES, sigchecker, + &err); + BOOST_CHECK(r); + BOOST_CHECK(stack == expected_stack); +} + +static void CheckOp(const stacktype &original_stack, const CScript& script, + const stacktype& expected_stack) { + for (uint32_t flags : flagset) { + CheckOp(flags, original_stack, script, expected_stack); + } +} + +static void CheckOp(const stacktype &original_stack, const CScript& script, + const valtype &expected) { + CheckOp(original_stack, script, stacktype{expected}); +} + +static void CheckOp(const valtype &a, const CScript& script, const valtype &expected) { + CheckOp(stacktype{a}, script, expected); +} + +static void CheckOp(const valtype &a, const valtype &b, const CScript& script, + const valtype &expected) { + CheckOp(stacktype{a, b}, script, expected); +} + +} // namespace + +/// OP_CAT + +void test_cat() { + CScript script; + script << OP_CAT; + + // Two inputs required + CheckOpError(stacktype(), script, SCRIPT_ERR_INVALID_STACK_OPERATION); + CheckOpError(stacktype{{0x00}}, script, SCRIPT_ERR_INVALID_STACK_OPERATION); + + valtype maxlength_valtype(MAX_SCRIPT_ELEMENT_SIZE, 0x00); + + // Concatenation producing illegal sized output + CheckOpError(stacktype{{maxlength_valtype}, {0x00}}, script, SCRIPT_ERR_PUSH_SIZE); + + // Concatenation of a max-sized valtype with empty is legal + CheckOp(stacktype{{maxlength_valtype}, {}}, script, maxlength_valtype); + CheckOp(stacktype{{}, {maxlength_valtype}}, script, maxlength_valtype); + + // Concatenation of a zero length operand + CheckOp(stacktype{{0x01}, {}}, script, valtype{0x01}); + CheckOp(stacktype{{}, {0x01}}, script, valtype{0x01}); + + // Concatenation of two empty operands results in empty valtype + CheckOp(stacktype{{}, {}}, script, valtype{}); + + // Concatenating two operands generates the correct result + CheckOp(stacktype{{0x00}, {0x00}}, script, {0x00, 0x00}); + CheckOp(stacktype{{0x01}, {0x02}}, script, {0x01, 0x02}); + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}, + {0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}}, + script, + valtype{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14}); +} + +/// OP_SPLIT + +void test_split() { + CScript script; + script << OP_SPLIT; //inputs: x n; outputs: x1 x2 + + // Two inputs required + CheckOpError(stacktype{}, script, SCRIPT_ERR_INVALID_STACK_OPERATION); + CheckOpError(stacktype{{0x01}}, script, SCRIPT_ERR_INVALID_STACK_OPERATION); + + // Length of 2nd input greater than CScriptNum::nDefaultMaxNumSize + valtype illegal_numeric_valtype(CScriptNum::nDefaultMaxNumSize, 0x01); + illegal_numeric_valtype.push_back(0x00); + CheckOpError(stacktype{{0x01}, illegal_numeric_valtype}, script, SCRIPT_ERR_UNKNOWN_ERROR); + + // if n == 0, then x1 is the empty array and x2 == x; + //execution of OP_SPLIT on empty array results in two empty arrays. + CheckOp(stacktype{{}, {}}, script, stacktype{{}, {}}); + CheckOp(stacktype{{0x01}, {}}, script, stacktype{{}, {0x01}}); //x 0 OP_SPLIT -> OP_0 x + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04}, {}}, script, stacktype{{}, {0x01, 0x02, 0x03, 0x04}}); + + // if n == len(x) then x1 == x and x2 is the empty array + CheckOp(stacktype{{0x01}, {0x01}}, script, stacktype{{0x01}, {}}); + CheckOp(stacktype{{0x01, 0x02, 0x03}, {0x03}}, script, stacktype{{0x01, 0x02, 0x03}, {}}); //x len(x) OP_SPLIT -> x OP_0 + + // if n > len(x), then the operator must fail; x (len(x) + 1) OP_SPLIT -> FAIL + CheckOpError(stacktype{{}, {0x01}}, script, SCRIPT_ERR_INVALID_SPLIT_RANGE); + CheckOpError(stacktype{{0x01}, {0x02}}, script, SCRIPT_ERR_INVALID_SPLIT_RANGE); + CheckOpError(stacktype{{0x01, 0x02, 0x03}, {0x04}}, script, SCRIPT_ERR_INVALID_SPLIT_RANGE); + CheckOpError(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x05}}, script, SCRIPT_ERR_INVALID_SPLIT_RANGE); + + // if n < 0 the operator must fail. + CheckOpError(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x81}}, script, SCRIPT_ERR_INVALID_SPLIT_RANGE); + + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x01}}, script, stacktype{{0x01}, {0x02, 0x03, 0x04}}); + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x02}}, script, stacktype{{0x01, 0x02}, {0x03, 0x04}}); + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x03}}, script, stacktype{{0x01, 0x02, 0x03}, {0x04}}); + CheckOp(stacktype{{0x01, 0x02, 0x03, 0x04}, {0x04}}, script, stacktype{{0x01, 0x02, 0x03, 0x04}, {}}); + + //split of a max-len valtype + valtype maxlength_valtype(MAX_SCRIPT_ELEMENT_SIZE, 0x00); + CheckOp(stacktype{maxlength_valtype, {}}, script, stacktype{{}, maxlength_valtype}); +} + +/// OP_CAT + OP_SPLIT + +void test_cat_split(const valtype& x) { + CScript script; + + // x n OP_SPLIT OP_CAT -> x - for all x and for all 0 <= n <= len(x) + script << OP_SPLIT << OP_CAT; + CheckOp(stacktype{x, {}}, script, x); + for (uint8_t i=1; i <= x.size(); ++i) { + CheckOp(stacktype{x, {i}}, script, x); + } +} + +void test_cat_split() { + test_cat_split({}); + test_cat_split({0x01}); + test_cat_split({0x01, 0x02}); + test_cat_split({0x01, 0x02, 0x03}); +} + +BOOST_AUTO_TEST_SUITE(opcodes_string) + +BOOST_AUTO_TEST_CASE(op_cat) { + test_cat(); +} + +BOOST_AUTO_TEST_CASE(op_split) { + test_split(); +} + +BOOST_AUTO_TEST_CASE(cat_split) { + test_cat_split(); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -62,6 +62,8 @@ {SCRIPT_ERR_STACK_SIZE, "STACK_SIZE"}, {SCRIPT_ERR_SIG_COUNT, "SIG_COUNT"}, {SCRIPT_ERR_PUBKEY_COUNT, "PUBKEY_COUNT"}, + {SCRIPT_ERR_PUBKEY_COUNT, "PUBKEY_COUNT"}, + {SCRIPT_ERR_INVALID_SPLIT_RANGE, "SPLIT_RANGE"}, {SCRIPT_ERR_VERIFY, "VERIFY"}, {SCRIPT_ERR_EQUALVERIFY, "EQUALVERIFY"}, {SCRIPT_ERR_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"},