Update CMakeLists.txt - play with openssl
[novacoin.git] / src / bignum.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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.
5 #ifndef BITCOIN_BIGNUM_H
6 #define BITCOIN_BIGNUM_H
7
8
9 #include "serialize.h"
10 #include "version.h"
11
12 #include <openssl/bn.h>
13
14 #include <stdexcept>
15 #include <vector>
16 #include <algorithm>
17
18 class uint160;
19 class uint256;
20
21 /** Errors thrown by the bignum class */
22 class bignum_error : public std::runtime_error
23 {
24 public:
25     explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
26 };
27
28
29 /** RAII encapsulated BN_CTX (OpenSSL bignum context) */
30 class CAutoBN_CTX
31 {
32 protected:
33     BN_CTX* pctx;
34     BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
35
36 public:
37     CAutoBN_CTX();
38     ~CAutoBN_CTX();
39
40     operator BN_CTX*() { return pctx; }
41     BN_CTX& operator*() { return *pctx; }
42     BN_CTX** operator&() { return &pctx; }
43     bool operator!() { return (pctx == NULL); }
44 };
45
46
47 /** C++ wrapper for BIGNUM (OpenSSL bignum) */
48 class CBigNum
49 {
50 private:
51     BIGNUM* bn;
52 public:
53     CBigNum();
54     CBigNum(const CBigNum& b);
55     CBigNum& operator=(const CBigNum& b);
56     CBigNum(const BIGNUM *bnp);
57
58     ~CBigNum();
59
60     CBigNum(bool n)     { bn = BN_new(); setuint32(n); }
61
62     CBigNum(int8_t  n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
63     CBigNum(int16_t n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
64     CBigNum(int32_t n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
65     CBigNum(int64_t n)  { bn = BN_new(); if (n >= 0) setuint64(n); else setint64(n); }
66
67     CBigNum(uint8_t  n) { bn = BN_new(); setuint32(n); }
68     CBigNum(uint16_t n) { bn = BN_new(); setuint32(n); }
69     CBigNum(uint32_t n) { bn = BN_new(); setuint32(n); }
70     CBigNum(uint64_t n) { bn = BN_new(); setuint64(n); }
71
72     explicit CBigNum(uint256 n);
73     explicit CBigNum(const std::vector<uint8_t>& vch) { bn = BN_new(); setvch(vch); }
74
75     void setuint32(uint32_t n);
76     uint32_t getuint32() const;
77     int32_t getint32() const;
78     void setint64(int64_t sn);
79     uint64_t getuint64();
80
81     //supress msvc C4127: conditional expression is constant
82     inline bool check(bool value) {return value;}
83
84     void setuint64(uint64_t n);
85     void setuint160(uint160 n);
86     uint160 getuint160() const;
87     void setuint256(uint256 n);
88     uint256 getuint256() const;
89     void setBytes(const std::vector<uint8_t>& vchBytes);
90     std::vector<uint8_t> getBytes() const;
91     void setvch(const std::vector<uint8_t>& vch);
92     std::vector<uint8_t> getvch() const;
93     CBigNum& SetCompact(uint32_t nCompact);
94     uint32_t GetCompact() const;
95     void SetHex(const std::string& str);
96     std::string ToString(int nBase=10) const;
97     std::string GetHex() const { return ToString(16); }
98     BIGNUM* get() const { return BN_dup(bn); }
99
100     unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
101     {
102         return ::GetSerializeSize(getvch(), nType, nVersion);
103     }
104
105     template<typename Stream>
106     void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
107     {
108         ::Serialize(s, getvch(), nType, nVersion);
109     }
110
111     template<typename Stream>
112     void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
113     {
114         std::vector<uint8_t> vch;
115         ::Unserialize(s, vch, nType, nVersion);
116         setvch(vch);
117     }
118
119     bool operator!() const;
120
121     CBigNum& operator+=(const CBigNum& b);
122     CBigNum& operator-=(const CBigNum& b);
123     CBigNum& operator*=(const CBigNum& b);
124     CBigNum& operator/=(const CBigNum& b);
125     CBigNum& operator%=(const CBigNum& b);
126     CBigNum& operator<<=(unsigned int shift);
127     CBigNum& operator>>=(unsigned int shift);
128     CBigNum& operator++();
129     const CBigNum operator++(int);
130     CBigNum& operator--();
131     const CBigNum operator--(int);
132
133     friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
134     friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
135     friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
136     friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b);
137     friend inline const CBigNum operator+(const CBigNum& a, const CBigNum& b);
138     friend inline const CBigNum operator*(const CBigNum& a);
139     
140     friend inline const CBigNum operator-(const CBigNum& a);
141     friend inline const CBigNum operator<<(const CBigNum& a, unsigned int shift);
142     
143     friend inline bool operator==(const CBigNum& a, const CBigNum& b);
144     friend inline bool operator!=(const CBigNum& a, const CBigNum& b);
145     friend inline bool operator<=(const CBigNum& a, const CBigNum& b);
146     friend inline bool operator>=(const CBigNum& a, const CBigNum& b);
147     friend inline bool operator<(const CBigNum& a, const CBigNum& b);
148     friend inline bool operator>(const CBigNum& a, const CBigNum& b);
149     friend inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b);
150 };
151
152
153 inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
154 {
155     CBigNum r;
156     if (!BN_add(r.bn, a.bn, b.bn))
157         throw bignum_error("CBigNum::operator+ : BN_add failed");
158     return r;
159 }
160
161 inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
162 {
163     CBigNum r;
164     if (!BN_sub(r.bn, a.bn, b.bn))
165         throw bignum_error("CBigNum::operator- : BN_sub failed");
166     return r;
167 }
168
169 inline const CBigNum operator-(const CBigNum& a)
170 {
171     CBigNum r(a);
172     BN_set_negative(r.bn, !BN_is_negative(r.bn));
173     return r;
174 }
175
176 inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
177 {
178     CAutoBN_CTX pctx;
179     CBigNum r;
180     if (!BN_mul(r.bn, a.bn, b.bn, pctx))
181         throw bignum_error("CBigNum::operator* : BN_mul failed");
182     return r;
183 }
184
185 inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
186 {
187     CAutoBN_CTX pctx;
188     CBigNum r;
189     if (!BN_div(r.bn, NULL, a.bn, b.bn, pctx))
190         throw bignum_error("CBigNum::operator/ : BN_div failed");
191     return r;
192 }
193
194 inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
195 {
196     CAutoBN_CTX pctx;
197     CBigNum r;
198     if (!BN_nnmod(r.bn, a.bn, b.bn, pctx))
199         throw bignum_error("CBigNum::operator% : BN_div failed");
200     return r;
201 }
202
203 inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
204 {
205     CBigNum r;
206     if (!BN_lshift(r.bn, a.bn, shift))
207         throw bignum_error("CBigNum:operator<< : BN_lshift failed");
208     return r;
209 }
210
211 inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
212 {
213     CBigNum r = a;
214     r >>= shift;
215     return r;
216 }
217
218 inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) == 0); }
219 inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) != 0); }
220 inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) <= 0); }
221 inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) >= 0); }
222 inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(a.bn, b.bn) < 0); }
223 inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(a.bn, b.bn) > 0); }
224
225 inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); }
226
227 #endif