1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #ifndef BITCOIN_BIGNUM_H
7 #define BITCOIN_BIGNUM_H
16 #include <openssl/bn.h>
18 class bignum_error
: public std::runtime_error
21 explicit bignum_error(const std::string
& str
) : std::runtime_error(str
) {}
25 /** C++ wrapper for BIGNUM (OpenSSL bignum) */
26 class CBigNum
: public BIGNUM
34 CBigNum(const CBigNum
& b
)
37 if (!BN_copy(this, &b
))
40 throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
44 CBigNum
& operator=(const CBigNum
& b
)
46 if (!BN_copy(this, &b
))
47 throw bignum_error("CBigNum::operator= : BN_copy failed");
56 CBigNum(long long n
) { BN_init(this); setint64(n
); }
58 explicit CBigNum(const std::vector
<unsigned char>& vch
)
66 unsigned long n
= BN_get_word(this);
67 if (!BN_is_negative(this))
68 return (n
> (unsigned long)std::numeric_limits
<int>::max() ? std::numeric_limits
<int>::max() : n
);
70 return (n
> (unsigned long)std::numeric_limits
<int>::max() ? std::numeric_limits
<int>::min() : -(int)n
);
73 void setint64(int64_t sn
)
75 unsigned char pch
[sizeof(sn
) + 6];
76 unsigned char* p
= pch
+ 4;
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
93 bool fLeadingZeroes
= true;
94 for (int i
= 0; i
< 8; i
++)
96 unsigned char c
= (n
>> 56) & 0xff;
103 *p
++ = (fNegative
? 0x80 : 0);
106 fLeadingZeroes
= false;
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);
118 void setvch(const std::vector
<unsigned char>& vch
)
120 std::vector
<unsigned char> vch2(vch
.size() + 4);
121 unsigned int nSize
= vch
.size();
122 // BIGNUM's byte stream format expects 4 bytes of
123 // big endian size data info at the front
124 vch2
[0] = (nSize
>> 24) & 0xff;
125 vch2
[1] = (nSize
>> 16) & 0xff;
126 vch2
[2] = (nSize
>> 8) & 0xff;
127 vch2
[3] = (nSize
>> 0) & 0xff;
128 // swap data to big endian
129 reverse_copy(vch
.begin(), vch
.end(), vch2
.begin() + 4);
130 BN_mpi2bn(&vch2
[0], vch2
.size(), this);
133 std::vector
<unsigned char> getvch() const
135 unsigned int nSize
= BN_bn2mpi(this, NULL
);
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());
145 friend inline const CBigNum
operator-(const CBigNum
& a
, const CBigNum
& b
);
150 inline const CBigNum
operator+(const CBigNum
& a
, const CBigNum
& b
)
153 if (!BN_add(&r
, &a
, &b
))
154 throw bignum_error("CBigNum::operator+ : BN_add failed");
158 inline const CBigNum
operator-(const CBigNum
& a
, const CBigNum
& b
)
161 if (!BN_sub(&r
, &a
, &b
))
162 throw bignum_error("CBigNum::operator- : BN_sub failed");
166 inline const CBigNum
operator-(const CBigNum
& a
)
169 BN_set_negative(&r
, !BN_is_negative(&r
));
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); }