Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2020 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 144 : 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 51948 : explicit CScriptNum10(const int64_t& n) 30 25974 : { 31 25974 : m_value = n; 32 51948 : } 33 : 34 : static const size_t nDefaultMaxNumSize = 4; 35 : 36 1260 : explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal, 37 : const size_t nMaxNumSize = nDefaultMaxNumSize) 38 630 : { 39 630 : if (vch.size() > nMaxNumSize) { 40 72 : throw scriptnum10_error("script number overflow"); 41 : } 42 558 : 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 : } 58 : } 59 : } 60 558 : m_value = set_vch(vch); 61 1260 : } 62 : 63 5616 : inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } 64 5616 : inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } 65 5616 : inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } 66 5616 : inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } 67 5616 : inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } 68 5616 : inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } 69 : 70 5616 : inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); } 71 5616 : inline bool operator!=(const CScriptNum10& rhs) const { return operator!=(rhs.m_value); } 72 5616 : inline bool operator<=(const CScriptNum10& rhs) const { return operator<=(rhs.m_value); } 73 5616 : inline bool operator< (const CScriptNum10& rhs) const { return operator< (rhs.m_value); } 74 5616 : inline bool operator>=(const CScriptNum10& rhs) const { return operator>=(rhs.m_value); } 75 5616 : inline bool operator> (const CScriptNum10& rhs) const { return operator> (rhs.m_value); } 76 : 77 4212 : inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);} 78 5616 : inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);} 79 4212 : inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); } 80 5616 : inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); } 81 : 82 : inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); } 83 : inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); } 84 : 85 1404 : inline CScriptNum10 operator-() const 86 : { 87 1404 : assert(m_value != std::numeric_limits<int64_t>::min()); 88 1404 : return CScriptNum10(-m_value); 89 : } 90 : 91 : inline CScriptNum10& operator=( const int64_t& rhs) 92 : { 93 : m_value = rhs; 94 : return *this; 95 : } 96 : 97 : inline CScriptNum10& operator+=( const int64_t& rhs) 98 : { 99 : assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || 100 : (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)); 101 : m_value += rhs; 102 : return *this; 103 : } 104 : 105 : inline CScriptNum10& operator-=( const int64_t& rhs) 106 : { 107 : assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || 108 : (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)); 109 : m_value -= rhs; 110 : return *this; 111 : } 112 : 113 14949 : int getint() const 114 : { 115 14949 : if (m_value > std::numeric_limits<int>::max()) 116 1225 : return std::numeric_limits<int>::max(); 117 13724 : else if (m_value < std::numeric_limits<int>::min()) 118 874 : return std::numeric_limits<int>::min(); 119 12850 : return m_value; 120 14949 : } 121 : 122 14175 : std::vector<unsigned char> getvch() const 123 : { 124 14175 : return serialize(m_value); 125 : } 126 : 127 14175 : static std::vector<unsigned char> serialize(const int64_t& value) 128 : { 129 14175 : if(value == 0) 130 2432 : return std::vector<unsigned char>(); 131 : 132 11743 : std::vector<unsigned char> result; 133 11743 : const bool neg = value < 0; 134 11743 : uint64_t absvalue = neg ? -value : value; 135 : 136 41047 : while(absvalue) 137 : { 138 29304 : result.push_back(absvalue & 0xff); 139 29304 : absvalue >>= 8; 140 : } 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 11743 : if (result.back() & 0x80) 153 4170 : result.push_back(neg ? 0x80 : 0); 154 7573 : else if (neg) 155 3358 : result.back() |= 0x80; 156 : 157 11743 : return result; 158 14175 : } 159 : 160 : private: 161 558 : static int64_t set_vch(const std::vector<unsigned char>& vch) 162 : { 163 558 : if (vch.empty()) 164 28 : return 0; 165 : 166 : int64_t result = 0; 167 1780 : for (size_t i = 0; i != vch.size(); ++i) 168 1250 : 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 530 : if (vch.back() & 0x80) 173 208 : return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1))))); 174 : 175 322 : return result; 176 558 : } 177 : 178 : int64_t m_value; 179 : }; 180 : 181 : 182 : #endif // BITCOIN_TEST_BIGNUM_H