Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-present 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 <cassert>
10 : : #include <cstdint>
11 : : #include <limits>
12 : : #include <stdexcept>
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 [ + + + + : 11232 : inline auto operator<=>(const int64_t& rhs) const { return m_value <=> rhs; }
+ + + + +
+ + + + +
+ + ]
65 : :
66 [ + - + - : 11232 : inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }
+ - + - +
- + - + -
+ - ]
67 [ + - + - : 33696 : inline auto operator<=>(const CScriptNum10& rhs) const { return operator<=>(rhs.m_value); }
+ - + - -
+ - + - +
- + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + ]
68 : :
69 : 4212 : inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);}
70 : 5616 : inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);}
71 [ + - + - : 4212 : inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); }
+ - ]
72 [ + - + - : 5616 : inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); }
+ - + - ]
73 : :
74 : : inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); }
75 : : inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); }
76 : :
77 : 1404 : inline CScriptNum10 operator-() const
78 : : {
79 [ - + ]: 1404 : assert(m_value != std::numeric_limits<int64_t>::min());
80 : 1404 : return CScriptNum10(-m_value);
81 : : }
82 : :
83 : : inline CScriptNum10& operator=( const int64_t& rhs)
84 : : {
85 : : m_value = rhs;
86 : : return *this;
87 : : }
88 : :
89 : : inline CScriptNum10& operator+=( const int64_t& rhs)
90 : : {
91 : : assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
92 : : (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
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>::min() + rhs) ||
100 : : (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
101 : : m_value -= rhs;
102 : : return *this;
103 : : }
104 : :
105 : 14598 : int getint() const
106 : : {
107 [ + + + + : 14598 : if (m_value > std::numeric_limits<int>::max())
+ + + + ]
108 : : return std::numeric_limits<int>::max();
109 [ + + + + : 13373 : else if (m_value < std::numeric_limits<int>::min())
+ + + + ]
110 : : return std::numeric_limits<int>::min();
111 : 12499 : return m_value;
112 : : }
113 : :
114 : 14175 : std::vector<unsigned char> getvch() const
115 : : {
116 [ + - ]: 14175 : return serialize(m_value);
117 : : }
118 : :
119 : 14175 : static std::vector<unsigned char> serialize(const int64_t& value)
120 : : {
121 [ + + ]: 14175 : if(value == 0)
122 : 2432 : return std::vector<unsigned char>();
123 : :
124 : 11743 : std::vector<unsigned char> result;
125 : 11743 : const bool neg = value < 0;
126 [ + + ]: 11743 : uint64_t absvalue = neg ? -value : value;
127 : :
128 [ + + ]: 41047 : while(absvalue)
129 : : {
130 [ + - ]: 29304 : result.push_back(absvalue & 0xff);
131 : 29304 : absvalue >>= 8;
132 : : }
133 : :
134 : : // - If the most significant byte is >= 0x80 and the value is positive, push a
135 : : // new zero-byte to make the significant byte < 0x80 again.
136 : :
137 : : // - If the most significant byte is >= 0x80 and the value is negative, push a
138 : : // new 0x80 byte that will be popped off when converting to an integral.
139 : :
140 : : // - If the most significant byte is < 0x80 and the value is negative, add
141 : : // 0x80 to it, since it will be subtracted and interpreted as a negative when
142 : : // converting to an integral.
143 : :
144 [ + + ]: 11743 : if (result.back() & 0x80)
145 [ + + + - ]: 6454 : result.push_back(neg ? 0x80 : 0);
146 [ + + ]: 7573 : else if (neg)
147 : 3358 : result.back() |= 0x80;
148 : :
149 : 11743 : return result;
150 : 11743 : }
151 : :
152 : : private:
153 : 558 : static int64_t set_vch(const std::vector<unsigned char>& vch)
154 : : {
155 [ + + ]: 558 : if (vch.empty())
156 : : return 0;
157 : :
158 : : int64_t result = 0;
159 [ - + + + ]: 1780 : for (size_t i = 0; i != vch.size(); ++i)
160 : 1250 : result |= static_cast<int64_t>(vch[i]) << 8*i;
161 : :
162 : : // If the input vector's most significant byte is 0x80, remove it from
163 : : // the result's msb and return a negative.
164 [ + + ]: 530 : if (vch.back() & 0x80)
165 : 208 : return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
166 : :
167 : : return result;
168 : : }
169 : :
170 : : int64_t m_value;
171 : : };
172 : :
173 : :
174 : : #endif // BITCOIN_TEST_SCRIPTNUM10_H
|