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