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 [ + - - - ]: 72 : 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 : 18603 : explicit CScriptNum10(const int64_t& n)
30 : 18603 : {
31 [ + + + - : 7371 : m_value = n;
+ + + - +
- + - ]
32 : : }
33 : :
34 : : static const size_t nDefaultMaxNumSize = 4;
35 : :
36 : 630 : 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 [ + - ]: 144 : 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 : 558 : }
62 : :
63 : 1404 : inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
64 : 1404 : inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; }
65 : 1404 : inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; }
66 : 1404 : inline bool operator< (const int64_t& rhs) const { return m_value < rhs; }
67 : 1404 : inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; }
68 : 1404 : 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 : 14598 : int getint() const
114 : : {
115 [ + + + + : 14598 : if (m_value > std::numeric_limits<int>::max())
+ + + + ]
116 : : return std::numeric_limits<int>::max();
117 [ + + + + : 13373 : else if (m_value < std::numeric_limits<int>::min())
+ + + + ]
118 : : return std::numeric_limits<int>::min();
119 : 12499 : return m_value;
120 : : }
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 [ + + + - ]: 6454 : result.push_back(neg ? 0x80 : 0);
154 [ + + ]: 7573 : else if (neg)
155 : 3358 : result.back() |= 0x80;
156 : :
157 : 11743 : return result;
158 : 11743 : }
159 : :
160 : : private:
161 : 558 : static int64_t set_vch(const std::vector<unsigned char>& vch)
162 : : {
163 [ + + ]: 558 : if (vch.empty())
164 : : 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 : : return result;
176 : : }
177 : :
178 : : int64_t m_value;
179 : : };
180 : :
181 : :
182 : : #endif // BITCOIN_TEST_SCRIPTNUM10_H
|