Index: src/script/interpreter.cpp =================================================================== --- src/script/interpreter.cpp +++ src/script/interpreter.cpp @@ -335,9 +335,8 @@ return set_error(serror, SCRIPT_ERR_OP_COUNT); } - if (opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_2MUL || - opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_LSHIFT || - opcode == OP_RSHIFT) { + 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); } @@ -1306,6 +1305,39 @@ 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) > CScriptNum::nDefaultMaxNumSize) { + 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 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=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 + } + } /// Entry points @@ -535,5 +669,27 @@ test_bin2num(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(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()