Index: src/script/interpreter.cpp =================================================================== --- src/script/interpreter.cpp +++ src/script/interpreter.cpp @@ -334,8 +334,11 @@ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) { 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) { + + if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || + opcode == OP_RIGHT || opcode == OP_INVERT || 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); } @@ -784,31 +787,35 @@ return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } - valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); - // throw error if inputs are not the same size if (vch1.size() != vch2.size()) { return set_error( serror, SCRIPT_ERR_INVALID_BITWISE_OPERATION); } - if (opcode == OP_AND) { - for (size_t i = 0; i < vch1.size(); i++) - vch1[i] &= vch2[i]; - } - else if (opcode == OP_OR) { - for (size_t i = 0; i < vch1.size(); i++) - vch1[i] |= vch2[i]; - } - else if (opcode == OP_XOR) { - for (size_t i = 0; i < vch1.size(); i++) - vch1[i] ^= vch2[i]; + switch (opcode) { + case OP_AND: + for (size_t i = 0; i < vch1.size(); i++) { + vch1[i] &= vch2[i]; + } + break; + case OP_OR: + for (size_t i = 0; i < vch1.size(); i++) { + vch1[i] |= vch2[i]; + } + break; + case OP_XOR: + for (size_t i = 0; i < vch1.size(); i++) { + vch1[i] ^= vch2[i]; + } + break; + default: //avoid enumeration value not handled in switch compiler warning + break; } stack.pop_back(); - } - break; + } break; case OP_EQUAL: case OP_EQUALVERIFY: @@ -888,8 +895,6 @@ case OP_ADD: case OP_SUB: - case OP_DIV: - case OP_MOD: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: @@ -906,7 +911,6 @@ return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } - // first two inputs must be minimally encoded numbers CScriptNum bn1(stacktop(-2), fRequireMinimal); CScriptNum bn2(stacktop(-1), fRequireMinimal); CScriptNum bn(0); @@ -919,23 +923,6 @@ bn = bn1 - bn2; break; - case OP_DIV: - // bn2 must not be 0 - if (bn2 == 0) { - return set_error( - serror, SCRIPT_ERR_DIV_BY_ZERO); - } - bn = bn1 / bn2; - break; - case OP_MOD: - // 2nd operand must be positive - if (bn2 <= 0) { - return set_error( - serror, SCRIPT_ERR_MOD_BY_ZERO); - } - bn = bn1 % bn2; - break; - case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; @@ -1229,98 +1216,6 @@ } } break; - 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; - - case OP_BIN2NUM: { - // (in -- out) - if (stack.size() < 1) { - return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - } - valtype bin=stacktop(-1); - std::reverse(bin.begin(),bin.end()); //be2le - CScriptNum num(bin, false); - if (num > (INT_MAX>>1) || num < (INT_MIN>>1)) - return set_error(serror, SCRIPT_ERR_INVALID_BIN2NUM_OPERATION); - stack.pop_back(); - stack.push_back(num.getvch()); - } break; - - case OP_NUM2BIN: { - if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); - CScriptNum bn(stacktop(-2), fRequireMinimal); - int64_t sz = CScriptNum(stacktop(-1), fRequireMinimal).getint(); - if (sz<1 || static_cast(sz) > MAX_NUM2BIN_SIZE) - return set_error(serror, SCRIPT_ERR_INVALID_NUM2BIN_OPERATION); - valtype v=bn.getvch(); //LE - if (static_cast(sz) < v.size()) - return set_error(serror, SCRIPT_ERR_INVALID_NUM2BIN_OPERATION); - valtype ans; - ans.reserve(sz); - bool neg{false}; - if (!v.empty()) { - neg=*v.rbegin()&0x80; - *v.rbegin()&=~0x80; //make it positive - } - size_t pad=sz-v.size(); - for (uint8_t i=0; i std::vector ToByteVector(const T &in) { return std::vector(in.begin(), in.end()); } @@ -105,7 +102,9 @@ // splice ops OP_CAT = 0x7e, - OP_SPLIT = 0x7f, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, OP_SIZE = 0x82, // bit logic @@ -163,8 +162,6 @@ OP_CHECKMULTISIGVERIFY = 0xaf, // expansion - OP_BIN2NUM = 0x80, - OP_NUM2BIN = 0x81, OP_NOP1 = 0xb0, OP_CHECKLOCKTIMEVERIFY = 0xb1, OP_NOP2 = OP_CHECKLOCKTIMEVERIFY, @@ -276,20 +273,6 @@ 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); - } - inline CScriptNum operator%(const CScriptNum &rhs) const { - return operator%(rhs.m_value); - } - inline CScriptNum &operator+=(const CScriptNum &rhs) { return operator+=(rhs.m_value); } Index: src/script/script.cpp =================================================================== --- src/script/script.cpp +++ src/script/script.cpp @@ -121,8 +121,12 @@ // splice ops case OP_CAT: return "OP_CAT"; - case OP_SPLIT: - return "OP_SPLIT"; + case OP_SUBSTR: + return "OP_SUBSTR"; + case OP_LEFT: + return "OP_LEFT"; + case OP_RIGHT: + return "OP_RIGHT"; case OP_SIZE: return "OP_SIZE"; @@ -223,10 +227,6 @@ return "OP_CHECKMULTISIGVERIFY"; // expansion - case OP_BIN2NUM: - return "OP_BIN2NUM"; - case OP_NUM2BIN: - return "OP_NUM2BIN"; case OP_NOP1: return "OP_NOP1"; case OP_CHECKLOCKTIMEVERIFY: Index: src/script/script_error.h =================================================================== --- src/script/script_error.h +++ src/script/script_error.h @@ -33,11 +33,6 @@ SCRIPT_ERR_INVALID_STACK_OPERATION, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, SCRIPT_ERR_UNBALANCED_CONDITIONAL, - SCRIPT_ERR_DIV_BY_ZERO, - SCRIPT_ERR_MOD_BY_ZERO, - SCRIPT_ERR_INVALID_BIN2NUM_OPERATION, - SCRIPT_ERR_INVALID_NUM2BIN_OPERATION, - SCRIPT_ERR_INVALID_SPLIT_RANGE, SCRIPT_ERR_INVALID_BITWISE_OPERATION, /* CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY */ Index: src/script/script_error.cpp =================================================================== --- src/script/script_error.cpp +++ src/script/script_error.cpp @@ -46,16 +46,6 @@ return "OP_RETURN was encountered"; case SCRIPT_ERR_UNBALANCED_CONDITIONAL: return "Invalid OP_IF construction"; - case SCRIPT_ERR_DIV_BY_ZERO: - return "Invalid division operation"; - case SCRIPT_ERR_MOD_BY_ZERO: - return "Invalid modulo operation"; - case SCRIPT_ERR_INVALID_BIN2NUM_OPERATION: - return "Invalid OP_BIN2NUM operation (check operand values)"; - case SCRIPT_ERR_INVALID_NUM2BIN_OPERATION: - return "Invalid OP_NUM2BIN operation (check operand values)"; - case SCRIPT_ERR_INVALID_SPLIT_RANGE: - return "Invalid OP_SPLIT range"; case SCRIPT_ERR_INVALID_BITWISE_OPERATION: return "Invalid bitwise operation (check length of inputs)"; case SCRIPT_ERR_NEGATIVE_LOCKTIME: Index: src/test/data/script_tests.json =================================================================== --- src/test/data/script_tests.json +++ src/test/data/script_tests.json @@ -817,12 +817,17 @@ ["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], +["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"], + ["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"], ["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"], ["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"], ["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"], ["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"], ["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"], ["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"], @@ -838,8 +843,10 @@ ["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"], ["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], +["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], ["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"], Index: src/test/op_code.cpp =================================================================== --- src/test/op_code.cpp +++ src/test/op_code.cpp @@ -1,13 +1,10 @@ -// Copyright (c) 2011-2016 The Bitcoin Core developers +// 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 "data/script_tests.json.h" - #include "script/script.h" #include "script/interpreter.h" #include "policy/policy.h" -#include "core_io.h" #include #include @@ -25,6 +22,7 @@ #ifdef VERBOSE #include #include +#include "core_io.h" #endif namespace { @@ -43,6 +41,8 @@ } #endif + /// Deepest sole function for testing expected errors + /// Invokes the interpreter. void test(const CScript& script, stack_t stack, uint32_t flags, const ScriptError se) { #ifdef VERBOSE cout << "--------------" << endl; @@ -61,7 +61,8 @@ BOOST_CHECK_EQUAL(err==se, true); } - + /// Deepest sole function for testing expected returning stacks + /// Invokes the interpreter. void test(const CScript& script, stack_t stack, uint32_t flags, stack_t expected) { #ifdef VERBOSE cout << "--------------" << endl; @@ -83,118 +84,7 @@ BOOST_CHECK_EQUAL(stack==expected, true); } - void test_cat(uint32_t flags) { - CScript script; - script << OP_CAT; - - //two inputs required - test(script,stack_t(),flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - test(script,stack_t{{0x00}},flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - - //stack item with maximum length - item maxlength_item(MAX_SCRIPT_ELEMENT_SIZE, 0x00); - - //Concatenation producing illegal sized output - { - stack_t input_stack; - input_stack.push_back(maxlength_item); - item i; - i.push_back(0x00); - input_stack.push_back(i); - test(script,input_stack,flags,SCRIPT_ERR_PUSH_SIZE); - } - - //Concatenation of a max-sized item with empty is legal - { - stack_t input_stack; - input_stack.push_back(maxlength_item); - input_stack.push_back(item()); //empty item - test(script,input_stack,flags,stack_t{maxlength_item}); - } - { - stack_t input_stack; - input_stack.push_back(item()); //empty item - input_stack.push_back(maxlength_item); - test(script,input_stack,flags,stack_t{maxlength_item}); - } - - //Concatenation of a zero length operand - test(script,stack_t{{0x01},{}},flags,stack_t{{0x01}}); - test(script,stack_t{{},{0x01}},flags,stack_t{{0x01}}); - - //Concatenation of two empty operands results in empty item - test(script,stack_t{{},{}},flags,stack_t{{}}); - - // concatenating two operands generates the correct result - test(script,stack_t{{0x00},{0x00}},flags,stack_t{{0x00,0x00}}); - test(script,stack_t{{0x01},{0x02}},flags,stack_t{{0x01,0x02}}); - test(script,stack_t{{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a},{0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14}},flags,stack_t{{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14}}); - } - - void test_split(uint32_t flags) { - CScript script; - script << OP_SPLIT; //inputs: x n; outputs: x1 x2 - - //two inputs required - test(script,stack_t(),flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - test(script,stack_t{{0x01}},flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - - //length of 2nd input greater than CScriptNum::nDefaultMaxNumSize - { - item maxlength_num_item(CScriptNum::nDefaultMaxNumSize,0x01); - item illegal_item=maxlength_num_item; - illegal_item.push_back(0x00); - test(script,stack_t{{0x01},illegal_item},flags,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. - test(script,stack_t{{},{}},flags,stack_t{{},{}}); - test(script,stack_t{{0x01},{}},flags,stack_t{{},{0x01}}); //x 0 OP_SPLIT -> OP_0 x - test(script,stack_t{{0x01,0x02,0x03,0x04},{}},flags,stack_t{{},{0x01,0x02,0x03,0x04}}); - - //if n == len(x) then x1 == x and x2 is the empty array - test(script,stack_t{{0x01},{0x01}},flags,stack_t{{0x01},{}}); - test(script,stack_t{{0x01,0x02,0x03},{0x03}},flags,stack_t{{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 - test(script,stack_t{{},{0x01}},flags,SCRIPT_ERR_INVALID_SPLIT_RANGE); - test(script,stack_t{{0x01},{0x02}},flags,SCRIPT_ERR_INVALID_SPLIT_RANGE); - test(script,stack_t{{0x01,0x02,0x03},{0x04}},flags,SCRIPT_ERR_INVALID_SPLIT_RANGE); - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x05}},flags,SCRIPT_ERR_INVALID_SPLIT_RANGE); - - //if n < 0 the operator must fail. - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x81}},flags,SCRIPT_ERR_INVALID_SPLIT_RANGE); - - - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x01}},flags,stack_t{{0x01},{0x02,0x03,0x04}}); - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x02}},flags,stack_t{{0x01,0x02},{0x03,0x04}}); - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x03}},flags,stack_t{{0x01,0x02,0x03},{0x04}}); - test(script,stack_t{{0x01,0x02,0x03,0x04},{0x04}},flags,stack_t{{0x01,0x02,0x03,0x04},{}}); - - //split of a max-len item - { - item maxlength_item(MAX_SCRIPT_ELEMENT_SIZE, 0x00); - test(script,stack_t{maxlength_item,{}},flags,stack_t{{},maxlength_item}); - } - } - - void test_cat_split(const item& x, uint32_t flags) { - CScript script; - script << OP_SPLIT << OP_CAT; - // x n OP_SPLIT OP_CAT -> x - for all x and for all 0 <= n <= len(x) - test(script,stack_t{x,{}},flags,stack_t{x}); - for (uint8_t i=1; i<=x.size(); ++i) { - test(script,stack_t{x,{i}},flags,stack_t{x}); - } - } - - void test_cat_split(uint32_t flags) { - test_cat_split({},flags); - test_cat_split({0x01},flags); - test_cat_split({0x01,0x02},flags); - test_cat_split({0x01,0x02,0x03},flags); - } + /// OP_AND, OP_OR, OP_XOR common tests void test_bitwiseop(const CScript& script, uint32_t flags) { //number of inputs @@ -216,6 +106,8 @@ test(script,stack_t{{0x01,0x01,0x01},{0x01,0x01}},flags,SCRIPT_ERR_INVALID_BITWISE_OPERATION); } + /// OP_AND tests + void test_and(uint32_t flags) { CScript script; script << OP_AND; @@ -245,6 +137,8 @@ } } + /// OP_OR tests + void test_or(uint32_t flags) { CScript script; script << OP_OR; @@ -275,6 +169,9 @@ } } + + /// OP_XOR tests + void test_xor(uint32_t flags) { CScript script; script << OP_XOR; @@ -305,289 +202,11 @@ } } - void test_div(uint32_t flags) { - CScript script; - script << OP_DIV; - - test(script,stack_t(),flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - test(script,stack_t{{}},flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - - //test not valid numbers - test(script,stack_t{{0x01,0x02,0x03,0x04,0x05},{0x01,0x02,0x03,0x04,0x05}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - test(script,stack_t{{0x01,0x02,0x03,0x04,0x05},{0x01}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - test(script,stack_t{{0x01,0x05},{0x01,0x02,0x03,0x04,0x05}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - //b == 0 ; b is equal to any type of zero - test(script,stack_t{{0x01,0x05},{}},flags,SCRIPT_ERR_DIV_BY_ZERO); - test(script,stack_t{{},{}},flags,SCRIPT_ERR_DIV_BY_ZERO); - if (flags&SCRIPT_VERIFY_MINIMALDATA) { - test(script,stack_t{{},{0x00}},flags,SCRIPT_ERR_UNKNOWN_ERROR); //not minimal encoding - test(script,stack_t{{},{0x00,0x00}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - } - else { - test(script,stack_t{{},{0x00}},flags,SCRIPT_ERR_DIV_BY_ZERO); - test(script,stack_t{{},{0x00,0x00}},flags,SCRIPT_ERR_DIV_BY_ZERO); - } - //185377af/85f41b01 =-4 - //185377af/00001b01 =E69D - test(script,stack_t{{0xaf,0x77,0x53,0x18},{0x01,0x1b,0xf4,0x85}},flags,stack_t{{0x84}}); - test(script,stack_t{{0xaf,0x77,0x53,0x18},{0x01,0x1b}},flags,stack_t{{0x9D,0xE6,0x00}}); - //15/4 =3 - //15/-4 =-3 - //-15/4 =-3 - //-15/-4 =3 - test(script,stack_t{{0x0f},{0x04}},flags,stack_t{{0x03}}); - test(script,stack_t{{0x0f},{0x84}},flags,stack_t{{0x83}}); - test(script,stack_t{{0x8f},{0x04}},flags,stack_t{{0x83}}); - test(script,stack_t{{0x8f},{0x84}},flags,stack_t{{0x03}}); - //15000/4 =3750 - //15000/-4 =-3750 - //-15000/4 =-3750 - //-15000/-4 =3750 - test(script,stack_t{{0x98,0x3a},{0x04}},flags,stack_t{{0xa6,0x0e}}); - test(script,stack_t{{0x98,0x3a},{0x84}},flags,stack_t{{0xa6,0x8e}}); - test(script,stack_t{{0x98,0xba},{0x04}},flags,stack_t{{0xa6,0x8e}}); - test(script,stack_t{{0x98,0xba},{0x84}},flags,stack_t{{0xa6,0x0e}}); - //15000/4000 =3 - //15000/-4000 =-3 - //-15000/4000 =-3 - //-15000/-4000 =3 - test(script,stack_t{{0x98,0x3a},{0xa0,0x0f}},flags,stack_t{{0x03}}); - test(script,stack_t{{0x98,0x3a},{0xa0,0x8f}},flags,stack_t{{0x83}}); - test(script,stack_t{{0x98,0xba},{0xa0,0x0f}},flags,stack_t{{0x83}}); - test(script,stack_t{{0x98,0xba},{0xa0,0x8f}},flags,stack_t{{0x03}}); - //15000000/4000 =3750 - //15000000/-4000 =-3750 - //-15000000/4000 =-3750 - //-15000000/-4000 =3750 - test(script,stack_t{{0xc0,0xe1,0xe4,0x00},{0xa0,0x0f}},flags,stack_t{{0xa6,0x0e}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x00},{0xa0,0x8f}},flags,stack_t{{0xa6,0x8e}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x80},{0xa0,0x0f}},flags,stack_t{{0xa6,0x8e}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x80},{0xa0,0x8f}},flags,stack_t{{0xa6,0x0e}}); - //15000000/4 =3750000 - //15000000/-4 =-3750000 - //-15000000/4 =-3750000 - //-15000000/-4 =3750000 - test(script,stack_t{{0xc0,0xe1,0xe4,0x00},{0x04}},flags,stack_t{{0x70,0x38,0x39}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x00},{0x84}},flags,stack_t{{0x70,0x38,0xb9}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x80},{0x04}},flags,stack_t{{0x70,0x38,0xb9}}); - test(script,stack_t{{0xc0,0xe1,0xe4,0x80},{0x84}},flags,stack_t{{0x70,0x38,0x39}}); - } - - void test_mod(uint32_t flags) { - CScript script; - script << OP_MOD; - - test(script,stack_t(),flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - test(script,stack_t{{}},flags,SCRIPT_ERR_INVALID_STACK_OPERATION); - - //test not valid numbers - test(script,stack_t{{0x01,0x02,0x03,0x04,0x05},{0x01,0x02,0x03,0x04,0x05}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - test(script,stack_t{{0x01,0x02,0x03,0x04,0x05},{0x01}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - test(script,stack_t{{0x01,0x05},{0x01,0x02,0x03,0x04,0x05}},flags,SCRIPT_ERR_UNKNOWN_ERROR); - - //mod by <0 - test(script,stack_t{{0x01,0x05},{}},flags,SCRIPT_ERR_MOD_BY_ZERO); - test(script,stack_t{{0x01,0x05},{0x81}},flags,SCRIPT_ERR_MOD_BY_ZERO); - test(script,stack_t{{0x01,0x05},{0xad,0x81}},flags,SCRIPT_ERR_MOD_BY_ZERO); - - //56488123%321 =148 - //56488123%3 =1 - //56488123%564881230 =56488123 - test(script,stack_t{{0xbb,0xf0,0x5d,0x03},{0x41,0x01}},flags,stack_t{{0x94,0x00}}); - test(script,stack_t{{0xbb,0xf0,0x5d,0x03},{0x03}},flags,stack_t{{0x01}}); - test(script,stack_t{{0xbb,0xf0,0x5d,0x03},{0x4e,0x67,0xab,0x21}},flags,stack_t{{0xbb,0xf0,0x5d,0x03}}); - - //-56488123%321 = -148 - //-56488123%3 = -1 - //-56488123%564881230 = -56488123 - test(script,stack_t{{0xbb,0xf0,0x5d,0x83},{0x41,0x01}},flags,stack_t{{0x94,0x80}}); - test(script,stack_t{{0xbb,0xf0,0x5d,0x83},{0x03}},flags,stack_t{{0x81}}); - test(script,stack_t{{0xbb,0xf0,0x5d,0x83},{0x4e,0x67,0xab,0x21}},flags,stack_t{{0xbb,0xf0,0x5d,0x83}}); - } - - vector make_ev(vector v, size_t sz) { //v contains a num in LE - if (v.empty()) return vector(sz,0); - vector ans; - assert(sz>=v.size()); - ans.reserve(sz); - bool neg=*v.rbegin()&0x80; - *v.rbegin()&=~0x80; - size_t pad=sz-v.size(); - for (uint8_t i=0; i v, uint32_t flags) { - if (v.empty()) return; - for (uint8_t i=0; i(&v); - for (size_t i=0; i>1)},flags,stack_t{CScriptNum(INT_MAX>>1).getvch()}); - test(script,stack_t{mk_bin((int64_t)INT_MIN>>1)},flags,stack_t{CScriptNum(INT_MIN>>1).getvch()}); - test(script,stack_t{mk_bin((int64_t)(INT_MAX>>1)+1)},flags,SCRIPT_ERR_INVALID_BIN2NUM_OPERATION); - test(script,stack_t{mk_bin((int64_t)(INT_MIN>>1)-1)},flags,SCRIPT_ERR_INVALID_BIN2NUM_OPERATION); - test(script,stack_t{mk_bin(106894)},flags,stack_t{CScriptNum(106894).getvch()}); - test(script,stack_t{mk_bin(-106894)},flags,stack_t{CScriptNum(-106894).getvch()}); - test(script,stack_t{mk_bin(0)},flags,stack_t{CScriptNum(0).getvch()}); - } - - void test_bin2num_num2bin(const CScript& script, int sz, int64_t v, uint32_t flags) { - auto x=mk_bin(v); - test(script,stack_t{x},flags,stack_t{make_ev(CScriptNum(v).getvch(),sz)}); - } - - void test_num2bin_bin2num(const CScript& script, int64_t v, uint32_t flags) { - test(script,stack_t{CScriptNum(v).getvch()},flags,stack_t{CScriptNum(v).getvch()}); - } - - void test_bin2num_num2bin(int sz, uint32_t flags) { - CScript script; - script << OP_BIN2NUM << sz << OP_NUM2BIN; - test_bin2num_num2bin(script,sz,0,flags); - test_bin2num_num2bin(script,sz,1,flags); - test_bin2num_num2bin(script,sz,-1,flags); - if (sz>=2) { - test_bin2num_num2bin(script,sz,321,flags); - test_bin2num_num2bin(script,sz,-321,flags); - if (sz>=3) { - test_bin2num_num2bin(script,sz,106894,flags); - test_bin2num_num2bin(script,sz,-106894,flags); - if (sz>=4) { - test_bin2num_num2bin(script,sz,INT_MAX>>1,flags); - test_bin2num_num2bin(script,sz,INT_MIN>>1,flags); - } - } - } - } - - void test_num2bin_bin2num(int sz, uint32_t flags) { - CScript script; - script << sz << OP_NUM2BIN << OP_BIN2NUM; - test_num2bin_bin2num(script,0,flags); - test_num2bin_bin2num(script,1,flags); - test_num2bin_bin2num(script,-1,flags); - if (sz>=2) { - test_num2bin_bin2num(script,321,flags); - test_num2bin_bin2num(script,-321,flags); - if (sz>=3) { - test_num2bin_bin2num(script,106894,flags); - test_num2bin_bin2num(script,-106894,flags); - if (sz>=4) { - test_num2bin_bin2num(script,INT_MAX>>1,flags); - test_num2bin_bin2num(script,INT_MIN>>1,flags); - } - } - } - } - - void test_bin2num_num2bin(uint32_t flags) { - test_bin2num_num2bin(4,flags); //expect 4 byte output - test_bin2num_num2bin(3,flags); //expect 3 byte output - test_bin2num_num2bin(2,flags); //expect 2 byte output - test_bin2num_num2bin(1,flags); //expect 1 byte output - } - - void test_num2bin_bin2num(uint32_t flags) { - test_num2bin_bin2num(4,flags); //4 byte num2bin output - test_num2bin_bin2num(3,flags); //3 byte num2bin output - test_num2bin_bin2num(2,flags); //2 byte num2bin output - test_num2bin_bin2num(1,flags); //1 byte num2bin output - } -} - -BOOST_AUTO_TEST_SUITE(op_code) - -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); } -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); -} +/// Entry points -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); -} +BOOST_AUTO_TEST_SUITE(op_code) BOOST_AUTO_TEST_CASE(op_and) { test_and(0); @@ -610,50 +229,5 @@ test_xor(STANDARD_LOCKTIME_VERIFY_FLAGS); } -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); -} - - -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); -} - - -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); - -} - -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); -} - -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); -} - -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); -} - BOOST_AUTO_TEST_SUITE_END()