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; @@ -839,6 +839,7 @@ // // Bitwise logic // + case OP_EQUAL: case OP_EQUALVERIFY: // case OP_NOTEQUAL: // use OP_NUMNOTEQUAL @@ -1238,6 +1239,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()); + stack.pop_back(); + } 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); + } + + stack.pop_back(); + stack.pop_back(); + + // 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,26 @@ ["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"], + +["'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"], + +["'abcd' 'abcd'", "2 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +["'abcd' 'abcd'", "0 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +["'abcd' 'abcd'", "4 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "OK", "CAT enabled"], +["'abcd' 'abcd'", "5 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "SPLIT_RANGE", "CAT enabled"], +["'abcd' 'abcd'", "-5 SPLIT CAT EQUAL", "P2SH,STRICTENC,MONOLITH_OPCODES", "SPLIT_RANGE", "CAT enabled"], + ["'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 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"},