6 #ifndef BITCOIN_BIGNUM_H
7 #define BITCOIN_BIGNUM_H
18 #include <openssl/bn.h>
33 BN_CTX*
operator=(BN_CTX* pnew) {
return pctx = pnew; }
40 throw bignum_error(
"CAutoBN_CTX : BN_CTX_new() returned NULL");
49 operator BN_CTX*() {
return pctx; }
68 if (!BN_copy(
this, &b))
71 throw bignum_error(
"CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
77 if (!BN_copy(
this, &b))
78 throw bignum_error(
"CBigNum::operator= : BN_copy failed");
100 explicit CBigNum(
const std::vector<unsigned char>& vch)
108 if (!BN_set_word(
this, n))
109 throw bignum_error(
"CBigNum conversion from unsigned long : BN_set_word failed");
114 return BN_get_word(
this);
119 return BN_get_word(
this);
124 BN_ULONG n = BN_get_word(
this);
125 if (!BN_is_negative(
this))
126 return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
128 return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(
int)n);
133 unsigned char pch[
sizeof(sn) + 6];
134 unsigned char* p = pch + 4;
151 bool fLeadingZeroes =
true;
152 for (
int i = 0; i < 8; i++)
154 unsigned char c = (n >> 56) & 0xff;
161 *p++ = (fNegative ? 0x80 : 0);
164 fLeadingZeroes =
false;
168 unsigned int nSize = p - (pch + 4);
169 pch[0] = (nSize >> 24) & 0xff;
170 pch[1] = (nSize >> 16) & 0xff;
171 pch[2] = (nSize >> 8) & 0xff;
172 pch[3] = (nSize) & 0xff;
173 BN_mpi2bn(pch, p - pch,
this);
178 unsigned char pch[
sizeof(n) + 6];
179 unsigned char* p = pch + 4;
180 bool fLeadingZeroes =
true;
181 for (
int i = 0; i < 8; i++)
183 unsigned char c = (n >> 56) & 0xff;
191 fLeadingZeroes =
false;
195 unsigned int nSize = p - (pch + 4);
196 pch[0] = (nSize >> 24) & 0xff;
197 pch[1] = (nSize >> 16) & 0xff;
198 pch[2] = (nSize >> 8) & 0xff;
199 pch[3] = (nSize) & 0xff;
200 BN_mpi2bn(pch, p - pch,
this);
205 unsigned char pch[
sizeof(n) + 6];
206 unsigned char* p = pch + 4;
207 bool fLeadingZeroes =
true;
208 unsigned char* pbegin = (
unsigned char*)&n;
209 unsigned char* psrc = pbegin +
sizeof(n);
210 while (psrc != pbegin)
212 unsigned char c = *(--psrc);
219 fLeadingZeroes =
false;
223 unsigned int nSize = p - (pch + 4);
224 pch[0] = (nSize >> 24) & 0xff;
225 pch[1] = (nSize >> 16) & 0xff;
226 pch[2] = (nSize >> 8) & 0xff;
227 pch[3] = (nSize >> 0) & 0xff;
228 BN_mpi2bn(pch, p - pch,
this);
233 unsigned int nSize = BN_bn2mpi(
this, NULL);
236 std::vector<unsigned char> vch(nSize);
237 BN_bn2mpi(
this, &vch[0]);
241 for (
unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
242 ((
unsigned char*)&n)[i] = vch[j];
246 void setvch(
const std::vector<unsigned char>& vch)
248 std::vector<unsigned char> vch2(vch.size() + 4);
249 unsigned int nSize = vch.size();
252 vch2[0] = (nSize >> 24) & 0xff;
253 vch2[1] = (nSize >> 16) & 0xff;
254 vch2[2] = (nSize >> 8) & 0xff;
255 vch2[3] = (nSize >> 0) & 0xff;
257 reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
258 BN_mpi2bn(&vch2[0], vch2.size(),
this);
261 std::vector<unsigned char>
getvch()
const
263 unsigned int nSize = BN_bn2mpi(
this, NULL);
265 return std::vector<unsigned char>();
266 std::vector<unsigned char> vch(nSize);
267 BN_bn2mpi(
this, &vch[0]);
268 vch.erase(vch.begin(), vch.begin() + 4);
269 reverse(vch.begin(), vch.end());
297 unsigned int nSize = nCompact >> 24;
298 bool fNegative =(nCompact & 0x00800000) != 0;
299 unsigned int nWord = nCompact & 0x007fffff;
302 nWord >>= 8*(3-nSize);
303 BN_set_word(
this, nWord);
307 BN_set_word(
this, nWord);
308 BN_lshift(
this,
this, 8*(nSize-3));
310 BN_set_negative(
this, fNegative);
316 unsigned int nSize = BN_num_bytes(
this);
317 unsigned int nCompact = 0;
319 nCompact = BN_get_word(
this) << 8*(3-nSize);
323 BN_rshift(&bn,
this, 8*(nSize-3));
324 nCompact = BN_get_word(&bn);
328 if (nCompact & 0x00800000)
333 nCompact |= nSize << 24;
334 nCompact |= (BN_is_negative(
this) ? 0x00800000 : 0);
341 const char* psz = str.c_str();
342 while (isspace(*psz))
344 bool fNegative =
false;
350 if (psz[0] ==
'0' && tolower(psz[1]) ==
'x')
352 while (isspace(*psz))
375 BN_set_negative(&bn,
false);
378 if (BN_cmp(&bn, &bn0) == 0)
380 while (BN_cmp(&bn, &bn0) > 0)
382 if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
383 throw bignum_error(
"CBigNum::ToString() : BN_div failed");
386 str +=
"0123456789abcdef"[c];
388 if (BN_is_negative(
this))
390 reverse(str.begin(), str.end());
404 template<
typename Stream>
410 template<
typename Stream>
413 std::vector<unsigned char> vch;
421 return BN_is_zero(
this);
426 if (!BN_add(
this,
this, &b))
427 throw bignum_error(
"CBigNum::operator+= : BN_add failed");
440 if (!BN_mul(
this,
this, &b, pctx))
441 throw bignum_error(
"CBigNum::operator*= : BN_mul failed");
459 if (!BN_lshift(
this,
this, shift))
460 throw bignum_error(
"CBigNum:operator<<= : BN_lshift failed");
470 if (BN_cmp(&a,
this) > 0)
476 if (!BN_rshift(
this,
this, shift))
477 throw bignum_error(
"CBigNum:operator>>= : BN_rshift failed");
485 if (!BN_add(
this,
this, BN_value_one()))
486 throw bignum_error(
"CBigNum::operator++ : BN_add failed");
502 if (!BN_sub(&r,
this, BN_value_one()))
503 throw bignum_error(
"CBigNum::operator-- : BN_sub failed");
527 if (!BN_add(&r, &a, &b))
528 throw bignum_error(
"CBigNum::operator+ : BN_add failed");
535 if (!BN_sub(&r, &a, &b))
536 throw bignum_error(
"CBigNum::operator- : BN_sub failed");
543 BN_set_negative(&r, !BN_is_negative(&r));
551 if (!BN_mul(&r, &a, &b, pctx))
552 throw bignum_error(
"CBigNum::operator* : BN_mul failed");
560 if (!BN_div(&r, NULL, &a, &b, pctx))
561 throw bignum_error(
"CBigNum::operator/ : BN_div failed");
569 if (!BN_mod(&r, &a, &b, pctx))
570 throw bignum_error(
"CBigNum::operator% : BN_div failed");
577 if (!BN_lshift(&r, &a, shift))
578 throw bignum_error(
"CBigNum:operator<< : BN_lshift failed");
const CBigNum operator-(const CBigNum &a, const CBigNum &b)
bool operator!=(const CBigNum &a, const CBigNum &b)
bool operator==(const CBigNum &a, const CBigNum &b)
uint256 getuint256() const
bool operator<(const CBigNum &a, const CBigNum &b)
bignum_error(const std::string &str)
CBigNum & operator>>=(unsigned int shift)
std::string GetHex() const
CBigNum & operator/=(const CBigNum &b)
const CBigNum operator%(const CBigNum &a, const CBigNum &b)
void setuint256(uint256 n)
CBigNum & operator<<=(unsigned int shift)
unsigned long getulong() const
RAII encapsulated BN_CTX (OpenSSL bignum context)
void setulong(unsigned long n)
CBigNum & operator%=(const CBigNum &b)
const CBigNum operator/(const CBigNum &a, const CBigNum &b)
const CBigNum operator<<(const CBigNum &a, unsigned int shift)
BN_CTX * operator=(BN_CTX *pnew)
const CBigNum operator*(const CBigNum &a, const CBigNum &b)
void Unserialize(Stream &s, int nType=0, int nVersion=PROTOCOL_VERSION)
signed char HexDigit(char c)
CBigNum & SetCompact(unsigned int nCompact)
bool operator>(const CBigNum &a, const CBigNum &b)
CBigNum(const std::vector< unsigned char > &vch)
unsigned int GetSerializeSize(char a, int, int=0)
const CBigNum operator>>(const CBigNum &a, unsigned int shift)
const CBigNum operator--(int)
CBigNum & operator*=(const CBigNum &b)
bool operator<=(const CBigNum &a, const CBigNum &b)
const CBigNum operator+(const CBigNum &a, const CBigNum &b)
unsigned int getuint() const
C++ wrapper for BIGNUM (OpenSSL bignum)
std::vector< unsigned char > getvch() const
friend const CBigNum operator%(const CBigNum &a, const CBigNum &b)
Errors thrown by the bignum class.
unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
bool operator>=(const CBigNum &a, const CBigNum &b)
CBigNum & operator-=(const CBigNum &b)
void SetHex(const std::string &str)
void setuint64(uint64_t n)
void setvch(const std::vector< unsigned char > &vch)
CBigNum(unsigned short n)
static const int PROTOCOL_VERSION
void setint64(int64_t sn)
CBigNum & operator=(const CBigNum &b)
unsigned int GetCompact() const
CBigNum & operator+=(const CBigNum &b)
const CBigNum operator++(int)
friend const CBigNum operator-(const CBigNum &a, const CBigNum &b)
std::string ToString(int nBase=10) const
CBigNum(const CBigNum &b)
friend const CBigNum operator/(const CBigNum &a, const CBigNum &b)
CBigNum(unsigned long long n)
void Serialize(Stream &s, int nType=0, int nVersion=PROTOCOL_VERSION) const