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