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