]>
Commit | Line | Data |
---|---|---|
8bd66202 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2013 The Bitcoin Core developers |
78253fcb | 3 | // Distributed under the MIT software license, see the accompanying |
3a25a2b9 | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
51ed9ec9 | 5 | |
84738627 PJ |
6 | #ifndef BITCOIN_TEST_BIGNUM_H |
7 | #define BITCOIN_TEST_BIGNUM_H | |
8bd66202 | 8 | |
ccc84e09 | 9 | #include <algorithm> |
017abaf6 | 10 | #include <cassert> |
ccc84e09 | 11 | #include <limits> |
8bd66202 | 12 | #include <stdexcept> |
51ed9ec9 | 13 | #include <stdint.h> |
f25e3adf | 14 | #include <string> |
8bd66202 | 15 | #include <vector> |
8bd66202 | 16 | |
51ed9ec9 | 17 | #include <openssl/bn.h> |
8bd66202 GA |
18 | |
19 | class bignum_error : public std::runtime_error | |
20 | { | |
21 | public: | |
22 | explicit bignum_error(const std::string& str) : std::runtime_error(str) {} | |
23 | }; | |
24 | ||
25 | ||
7e05b972 | 26 | /** C++ wrapper for BIGNUM (OpenSSL bignum) */ |
fa318aa9 | 27 | class CBigNum |
8bd66202 | 28 | { |
fa318aa9 | 29 | BIGNUM* bn; |
8bd66202 GA |
30 | public: |
31 | CBigNum() | |
32 | { | |
fa318aa9 | 33 | bn = BN_new(); |
017abaf6 | 34 | assert(bn); |
8bd66202 GA |
35 | } |
36 | ||
37 | CBigNum(const CBigNum& b) | |
38 | { | |
fa318aa9 | 39 | bn = BN_new(); |
017abaf6 | 40 | assert(bn); |
fa318aa9 | 41 | if (!BN_copy(bn, b.bn)) |
8bd66202 | 42 | { |
fa318aa9 | 43 | BN_clear_free(bn); |
5262fde0 | 44 | throw bignum_error("CBigNum::CBigNum(const CBigNum&): BN_copy failed"); |
8bd66202 GA |
45 | } |
46 | } | |
47 | ||
48 | CBigNum& operator=(const CBigNum& b) | |
49 | { | |
fa318aa9 | 50 | if (!BN_copy(bn, b.bn)) |
5262fde0 | 51 | throw bignum_error("CBigNum::operator=: BN_copy failed"); |
8bd66202 GA |
52 | return (*this); |
53 | } | |
54 | ||
55 | ~CBigNum() | |
56 | { | |
fa318aa9 | 57 | BN_clear_free(bn); |
8bd66202 GA |
58 | } |
59 | ||
017abaf6 | 60 | CBigNum(long long n) { bn = BN_new(); assert(bn); setint64(n); } |
8bd66202 GA |
61 | |
62 | explicit CBigNum(const std::vector<unsigned char>& vch) | |
63 | { | |
fa318aa9 | 64 | bn = BN_new(); |
017abaf6 | 65 | assert(bn); |
8bd66202 GA |
66 | setvch(vch); |
67 | } | |
68 | ||
8bd66202 GA |
69 | int getint() const |
70 | { | |
fa318aa9 JG |
71 | BN_ULONG n = BN_get_word(bn); |
72 | if (!BN_is_negative(bn)) | |
63c17613 | 73 | return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n); |
8bd66202 | 74 | else |
63c17613 | 75 | return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n); |
8bd66202 GA |
76 | } |
77 | ||
51ed9ec9 | 78 | void setint64(int64_t sn) |
8bd66202 | 79 | { |
fe78c9ae | 80 | unsigned char pch[sizeof(sn) + 6]; |
8bd66202 | 81 | unsigned char* p = pch + 4; |
fe78c9ae | 82 | bool fNegative; |
51ed9ec9 | 83 | uint64_t n; |
fe78c9ae | 84 | |
51ed9ec9 | 85 | if (sn < (int64_t)0) |
8bd66202 | 86 | { |
f0bf5fb2 | 87 | // Since the minimum signed integer cannot be represented as positive so long as its type is signed, |
88 | // and it's not well-defined what happens if you make it unsigned before negating it, | |
89 | // we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate | |
0f5a2a82 LD |
90 | n = -(sn + 1); |
91 | ++n; | |
8bd66202 | 92 | fNegative = true; |
fe78c9ae RC |
93 | } else { |
94 | n = sn; | |
95 | fNegative = false; | |
8bd66202 | 96 | } |
fe78c9ae | 97 | |
8bd66202 GA |
98 | bool fLeadingZeroes = true; |
99 | for (int i = 0; i < 8; i++) | |
100 | { | |
101 | unsigned char c = (n >> 56) & 0xff; | |
102 | n <<= 8; | |
103 | if (fLeadingZeroes) | |
104 | { | |
105 | if (c == 0) | |
106 | continue; | |
107 | if (c & 0x80) | |
108 | *p++ = (fNegative ? 0x80 : 0); | |
109 | else if (fNegative) | |
110 | c |= 0x80; | |
111 | fLeadingZeroes = false; | |
112 | } | |
113 | *p++ = c; | |
114 | } | |
115 | unsigned int nSize = p - (pch + 4); | |
116 | pch[0] = (nSize >> 24) & 0xff; | |
117 | pch[1] = (nSize >> 16) & 0xff; | |
118 | pch[2] = (nSize >> 8) & 0xff; | |
119 | pch[3] = (nSize) & 0xff; | |
fa318aa9 | 120 | BN_mpi2bn(pch, p - pch, bn); |
8bd66202 GA |
121 | } |
122 | ||
8bd66202 GA |
123 | void setvch(const std::vector<unsigned char>& vch) |
124 | { | |
125 | std::vector<unsigned char> vch2(vch.size() + 4); | |
126 | unsigned int nSize = vch.size(); | |
a9d3af88 DH |
127 | // BIGNUM's byte stream format expects 4 bytes of |
128 | // big endian size data info at the front | |
8bd66202 GA |
129 | vch2[0] = (nSize >> 24) & 0xff; |
130 | vch2[1] = (nSize >> 16) & 0xff; | |
131 | vch2[2] = (nSize >> 8) & 0xff; | |
132 | vch2[3] = (nSize >> 0) & 0xff; | |
a9d3af88 | 133 | // swap data to big endian |
8bd66202 | 134 | reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); |
fa318aa9 | 135 | BN_mpi2bn(&vch2[0], vch2.size(), bn); |
8bd66202 GA |
136 | } |
137 | ||
138 | std::vector<unsigned char> getvch() const | |
139 | { | |
fa318aa9 | 140 | unsigned int nSize = BN_bn2mpi(bn, NULL); |
a06113b0 | 141 | if (nSize <= 4) |
8bd66202 GA |
142 | return std::vector<unsigned char>(); |
143 | std::vector<unsigned char> vch(nSize); | |
fa318aa9 | 144 | BN_bn2mpi(bn, &vch[0]); |
8bd66202 GA |
145 | vch.erase(vch.begin(), vch.begin() + 4); |
146 | reverse(vch.begin(), vch.end()); | |
147 | return vch; | |
148 | } | |
149 | ||
fa318aa9 | 150 | friend inline const CBigNum operator+(const CBigNum& a, const CBigNum& b); |
8bd66202 | 151 | friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); |
fa318aa9 JG |
152 | friend inline const CBigNum operator-(const CBigNum& a); |
153 | friend inline bool operator==(const CBigNum& a, const CBigNum& b); | |
154 | friend inline bool operator!=(const CBigNum& a, const CBigNum& b); | |
155 | friend inline bool operator<=(const CBigNum& a, const CBigNum& b); | |
156 | friend inline bool operator>=(const CBigNum& a, const CBigNum& b); | |
157 | friend inline bool operator<(const CBigNum& a, const CBigNum& b); | |
158 | friend inline bool operator>(const CBigNum& a, const CBigNum& b); | |
8bd66202 GA |
159 | }; |
160 | ||
161 | ||
162 | ||
163 | inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) | |
164 | { | |
165 | CBigNum r; | |
fa318aa9 | 166 | if (!BN_add(r.bn, a.bn, b.bn)) |
5262fde0 | 167 | throw bignum_error("CBigNum::operator+: BN_add failed"); |
8bd66202 GA |
168 | return r; |
169 | } | |
170 | ||
171 | inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) | |
172 | { | |
173 | CBigNum r; | |
fa318aa9 | 174 | if (!BN_sub(r.bn, a.bn, b.bn)) |
5262fde0 | 175 | throw bignum_error("CBigNum::operator-: BN_sub failed"); |
8bd66202 GA |
176 | return r; |
177 | } | |
178 | ||
179 | inline const CBigNum operator-(const CBigNum& a) | |
180 | { | |
181 | CBigNum r(a); | |
fa318aa9 | 182 | BN_set_negative(r.bn, !BN_is_negative(r.bn)); |
8bd66202 GA |
183 | return r; |
184 | } | |
185 | ||
fa318aa9 JG |
186 | inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) == 0); } |
187 | inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) != 0); } | |
188 | inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) <= 0); } | |
189 | inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) >= 0); } | |
190 | inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) < 0); } | |
191 | inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) > 0); } | |
223b6f1b | 192 | |
84738627 | 193 | #endif // BITCOIN_TEST_BIGNUM_H |