Remove netbase.h from util header: create timedata 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 #include <stdexcept>
9 #include <vector>
10
11 #include <openssl/bn.h>
12
13 #include "serialize.h"
14 #include "util.h"
15 #include "uint256.h"
16
17 /** Errors thrown by the bignum class */
18 class bignum_error : public std::runtime_error
19 {
20 public:
21     explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
22 };
23
24
25 /** RAII encapsulated BN_CTX (OpenSSL bignum context) */
26 class CAutoBN_CTX
27 {
28 protected:
29     BN_CTX* pctx;
30     BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
31
32 public:
33     CAutoBN_CTX()
34     {
35         pctx = BN_CTX_new();
36         if (pctx == NULL)
37             throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
38     }
39
40     ~CAutoBN_CTX()
41     {
42         if (pctx != NULL)
43             BN_CTX_free(pctx);
44     }
45
46     operator BN_CTX*() { return pctx; }
47     BN_CTX& operator*() { return *pctx; }
48     BN_CTX** operator&() { return &pctx; }
49     bool operator!() { return (pctx == NULL); }
50 };
51
52
53 /** C++ wrapper for BIGNUM (OpenSSL bignum) */
54 class CBigNum : public BIGNUM
55 {
56 public:
57     CBigNum()
58     {
59         BN_init(this);
60     }
61
62     CBigNum(const CBigNum& b)
63     {
64         BN_init(this);
65         if (!BN_copy(this, &b))
66         {
67             BN_clear_free(this);
68             throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
69         }
70     }
71
72     CBigNum& operator=(const CBigNum& b)
73     {
74         if (!BN_copy(this, &b))
75             throw bignum_error("CBigNum::operator= : BN_copy failed");
76         return (*this);
77     }
78
79     ~CBigNum()
80     {
81         BN_clear_free(this);
82     }
83
84     CBigNum(int8_t  n)  { BN_init(this); if (n >= 0) setuint32(n); else setint64(n); }
85     CBigNum(int16_t n)  { BN_init(this); if (n >= 0) setuint32(n); else setint64(n); }
86     CBigNum(int32_t n)  { BN_init(this); if (n >= 0) setuint32(n); else setint64(n); }
87     CBigNum(int64_t n)  { BN_init(this); if (n >= 0) setuint64(n); else setint64(n); }
88
89     CBigNum(uint8_t  n) { BN_init(this); setuint32(n); }
90     CBigNum(uint16_t n) { BN_init(this); setuint32(n); }
91     CBigNum(uint32_t n) { BN_init(this); setuint32(n); }
92     CBigNum(uint64_t n) { BN_init(this); setuint64(n); }
93
94     explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
95     explicit CBigNum(const std::vector<uint8_t>& vch)
96     {
97         BN_init(this);
98         setvch(vch);
99     }
100
101     /** Generates a cryptographically secure random number between zero and range exclusive
102     * i.e. 0 < returned number < range
103     * @param range The upper bound on the number.
104     * @return
105     */
106     static CBigNum  randBignum(const CBigNum& range) {
107         CBigNum ret;
108         if(!BN_rand_range(&ret, &range)){
109             throw bignum_error("CBigNum:rand element : BN_rand_range failed");
110         }
111         return ret;
112     }
113
114     /** Generates a cryptographically secure random k-bit number
115     * @param k The bit length of the number.
116     * @return
117     */
118     static CBigNum RandKBitBigum(const uint32_t k){
119         CBigNum ret;
120         if(!BN_rand(&ret, k, -1, 0)){
121             throw bignum_error("CBigNum:rand element : BN_rand failed");
122         }
123         return ret;
124     }
125
126     /**Returns the size in bits of the underlying bignum.
127      *
128      * @return the size
129      */
130     int bitSize() const{
131         return  BN_num_bits(this);
132     }
133
134
135     void setuint32(uint32_t n)
136     {
137         if (!BN_set_word(this, n))
138             throw bignum_error("CBigNum conversion from uint32_t : BN_set_word failed");
139     }
140
141     uint32_t getuint32() const
142     {
143         return BN_get_word(this);
144     }
145
146     int32_t getint32() const
147     {
148         uint64_t n = BN_get_word(this);
149         if (!BN_is_negative(this))
150             return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::max() : (int32_t)n);
151         else
152             return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::min() : -(int32_t)n);
153     }
154
155     void setint64(int64_t sn)
156     {
157         uint8_t pch[sizeof(sn) + 6];
158         uint8_t* p = pch + 4;
159         bool fNegative;
160         uint64_t n;
161
162         if (sn < (int64_t)0)
163         {
164             // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
165             n = -(sn + 1);
166             ++n;
167             fNegative = true;
168         } else {
169             n = sn;
170             fNegative = false;
171         }
172
173         bool fLeadingZeroes = true;
174         for (int i = 0; i < 8; i++)
175         {
176             uint8_t c = (n >> 56) & 0xff;
177             n <<= 8;
178             if (fLeadingZeroes)
179             {
180                 if (c == 0)
181                     continue;
182                 if (c & 0x80)
183                     *p++ = (fNegative ? 0x80 : 0);
184                 else if (fNegative)
185                     c |= 0x80;
186                 fLeadingZeroes = false;
187             }
188             *p++ = c;
189         }
190         uint32_t nSize = (uint32_t) (p - (pch + 4));
191         pch[0] = (nSize >> 24) & 0xff;
192         pch[1] = (nSize >> 16) & 0xff;
193         pch[2] = (nSize >> 8) & 0xff;
194         pch[3] = (nSize) & 0xff;
195         BN_mpi2bn(pch, (int)(p - pch), this);
196     }
197
198     int64_t getint64()
199     {
200         return (int64_t) getuint64();
201     }
202
203     uint64_t getuint64()
204     {
205         size_t nSize = BN_bn2mpi(this, NULL);
206         if (nSize < 4)
207             return 0;
208         std::vector<uint8_t> vch(nSize);
209         BN_bn2mpi(this, &vch[0]);
210         if (vch.size() > 4)
211             vch[4] &= 0x7f;
212         uint64_t n = 0;
213         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
214             ((uint8_t*)&n)[i] = vch[j];
215         return n;
216     }
217
218     //supress msvc C4127: conditional expression is constant
219     inline bool check(bool value) {return value;}
220
221     void setuint64(uint64_t n)
222     {
223         // Use BN_set_word if word size is sufficient for uint64_t
224         if (check(sizeof(n) <= sizeof(BN_ULONG)))
225         {
226             if (!BN_set_word(this, (BN_ULONG)n))
227                 throw bignum_error("CBigNum conversion from uint64_t : BN_set_word failed");
228             return;
229         }
230
231         uint8_t pch[sizeof(n) + 6];
232         uint8_t* p = pch + 4;
233         bool fLeadingZeroes = true;
234         for (int i = 0; i < 8; i++)
235         {
236             uint8_t c = (n >> 56) & 0xff;
237             n <<= 8;
238             if (fLeadingZeroes)
239             {
240                 if (c == 0)
241                     continue;
242                 if (c & 0x80)
243                     *p++ = 0;
244                 fLeadingZeroes = false;
245             }
246             *p++ = c;
247         }
248         uint32_t nSize = (uint32_t) (p - (pch + 4));
249         pch[0] = (nSize >> 24) & 0xff;
250         pch[1] = (nSize >> 16) & 0xff;
251         pch[2] = (nSize >> 8) & 0xff;
252         pch[3] = (nSize) & 0xff;
253         BN_mpi2bn(pch, (int)(p - pch), this);
254     }
255
256     void setuint160(uint160 n)
257     {
258         uint8_t pch[sizeof(n) + 6];
259         uint8_t* p = pch + 4;
260         bool fLeadingZeroes = true;
261         uint8_t* pbegin = (uint8_t*)&n;
262         uint8_t* psrc = pbegin + sizeof(n);
263         while (psrc != pbegin)
264         {
265             uint8_t c = *(--psrc);
266             if (fLeadingZeroes)
267             {
268                 if (c == 0)
269                     continue;
270                 if (c & 0x80)
271                     *p++ = 0;
272                 fLeadingZeroes = false;
273             }
274             *p++ = c;
275         }
276         uint32_t nSize = (uint32_t) (p - (pch + 4));
277         pch[0] = (nSize >> 24) & 0xff;
278         pch[1] = (nSize >> 16) & 0xff;
279         pch[2] = (nSize >> 8) & 0xff;
280         pch[3] = (nSize >> 0) & 0xff;
281         BN_mpi2bn(pch, (int) (p - pch), this);
282     }
283
284     uint160 getuint160() const
285     {
286         unsigned int nSize = BN_bn2mpi(this, NULL);
287         if (nSize < 4)
288             return 0;
289         std::vector<uint8_t> vch(nSize);
290         BN_bn2mpi(this, &vch[0]);
291         if (vch.size() > 4)
292             vch[4] &= 0x7f;
293         uint160 n = 0;
294         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
295             ((uint8_t*)&n)[i] = vch[j];
296         return n;
297     }
298
299     void setuint256(uint256 n)
300     {
301         uint8_t pch[sizeof(n) + 6];
302         uint8_t* p = pch + 4;
303         bool fLeadingZeroes = true;
304         uint8_t* pbegin = (uint8_t*)&n;
305         uint8_t* psrc = pbegin + sizeof(n);
306         while (psrc != pbegin)
307         {
308             uint8_t c = *(--psrc);
309             if (fLeadingZeroes)
310             {
311                 if (c == 0)
312                     continue;
313                 if (c & 0x80)
314                     *p++ = 0;
315                 fLeadingZeroes = false;
316             }
317             *p++ = c;
318         }
319         uint32_t nSize = (uint32_t) (p - (pch + 4));
320         pch[0] = (nSize >> 24) & 0xff;
321         pch[1] = (nSize >> 16) & 0xff;
322         pch[2] = (nSize >> 8) & 0xff;
323         pch[3] = (nSize >> 0) & 0xff;
324         BN_mpi2bn(pch, (int) (p - pch), this);
325     }
326
327     uint256 getuint256() const
328     {
329         unsigned int nSize = BN_bn2mpi(this, NULL);
330         if (nSize < 4)
331             return 0;
332         std::vector<uint8_t> vch(nSize);
333         BN_bn2mpi(this, &vch[0]);
334         if (vch.size() > 4)
335             vch[4] &= 0x7f;
336         uint256 n = 0;
337         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
338             ((uint8_t*)&n)[i] = vch[j];
339         return n;
340     }
341
342     void setBytes(const std::vector<uint8_t>& vchBytes)
343     {
344         BN_bin2bn(&vchBytes[0], (int) vchBytes.size(), this);
345     }
346
347     std::vector<uint8_t> getBytes() const
348     {
349         int nBytes = BN_num_bytes(this);
350
351         std::vector<uint8_t> vchBytes(nBytes);
352
353         int n = BN_bn2bin(this, &vchBytes[0]);
354         if (n != nBytes) {
355             throw bignum_error("CBigNum::getBytes : BN_bn2bin failed");
356         }
357
358         return vchBytes;
359     }
360
361     void setvch(const std::vector<uint8_t>& vch)
362     {
363         std::vector<uint8_t> vch2(vch.size() + 4);
364         uint32_t nSize = (uint32_t) vch.size();
365         // BIGNUM's byte stream format expects 4 bytes of
366         // big endian size data info at the front
367         vch2[0] = (nSize >> 24) & 0xff;
368         vch2[1] = (nSize >> 16) & 0xff;
369         vch2[2] = (nSize >> 8) & 0xff;
370         vch2[3] = (nSize >> 0) & 0xff;
371         // swap data to big endian
372         reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
373         BN_mpi2bn(&vch2[0], (int) vch2.size(), this);
374     }
375
376     std::vector<uint8_t> getvch() const
377     {
378         unsigned int nSize = BN_bn2mpi(this, NULL);
379         if (nSize <= 4)
380             return std::vector<uint8_t>();
381         std::vector<uint8_t> vch(nSize);
382         BN_bn2mpi(this, &vch[0]);
383         vch.erase(vch.begin(), vch.begin() + 4);
384         reverse(vch.begin(), vch.end());
385         return vch;
386     }
387
388     CBigNum& SetCompact(uint32_t nCompact)
389     {
390         uint32_t nSize = nCompact >> 24;
391         std::vector<uint8_t> vch(4 + nSize);
392         vch[3] = nSize;
393         if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
394         if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
395         if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
396         BN_mpi2bn(&vch[0], (int) vch.size(), this);
397         return *this;
398     }
399
400     uint32_t GetCompact() const
401     {
402         uint32_t nSize = BN_bn2mpi(this, NULL);
403         std::vector<uint8_t> vch(nSize);
404         nSize -= 4;
405         BN_bn2mpi(this, &vch[0]);
406         uint32_t nCompact = nSize << 24;
407         if (nSize >= 1) nCompact |= (vch[4] << 16);
408         if (nSize >= 2) nCompact |= (vch[5] << 8);
409         if (nSize >= 3) nCompact |= (vch[6] << 0);
410         return nCompact;
411     }
412
413     void SetHex(const std::string& str)
414     {
415         // skip 0x
416         const char* psz = str.c_str();
417         while (isspace(*psz))
418             psz++;
419         bool fNegative = false;
420         if (*psz == '-')
421         {
422             fNegative = true;
423             psz++;
424         }
425         if (psz[0] == '0' && tolower(psz[1]) == 'x')
426             psz += 2;
427         while (isspace(*psz))
428             psz++;
429
430         // hex string to bignum
431         static const signed char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
432         *this = 0;
433         while (isxdigit(*psz))
434         {
435             *this <<= 4;
436             int n = phexdigit[(uint8_t)*psz++];
437             *this += n;
438         }
439         if (fNegative)
440             *this = 0 - *this;
441     }
442
443     std::string ToString(int nBase=10) const
444     {
445         CAutoBN_CTX pctx;
446         CBigNum bnBase = nBase;
447         CBigNum bn0 = 0;
448         std::string str;
449         CBigNum bn = *this;
450         BN_set_negative(&bn, false);
451         CBigNum dv;
452         CBigNum rem;
453         if (BN_cmp(&bn, &bn0) == 0)
454             return "0";
455         while (BN_cmp(&bn, &bn0) > 0)
456         {
457             if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
458                 throw bignum_error("CBigNum::ToString() : BN_div failed");
459             bn = dv;
460             uint32_t c = rem.getuint32();
461             str += "0123456789abcdef"[c];
462         }
463         if (BN_is_negative(this))
464             str += "-";
465         reverse(str.begin(), str.end());
466         return str;
467     }
468
469     std::string GetHex() const
470     {
471         return ToString(16);
472     }
473
474     unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
475     {
476         return ::GetSerializeSize(getvch(), nType, nVersion);
477     }
478
479     template<typename Stream>
480     void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
481     {
482         ::Serialize(s, getvch(), nType, nVersion);
483     }
484
485     template<typename Stream>
486     void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
487     {
488         std::vector<uint8_t> vch;
489         ::Unserialize(s, vch, nType, nVersion);
490         setvch(vch);
491     }
492
493     /**
494     * exponentiation with an int. this^e
495     * @param e the exponent as an int
496     * @return
497     */
498     CBigNum pow(const int e) const {
499         return this->pow(CBigNum(e));
500     }
501
502     /**
503      * exponentiation this^e
504      * @param e the exponent
505      * @return
506      */
507     CBigNum pow(const CBigNum& e) const {
508         CAutoBN_CTX pctx;
509         CBigNum ret;
510         if (!BN_exp(&ret, this, &e, pctx))
511             throw bignum_error("CBigNum::pow : BN_exp failed");
512         return ret;
513     }
514
515     /**
516      * modular multiplication: (this * b) mod m
517      * @param b operand
518      * @param m modulus
519      */
520     CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const {
521         CAutoBN_CTX pctx;
522         CBigNum ret;
523         if (!BN_mod_mul(&ret, this, &b, &m, pctx))
524             throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed");
525
526         return ret;
527     }
528
529     /**
530      * modular exponentiation: this^e mod n
531      * @param e exponent
532      * @param m modulus
533      */
534     CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const {
535         CAutoBN_CTX pctx;
536         CBigNum ret;
537         if( e < 0){
538             // g^-x = (g^-1)^x
539             CBigNum inv = this->inverse(m);
540             CBigNum posE = e * -1;
541             if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx))
542                 throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent");
543         }else
544             if (!BN_mod_exp(&ret, this, &e, &m, pctx))
545                 throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed");
546
547         return ret;
548     }
549
550     /**
551     * Calculates the inverse of this element mod m.
552     * i.e. i such this*i = 1 mod m
553     * @param m the modu
554     * @return the inverse
555     */
556     CBigNum inverse(const CBigNum& m) const {
557         CAutoBN_CTX pctx;
558         CBigNum ret;
559         if (!BN_mod_inverse(&ret, this, &m, pctx))
560             throw bignum_error("CBigNum::inverse*= :BN_mod_inverse");
561         return ret;
562     }
563
564     /**
565      * Generates a random (safe) prime of numBits bits
566      * @param numBits the number of bits
567      * @param safe true for a safe prime
568      * @return the prime
569      */
570     static CBigNum generatePrime(const unsigned int numBits, bool safe = false) {
571         CBigNum ret;
572         if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL))
573             throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex");
574         return ret;
575     }
576
577     /**
578      * Calculates the greatest common divisor (GCD) of two numbers.
579      * @param m the second element
580      * @return the GCD
581      */
582     CBigNum gcd( const CBigNum& b) const{
583         CAutoBN_CTX pctx;
584         CBigNum ret;
585         if (!BN_gcd(&ret, this, &b, pctx))
586             throw bignum_error("CBigNum::gcd*= :BN_gcd");
587         return ret;
588     }
589
590     /**
591     * Miller-Rabin primality test on this element
592     * @param checks: optional, the number of Miller-Rabin tests to run
593     * default causes error rate of 2^-80.
594     * @return true if prime
595     */
596     bool isPrime(const int checks=BN_prime_checks) const {
597         CAutoBN_CTX pctx;
598         int ret = BN_is_prime(this, checks, NULL, pctx, NULL);
599         if(ret < 0){
600             throw bignum_error("CBigNum::isPrime :BN_is_prime");
601         }
602         return ret != 0;
603     }
604
605     bool isOne() const {
606         return BN_is_one(this);
607     }
608
609
610     bool operator!() const
611     {
612         return BN_is_zero(this);
613     }
614
615     CBigNum& operator+=(const CBigNum& b)
616     {
617         if (!BN_add(this, this, &b))
618             throw bignum_error("CBigNum::operator+= : BN_add failed");
619         return *this;
620     }
621
622     CBigNum& operator-=(const CBigNum& b)
623     {
624         *this = *this - b;
625         return *this;
626     }
627
628     CBigNum& operator*=(const CBigNum& b)
629     {
630         CAutoBN_CTX pctx;
631         if (!BN_mul(this, this, &b, pctx))
632             throw bignum_error("CBigNum::operator*= : BN_mul failed");
633         return *this;
634     }
635
636     CBigNum& operator/=(const CBigNum& b)
637     {
638         *this = *this / b;
639         return *this;
640     }
641
642     CBigNum& operator%=(const CBigNum& b)
643     {
644         *this = *this % b;
645         return *this;
646     }
647
648     CBigNum& operator<<=(unsigned int shift)
649     {
650         if (!BN_lshift(this, this, shift))
651             throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
652         return *this;
653     }
654
655     CBigNum& operator>>=(unsigned int shift)
656     {
657         // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
658         //   if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
659         CBigNum a = 1;
660         a <<= shift;
661         if (BN_cmp(&a, this) > 0)
662         {
663             *this = 0;
664             return *this;
665         }
666
667         if (!BN_rshift(this, this, shift))
668             throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
669         return *this;
670     }
671
672
673     CBigNum& operator++()
674     {
675         // prefix operator
676         if (!BN_add(this, this, BN_value_one()))
677             throw bignum_error("CBigNum::operator++ : BN_add failed");
678         return *this;
679     }
680
681     const CBigNum operator++(int)
682     {
683         // postfix operator
684         const CBigNum ret = *this;
685         ++(*this);
686         return ret;
687     }
688
689     CBigNum& operator--()
690     {
691         // prefix operator
692         CBigNum r;
693         if (!BN_sub(&r, this, BN_value_one()))
694             throw bignum_error("CBigNum::operator-- : BN_sub failed");
695         *this = r;
696         return *this;
697     }
698
699     const CBigNum operator--(int)
700     {
701         // postfix operator
702         const CBigNum ret = *this;
703         --(*this);
704         return ret;
705     }
706
707
708     friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
709     friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
710     friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
711     friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b);
712     friend inline bool operator<(const CBigNum& a, const CBigNum& b);
713 };
714
715
716
717 inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
718 {
719     CBigNum r;
720     if (!BN_add(&r, &a, &b))
721         throw bignum_error("CBigNum::operator+ : BN_add failed");
722     return r;
723 }
724
725 inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
726 {
727     CBigNum r;
728     if (!BN_sub(&r, &a, &b))
729         throw bignum_error("CBigNum::operator- : BN_sub failed");
730     return r;
731 }
732
733 inline const CBigNum operator-(const CBigNum& a)
734 {
735     CBigNum r(a);
736     BN_set_negative(&r, !BN_is_negative(&r));
737     return r;
738 }
739
740 inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
741 {
742     CAutoBN_CTX pctx;
743     CBigNum r;
744     if (!BN_mul(&r, &a, &b, pctx))
745         throw bignum_error("CBigNum::operator* : BN_mul failed");
746     return r;
747 }
748
749 inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
750 {
751     CAutoBN_CTX pctx;
752     CBigNum r;
753     if (!BN_div(&r, NULL, &a, &b, pctx))
754         throw bignum_error("CBigNum::operator/ : BN_div failed");
755     return r;
756 }
757
758 inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
759 {
760     CAutoBN_CTX pctx;
761     CBigNum r;
762     if (!BN_nnmod(&r, &a, &b, pctx))
763         throw bignum_error("CBigNum::operator% : BN_div failed");
764     return r;
765 }
766
767 inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
768 {
769     CBigNum r;
770     if (!BN_lshift(&r, &a, shift))
771         throw bignum_error("CBigNum:operator<< : BN_lshift failed");
772     return r;
773 }
774
775 inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
776 {
777     CBigNum r = a;
778     r >>= shift;
779     return r;
780 }
781
782 inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
783 inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
784 inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
785 inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
786 inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) < 0); }
787 inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) > 0); }
788
789 inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); }
790
791 typedef  CBigNum Bignum;
792
793 #endif