diff --git a/src/script/script.h b/src/script/script.h --- a/src/script/script.h +++ b/src/script/script.h @@ -189,6 +189,8 @@ const char *GetOpName(opcodetype opcode); +std::vector MinimalizeBigEndianArray(const std::vector &data); + class scriptnum_error : public std::runtime_error { public: explicit scriptnum_error(const std::string &str) diff --git a/src/script/script.cpp b/src/script/script.cpp --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -8,6 +8,8 @@ #include "tinyformat.h" #include "utilstrencodings.h" +#include + const char *GetOpName(opcodetype opcode) { switch (opcode) { // push value @@ -262,6 +264,37 @@ } } +std::vector +MinimalizeBigEndianArray(const std::vector &data) { + std::vector res; + + // Ensure we have a byte to work with. + if (data.size() == 0) { + return res; + } + + // Check for a negative bit + uint8_t msb = data[0] & 0x80; + bool start = false; + for (size_t i = 0; i < data.size(); ++i) { + uint8_t x = data[i]; + if (i == 0 && (x & 0x7f) == 0) { + continue; + } + if (!start && x == 0) { + continue; + } + start = true; + res.push_back(x); + } + + if (res.size() != 0) { + res[0] |= msb; + } + + return res; +} + unsigned int CScript::GetSigOpCount(bool fAccurate) const { unsigned int n = 0; const_iterator pc = begin(); 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 @@ -414,6 +414,22 @@ } } // namespace +BOOST_AUTO_TEST_CASE(minimize_big_endian_test) { + std::vector input( + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01}}); + std::vector negInput( + {{0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01}}); + + std::vector check({0x01, 0x00, 0x00, 0x01}); + std::vector negCheck({0x81, 0x00, 0x00, 0x01}); + + std::vector out = MinimalizeBigEndianArray(input); + std::vector negOut = MinimalizeBigEndianArray(negInput); + + BOOST_CHECK(out == check); + BOOST_CHECK(negOut == negCheck); +} + BOOST_AUTO_TEST_CASE(script_build) { const KeyData keys;