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