Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto # 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers # 3 : : // Distributed under the MIT software license, see the accompanying # 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. # 5 : : # 6 : : #ifndef BITCOIN_TEST_SCRIPTNUM10_H # 7 : : #define BITCOIN_TEST_SCRIPTNUM10_H # 8 : : # 9 : : #include <assert.h> # 10 : : #include <limits> # 11 : : #include <stdexcept> # 12 : : #include <stdint.h> # 13 : : #include <string> # 14 : : #include <vector> # 15 : : # 16 : : class scriptnum10_error : public std::runtime_error # 17 : : { # 18 : : public: # 19 : 144 : explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {} # 20 : : }; # 21 : : # 22 : : class CScriptNum10 # 23 : : { # 24 : : /** # 25 : : * The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison. # 26 : : */ # 27 : : public: # 28 : : # 29 : : explicit CScriptNum10(const int64_t& n) # 30 : 51948 : { # 31 : 51948 : m_value = n; # 32 : 51948 : } # 33 : : # 34 : : static const size_t nDefaultMaxNumSize = 4; # 35 : : # 36 : : explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal, # 37 : : const size_t nMaxNumSize = nDefaultMaxNumSize) # 38 : 1260 : { # 39 [ + + ]: 1260 : if (vch.size() > nMaxNumSize) { # 40 : 144 : throw scriptnum10_error("script number overflow"); # 41 : 144 : } # 42 [ - + ][ # # ]: 1116 : if (fRequireMinimal && vch.size() > 0) { # 43 : : // Check that the number is encoded with the minimum possible # 44 : : // number of bytes. # 45 : : // # 46 : : // If the most-significant-byte - excluding the sign bit - is zero # 47 : : // then we're not minimal. Note how this test also rejects the # 48 : : // negative-zero encoding, 0x80. # 49 [ # # ]: 0 : if ((vch.back() & 0x7f) == 0) { # 50 : : // One exception: if there's more than one byte and the most # 51 : : // significant bit of the second-most-significant-byte is set # 52 : : // it would conflict with the sign bit. An example of this case # 53 : : // is +-255, which encode to 0xff00 and 0xff80 respectively. # 54 : : // (big-endian). # 55 [ # # ][ # # ]: 0 : if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) { # 56 : 0 : throw scriptnum10_error("non-minimally encoded script number"); # 57 : 0 : } # 58 : 0 : } # 59 : 0 : } # 60 : 1116 : m_value = set_vch(vch); # 61 : 1116 : } # 62 : : # 63 : 11232 : inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } # 64 : 11232 : inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } # 65 : 11232 : inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } # 66 : 11232 : inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } # 67 : 11232 : inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } # 68 : 11232 : inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } # 69 : : # 70 : 11232 : inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); } # 71 : 11232 : inline bool operator!=(const CScriptNum10& rhs) const { return operator!=(rhs.m_value); } # 72 : 11232 : inline bool operator<=(const CScriptNum10& rhs) const { return operator<=(rhs.m_value); } # 73 : 11232 : inline bool operator< (const CScriptNum10& rhs) const { return operator< (rhs.m_value); } # 74 : 11232 : inline bool operator>=(const CScriptNum10& rhs) const { return operator>=(rhs.m_value); } # 75 : 11232 : inline bool operator> (const CScriptNum10& rhs) const { return operator> (rhs.m_value); } # 76 : : # 77 : 8424 : inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);} # 78 : 11232 : inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);} # 79 : 8424 : inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); } # 80 : 11232 : inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); } # 81 : : # 82 : 0 : inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); } # 83 : 0 : inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); } # 84 : : # 85 : : inline CScriptNum10 operator-() const # 86 : 2808 : { # 87 : 2808 : assert(m_value != std::numeric_limits<int64_t>::min()); # 88 : 0 : return CScriptNum10(-m_value); # 89 : 2808 : } # 90 : : # 91 : : inline CScriptNum10& operator=( const int64_t& rhs) # 92 : 0 : { # 93 : 0 : m_value = rhs; # 94 : 0 : return *this; # 95 : 0 : } # 96 : : # 97 : : inline CScriptNum10& operator+=( const int64_t& rhs) # 98 : 0 : { # 99 : 0 : assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || # 100 : 0 : (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)); # 101 : 0 : m_value += rhs; # 102 : 0 : return *this; # 103 : 0 : } # 104 : : # 105 : : inline CScriptNum10& operator-=( const int64_t& rhs) # 106 : 0 : { # 107 : 0 : assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || # 108 : 0 : (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)); # 109 : 0 : m_value -= rhs; # 110 : 0 : return *this; # 111 : 0 : } # 112 : : # 113 : : int getint() const # 114 : 29898 : { # 115 [ + + ]: 29898 : if (m_value > std::numeric_limits<int>::max()) # 116 : 2450 : return std::numeric_limits<int>::max(); # 117 [ + + ]: 27448 : else if (m_value < std::numeric_limits<int>::min()) # 118 : 1748 : return std::numeric_limits<int>::min(); # 119 : 25700 : return m_value; # 120 : 29898 : } # 121 : : # 122 : : std::vector<unsigned char> getvch() const # 123 : 28350 : { # 124 : 28350 : return serialize(m_value); # 125 : 28350 : } # 126 : : # 127 : : static std::vector<unsigned char> serialize(const int64_t& value) # 128 : 28350 : { # 129 [ + + ]: 28350 : if(value == 0) # 130 : 4864 : return std::vector<unsigned char>(); # 131 : : # 132 : 23486 : std::vector<unsigned char> result; # 133 : 23486 : const bool neg = value < 0; # 134 [ + + ]: 23486 : uint64_t absvalue = neg ? -value : value; # 135 : : # 136 [ + + ]: 82094 : while(absvalue) # 137 : 58608 : { # 138 : 58608 : result.push_back(absvalue & 0xff); # 139 : 58608 : absvalue >>= 8; # 140 : 58608 : } # 141 : : # 142 : : // - If the most significant byte is >= 0x80 and the value is positive, push a # 143 : : // new zero-byte to make the significant byte < 0x80 again. # 144 : : # 145 : : // - If the most significant byte is >= 0x80 and the value is negative, push a # 146 : : // new 0x80 byte that will be popped off when converting to an integral. # 147 : : # 148 : : // - If the most significant byte is < 0x80 and the value is negative, add # 149 : : // 0x80 to it, since it will be subtracted and interpreted as a negative when # 150 : : // converting to an integral. # 151 : : # 152 [ + + ]: 23486 : if (result.back() & 0x80) # 153 [ + + ]: 8340 : result.push_back(neg ? 0x80 : 0); # 154 [ + + ]: 15146 : else if (neg) # 155 : 6716 : result.back() |= 0x80; # 156 : : # 157 : 23486 : return result; # 158 : 28350 : } # 159 : : # 160 : : private: # 161 : : static int64_t set_vch(const std::vector<unsigned char>& vch) # 162 : 1116 : { # 163 [ + + ]: 1116 : if (vch.empty()) # 164 : 56 : return 0; # 165 : : # 166 : 1060 : int64_t result = 0; # 167 [ + + ]: 3560 : for (size_t i = 0; i != vch.size(); ++i) # 168 : 2500 : result |= static_cast<int64_t>(vch[i]) << 8*i; # 169 : : # 170 : : // If the input vector's most significant byte is 0x80, remove it from # 171 : : // the result's msb and return a negative. # 172 [ + + ]: 1060 : if (vch.back() & 0x80) # 173 : 416 : return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); # 174 : : # 175 : 644 : return result; # 176 : 1060 : } # 177 : : # 178 : : int64_t m_value; # 179 : : }; # 180 : : # 181 : : # 182 : : #endif // BITCOIN_TEST_SCRIPTNUM10_H