5 CAutoBN_CTX::CAutoBN_CTX() {
8 throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
11 CAutoBN_CTX::~CAutoBN_CTX() {
20 CBigNum::CBigNum(const CBigNum &b) {
21 BIGNUM *dup = BN_dup(b.bn);
23 throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_dup failed");
28 CBigNum &CBigNum::operator=(const CBigNum &b) {
29 BIGNUM *dup = BN_dup(b.bn);
31 throw bignum_error("CBigNum::operator= : BN_dup failed");
37 CBigNum::CBigNum(const BIGNUM *bnp) {
38 BIGNUM *dup = BN_dup(bnp);
40 throw bignum_error("CBigNum::CBigNum(const BIGNUM*) : BN_dup failed");
49 CBigNum::CBigNum(uint256 n) { bn = BN_new(); setuint256(n); }
51 void CBigNum::setuint32(uint32_t n) {
52 if (!BN_set_word(bn, n))
53 throw bignum_error("CBigNum conversion from uint32_t : BN_set_word failed");
56 uint32_t CBigNum::getuint32() const {
57 return BN_get_word(bn);
60 int32_t CBigNum::getint32() const {
61 uint64_t n = BN_get_word(bn);
62 if (!BN_is_negative(bn))
63 return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::max() : (int32_t)n);
65 return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::min() : -(int32_t)n);
68 void CBigNum::setint64(int64_t sn) {
69 uint8_t pch[sizeof(sn) + 6];
76 // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
85 bool fLeadingZeroes = true;
86 for (int i = 0; i < 8; i++)
88 uint8_t c = (n >> 56) & 0xff;
95 *p++ = (fNegative ? 0x80 : 0);
98 fLeadingZeroes = false;
102 uint32_t nSize = (uint32_t) (p - (pch + 4));
103 pch[0] = (nSize >> 24) & 0xff;
104 pch[1] = (nSize >> 16) & 0xff;
105 pch[2] = (nSize >> 8) & 0xff;
106 pch[3] = (nSize) & 0xff;
107 BN_mpi2bn(pch, (int)(p - pch), bn);
110 uint64_t CBigNum::getuint64() {
111 size_t nSize = BN_bn2mpi(bn, nullptr);
114 std::vector<uint8_t> vch(nSize);
115 BN_bn2mpi(bn, &vch[0]);
119 for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
120 ((uint8_t*)&n)[i] = vch[j];
124 void CBigNum::setuint64(uint64_t n) {
125 // Use BN_set_word if word size is sufficient for uint64_t
126 if (check(sizeof(n) <= sizeof(BN_ULONG)))
128 if (!BN_set_word(bn, (BN_ULONG)n))
129 throw bignum_error("CBigNum conversion from uint64_t : BN_set_word failed");
133 uint8_t pch[sizeof(n) + 6];
134 uint8_t* p = pch + 4;
135 bool fLeadingZeroes = true;
136 for (int i = 0; i < 8; i++)
138 uint8_t c = (n >> 56) & 0xff;
146 fLeadingZeroes = false;
150 uint32_t nSize = (uint32_t) (p - (pch + 4));
151 pch[0] = (nSize >> 24) & 0xff;
152 pch[1] = (nSize >> 16) & 0xff;
153 pch[2] = (nSize >> 8) & 0xff;
154 pch[3] = (nSize) & 0xff;
155 BN_mpi2bn(pch, (int)(p - pch), bn);
158 void CBigNum::setuint160(uint160 n) {
159 uint8_t pch[sizeof(n) + 6];
160 uint8_t* p = pch + 4;
161 bool fLeadingZeroes = true;
162 uint8_t* pbegin = (uint8_t*)&n;
163 uint8_t* psrc = pbegin + sizeof(n);
164 while (psrc != pbegin)
166 uint8_t c = *(--psrc);
173 fLeadingZeroes = false;
177 uint32_t nSize = (uint32_t) (p - (pch + 4));
178 pch[0] = (nSize >> 24) & 0xff;
179 pch[1] = (nSize >> 16) & 0xff;
180 pch[2] = (nSize >> 8) & 0xff;
181 pch[3] = (nSize >> 0) & 0xff;
182 BN_mpi2bn(pch, (int) (p - pch), bn);
185 uint160 CBigNum::getuint160() const {
186 unsigned int nSize = BN_bn2mpi(bn, nullptr);
189 std::vector<uint8_t> vch(nSize);
190 BN_bn2mpi(bn, &vch[0]);
194 for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
195 ((uint8_t*)&n)[i] = vch[j];
199 void CBigNum::setuint256(uint256 n) {
200 uint8_t pch[sizeof(n) + 6];
201 uint8_t* p = pch + 4;
202 bool fLeadingZeroes = true;
203 uint8_t* pbegin = (uint8_t*)&n;
204 uint8_t* psrc = pbegin + sizeof(n);
205 while (psrc != pbegin)
207 uint8_t c = *(--psrc);
214 fLeadingZeroes = false;
218 uint32_t nSize = (uint32_t) (p - (pch + 4));
219 pch[0] = (nSize >> 24) & 0xff;
220 pch[1] = (nSize >> 16) & 0xff;
221 pch[2] = (nSize >> 8) & 0xff;
222 pch[3] = (nSize >> 0) & 0xff;
223 BN_mpi2bn(pch, (int) (p - pch), bn);
226 uint256 CBigNum::getuint256() const {
227 unsigned int nSize = BN_bn2mpi(bn, nullptr);
230 std::vector<uint8_t> vch(nSize);
231 BN_bn2mpi(bn, &vch[0]);
235 for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
236 ((uint8_t*)&n)[i] = vch[j];
240 void CBigNum::setBytes(const std::vector<uint8_t> &vchBytes) {
241 BN_bin2bn(&vchBytes[0], (int) vchBytes.size(), bn);
244 std::vector<uint8_t> CBigNum::getBytes() const {
245 int nBytes = BN_num_bytes(bn);
247 std::vector<uint8_t> vchBytes(nBytes);
249 int n = BN_bn2bin(bn, &vchBytes[0]);
251 throw bignum_error("CBigNum::getBytes : BN_bn2bin failed");
257 void CBigNum::setvch(const std::vector<uint8_t> &vch) {
258 std::vector<uint8_t> vch2(vch.size() + 4);
259 uint32_t nSize = (uint32_t) vch.size();
260 // BIGNUM's byte stream format expects 4 bytes of
261 // big endian size data info at the front
262 vch2[0] = (nSize >> 24) & 0xff;
263 vch2[1] = (nSize >> 16) & 0xff;
264 vch2[2] = (nSize >> 8) & 0xff;
265 vch2[3] = (nSize >> 0) & 0xff;
266 // swap data to big endian
267 std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
268 BN_mpi2bn(&vch2[0], (int) vch2.size(), bn);
271 std::vector<uint8_t> CBigNum::getvch() const {
272 unsigned int nSize = BN_bn2mpi(bn, nullptr);
275 std::vector<uint8_t> vch(nSize);
276 BN_bn2mpi(bn, &vch[0]);
277 vch.erase(vch.begin(), vch.begin() + 4);
278 std::reverse(vch.begin(), vch.end());
282 CBigNum &CBigNum::SetCompact(uint32_t nCompact) {
283 uint32_t nSize = nCompact >> 24;
284 std::vector<uint8_t> vch(4 + nSize);
286 if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
287 if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
288 if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
289 BN_mpi2bn(&vch[0], (int) vch.size(), bn);
293 uint32_t CBigNum::GetCompact() const {
294 uint32_t nSize = BN_bn2mpi(bn, nullptr);
295 std::vector<uint8_t> vch(nSize);
297 BN_bn2mpi(bn, &vch[0]);
298 uint32_t nCompact = nSize << 24;
299 if (nSize >= 1) nCompact |= (vch[4] << 16);
300 if (nSize >= 2) nCompact |= (vch[5] << 8);
301 if (nSize >= 3) nCompact |= (vch[6] << 0);
305 void CBigNum::SetHex(const std::string &str) {
307 const char* psz = str.c_str();
308 while (isspace(*psz))
310 bool fNegative = false;
316 if (psz[0] == '0' && tolower(psz[1]) == 'x')
318 while (isspace(*psz))
321 // hex string to bignum
322 static const signed char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
324 while (isxdigit(*psz))
327 int n = phexdigit[(uint8_t)*psz++];
334 std::string CBigNum::ToString(int nBase) const {
336 CBigNum bnBase = nBase;
340 BN_set_negative(bn.bn, false);
343 if (BN_cmp(bn.bn, bn0.bn) == 0)
345 while (BN_cmp(bn.bn, bn0.bn) > 0)
347 if (!BN_div(dv.bn, rem.bn, bn.bn, bnBase.bn, pctx))
348 throw bignum_error("CBigNum::ToString() : BN_div failed");
350 uint32_t c = rem.getuint32();
351 str += "0123456789abcdef"[c];
353 if (BN_is_negative(bn.bn))
355 std::reverse(str.begin(), str.end());
359 bool CBigNum::operator!() const {
360 return BN_is_zero(bn);
363 CBigNum &CBigNum::operator+=(const CBigNum &b) {
364 if (!BN_add(bn, bn, b.bn))
365 throw bignum_error("CBigNum::operator+= : BN_add failed");
369 CBigNum &CBigNum::operator-=(const CBigNum &b) {
374 CBigNum &CBigNum::operator*=(const CBigNum &b) {
376 if (!BN_mul(bn, bn, b.bn, pctx))
377 throw bignum_error("CBigNum::operator*= : BN_mul failed");
381 CBigNum &CBigNum::operator/=(const CBigNum &b) {
386 CBigNum &CBigNum::operator%=(const CBigNum &b) {
391 CBigNum &CBigNum::operator<<=(unsigned int shift) {
392 if (!BN_lshift(bn, bn, shift))
393 throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
397 CBigNum &CBigNum::operator>>=(unsigned int shift) {
398 // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
399 // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
402 if (BN_cmp(a.bn, bn) > 0)
408 if (!BN_rshift(bn, bn, shift))
409 throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
413 CBigNum &CBigNum::operator++() {
415 if (!BN_add(bn, bn, BN_value_one()))
416 throw bignum_error("CBigNum::operator++ : BN_add failed");
420 CBigNum &CBigNum::operator--() {
423 if (!BN_sub(r.bn, bn, BN_value_one()))
424 throw bignum_error("CBigNum::operator-- : BN_sub failed");
429 const CBigNum CBigNum::operator--(int) {
431 const CBigNum ret = *this;
436 const CBigNum CBigNum::operator++(int) {
438 const CBigNum ret = *this;