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