Remove unused code
[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     {
36         pctx = BN_CTX_new();
37         if (pctx == NULL)
38             throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
39     }
40
41     ~CAutoBN_CTX()
42     {
43         if (pctx != NULL)
44             BN_CTX_free(pctx);
45     }
46
47     operator BN_CTX*() { return pctx; }
48     BN_CTX& operator*() { return *pctx; }
49     BN_CTX** operator&() { return &pctx; }
50     bool operator!() { return (pctx == NULL); }
51 };
52
53
54 /** C++ wrapper for BIGNUM (OpenSSL bignum) */
55 class CBigNum
56 {
57 private:
58     BIGNUM* bn;
59 public:
60     CBigNum()
61     {
62         bn = BN_new();
63     }
64
65     CBigNum(const CBigNum& b)
66     {
67         BIGNUM *dup = BN_dup(b.bn);
68         if (!dup)
69         {
70             throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_dup failed");
71         }
72         bn = dup;
73     }
74
75     CBigNum& operator=(const CBigNum& b)
76     {
77         BIGNUM *dup = BN_dup(b.bn);
78         if (!dup)
79         {
80             throw bignum_error("CBigNum::operator= : BN_dup failed");
81         }
82         bn = dup;
83         return (*this);
84     }
85
86     CBigNum(const BIGNUM *bnp) {
87         BIGNUM *dup = BN_dup(bnp);
88         if (!dup)
89         {
90             throw bignum_error("CBigNum::CBigNum(const BIGNUM*) : BN_dup failed");
91         }
92         bn = dup;
93     }
94
95     ~CBigNum()
96     {
97         BN_clear_free(bn);
98     }
99
100     CBigNum(bool n)     { bn = BN_new(); setuint32(n); }
101
102     CBigNum(int8_t  n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
103     CBigNum(int16_t n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
104     CBigNum(int32_t n)  { bn = BN_new(); if (n >= 0) setuint32(n); else setint64(n); }
105     CBigNum(int64_t n)  { bn = BN_new(); if (n >= 0) setuint64(n); else setint64(n); }
106
107     CBigNum(uint8_t  n) { bn = BN_new(); setuint32(n); }
108     CBigNum(uint16_t n) { bn = BN_new(); setuint32(n); }
109     CBigNum(uint32_t n) { bn = BN_new(); setuint32(n); }
110     CBigNum(uint64_t n) { bn = BN_new(); setuint64(n); }
111
112     explicit CBigNum(uint256 n) { bn = BN_new(); setuint256(n); }
113     explicit CBigNum(const std::vector<uint8_t>& vch)
114     {
115         bn = BN_new();
116         setvch(vch);
117     }
118
119     void setuint32(uint32_t n)
120     {
121         if (!BN_set_word(bn, n))
122             throw bignum_error("CBigNum conversion from uint32_t : BN_set_word failed");
123     }
124
125     uint32_t getuint32() const
126     {
127         return BN_get_word(bn);
128     }
129
130     int32_t getint32() const
131     {
132         uint64_t n = BN_get_word(bn);
133         if (!BN_is_negative(bn))
134             return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::max() : (int32_t)n);
135         else
136             return (n > (uint64_t)std::numeric_limits<int32_t>::max() ? std::numeric_limits<int32_t>::min() : -(int32_t)n);
137     }
138
139     void setint64(int64_t sn)
140     {
141         uint8_t pch[sizeof(sn) + 6];
142         uint8_t* p = pch + 4;
143         bool fNegative;
144         uint64_t n;
145
146         if (sn < (int64_t)0)
147         {
148             // 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
149             n = -(sn + 1);
150             ++n;
151             fNegative = true;
152         } else {
153             n = sn;
154             fNegative = false;
155         }
156
157         bool fLeadingZeroes = true;
158         for (int i = 0; i < 8; i++)
159         {
160             uint8_t c = (n >> 56) & 0xff;
161             n <<= 8;
162             if (fLeadingZeroes)
163             {
164                 if (c == 0)
165                     continue;
166                 if (c & 0x80)
167                     *p++ = (fNegative ? 0x80 : 0);
168                 else if (fNegative)
169                     c |= 0x80;
170                 fLeadingZeroes = false;
171             }
172             *p++ = c;
173         }
174         uint32_t nSize = (uint32_t) (p - (pch + 4));
175         pch[0] = (nSize >> 24) & 0xff;
176         pch[1] = (nSize >> 16) & 0xff;
177         pch[2] = (nSize >> 8) & 0xff;
178         pch[3] = (nSize) & 0xff;
179         BN_mpi2bn(pch, (int)(p - pch), bn);
180     }
181
182     uint64_t getuint64()
183     {
184         size_t nSize = BN_bn2mpi(bn, NULL);
185         if (nSize < 4)
186             return 0;
187         std::vector<uint8_t> vch(nSize);
188         BN_bn2mpi(bn, &vch[0]);
189         if (vch.size() > 4)
190             vch[4] &= 0x7f;
191         uint64_t n = 0;
192         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
193             ((uint8_t*)&n)[i] = vch[j];
194         return n;
195     }
196
197     //supress msvc C4127: conditional expression is constant
198     inline bool check(bool value) {return value;}
199
200     void setuint64(uint64_t n)
201     {
202         // Use BN_set_word if word size is sufficient for uint64_t
203         if (check(sizeof(n) <= sizeof(BN_ULONG)))
204         {
205             if (!BN_set_word(bn, (BN_ULONG)n))
206                 throw bignum_error("CBigNum conversion from uint64_t : BN_set_word failed");
207             return;
208         }
209
210         uint8_t pch[sizeof(n) + 6];
211         uint8_t* p = pch + 4;
212         bool fLeadingZeroes = true;
213         for (int i = 0; i < 8; i++)
214         {
215             uint8_t c = (n >> 56) & 0xff;
216             n <<= 8;
217             if (fLeadingZeroes)
218             {
219                 if (c == 0)
220                     continue;
221                 if (c & 0x80)
222                     *p++ = 0;
223                 fLeadingZeroes = false;
224             }
225             *p++ = c;
226         }
227         uint32_t nSize = (uint32_t) (p - (pch + 4));
228         pch[0] = (nSize >> 24) & 0xff;
229         pch[1] = (nSize >> 16) & 0xff;
230         pch[2] = (nSize >> 8) & 0xff;
231         pch[3] = (nSize) & 0xff;
232         BN_mpi2bn(pch, (int)(p - pch), bn);
233     }
234
235     void setuint160(uint160 n)
236     {
237         uint8_t pch[sizeof(n) + 6];
238         uint8_t* p = pch + 4;
239         bool fLeadingZeroes = true;
240         uint8_t* pbegin = (uint8_t*)&n;
241         uint8_t* psrc = pbegin + sizeof(n);
242         while (psrc != pbegin)
243         {
244             uint8_t c = *(--psrc);
245             if (fLeadingZeroes)
246             {
247                 if (c == 0)
248                     continue;
249                 if (c & 0x80)
250                     *p++ = 0;
251                 fLeadingZeroes = false;
252             }
253             *p++ = c;
254         }
255         uint32_t nSize = (uint32_t) (p - (pch + 4));
256         pch[0] = (nSize >> 24) & 0xff;
257         pch[1] = (nSize >> 16) & 0xff;
258         pch[2] = (nSize >> 8) & 0xff;
259         pch[3] = (nSize >> 0) & 0xff;
260         BN_mpi2bn(pch, (int) (p - pch), bn);
261     }
262
263     uint160 getuint160() const
264     {
265         unsigned int nSize = BN_bn2mpi(bn, NULL);
266         if (nSize < 4)
267             return 0;
268         std::vector<uint8_t> vch(nSize);
269         BN_bn2mpi(bn, &vch[0]);
270         if (vch.size() > 4)
271             vch[4] &= 0x7f;
272         uint160 n = 0;
273         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
274             ((uint8_t*)&n)[i] = vch[j];
275         return n;
276     }
277
278     void setuint256(uint256 n)
279     {
280         uint8_t pch[sizeof(n) + 6];
281         uint8_t* p = pch + 4;
282         bool fLeadingZeroes = true;
283         uint8_t* pbegin = (uint8_t*)&n;
284         uint8_t* psrc = pbegin + sizeof(n);
285         while (psrc != pbegin)
286         {
287             uint8_t c = *(--psrc);
288             if (fLeadingZeroes)
289             {
290                 if (c == 0)
291                     continue;
292                 if (c & 0x80)
293                     *p++ = 0;
294                 fLeadingZeroes = false;
295             }
296             *p++ = c;
297         }
298         uint32_t nSize = (uint32_t) (p - (pch + 4));
299         pch[0] = (nSize >> 24) & 0xff;
300         pch[1] = (nSize >> 16) & 0xff;
301         pch[2] = (nSize >> 8) & 0xff;
302         pch[3] = (nSize >> 0) & 0xff;
303         BN_mpi2bn(pch, (int) (p - pch), bn);
304     }
305
306     uint256 getuint256() const
307     {
308         unsigned int nSize = BN_bn2mpi(bn, NULL);
309         if (nSize < 4)
310             return 0;
311         std::vector<uint8_t> vch(nSize);
312         BN_bn2mpi(bn, &vch[0]);
313         if (vch.size() > 4)
314             vch[4] &= 0x7f;
315         uint256 n = 0;
316         for (size_t i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
317             ((uint8_t*)&n)[i] = vch[j];
318         return n;
319     }
320
321     void setBytes(const std::vector<uint8_t>& vchBytes)
322     {
323         BN_bin2bn(&vchBytes[0], (int) vchBytes.size(), bn);
324     }
325
326     std::vector<uint8_t> getBytes() const
327     {
328         int nBytes = BN_num_bytes(bn);
329
330         std::vector<uint8_t> vchBytes(nBytes);
331
332         int n = BN_bn2bin(bn, &vchBytes[0]);
333         if (n != nBytes) {
334             throw bignum_error("CBigNum::getBytes : BN_bn2bin failed");
335         }
336
337         return vchBytes;
338     }
339
340     void setvch(const std::vector<uint8_t>& vch)
341     {
342         std::vector<uint8_t> vch2(vch.size() + 4);
343         uint32_t nSize = (uint32_t) vch.size();
344         // BIGNUM's byte stream format expects 4 bytes of
345         // big endian size data info at the front
346         vch2[0] = (nSize >> 24) & 0xff;
347         vch2[1] = (nSize >> 16) & 0xff;
348         vch2[2] = (nSize >> 8) & 0xff;
349         vch2[3] = (nSize >> 0) & 0xff;
350         // swap data to big endian
351         std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
352         BN_mpi2bn(&vch2[0], (int) vch2.size(), bn);
353     }
354
355     std::vector<uint8_t> getvch() const
356     {
357         unsigned int nSize = BN_bn2mpi(bn, NULL);
358         if (nSize <= 4)
359             return std::vector<uint8_t>();
360         std::vector<uint8_t> vch(nSize);
361         BN_bn2mpi(bn, &vch[0]);
362         vch.erase(vch.begin(), vch.begin() + 4);
363         std::reverse(vch.begin(), vch.end());
364         return vch;
365     }
366
367     CBigNum& SetCompact(uint32_t nCompact)
368     {
369         uint32_t nSize = nCompact >> 24;
370         std::vector<uint8_t> vch(4 + nSize);
371         vch[3] = nSize;
372         if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
373         if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
374         if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
375         BN_mpi2bn(&vch[0], (int) vch.size(), bn);
376         return *this;
377     }
378
379     uint32_t GetCompact() const
380     {
381         uint32_t nSize = BN_bn2mpi(bn, NULL);
382         std::vector<uint8_t> vch(nSize);
383         nSize -= 4;
384         BN_bn2mpi(bn, &vch[0]);
385         uint32_t nCompact = nSize << 24;
386         if (nSize >= 1) nCompact |= (vch[4] << 16);
387         if (nSize >= 2) nCompact |= (vch[5] << 8);
388         if (nSize >= 3) nCompact |= (vch[6] << 0);
389         return nCompact;
390     }
391
392     void SetHex(const std::string& str)
393     {
394         // skip 0x
395         const char* psz = str.c_str();
396         while (isspace(*psz))
397             psz++;
398         bool fNegative = false;
399         if (*psz == '-')
400         {
401             fNegative = true;
402             psz++;
403         }
404         if (psz[0] == '0' && tolower(psz[1]) == 'x')
405             psz += 2;
406         while (isspace(*psz))
407             psz++;
408
409         // hex string to bignum
410         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 };
411         *this = 0;
412         while (isxdigit(*psz))
413         {
414             *this <<= 4;
415             int n = phexdigit[(uint8_t)*psz++];
416             *this += n;
417         }
418         if (fNegative)
419             *this = 0 - *this;
420     }
421
422     std::string ToString(int nBase=10) const
423     {
424         CAutoBN_CTX pctx;
425         CBigNum bnBase = nBase;
426         CBigNum bn0 = 0;
427         std::string str;
428         CBigNum bn = *this;
429         BN_set_negative(bn.bn, false);
430         CBigNum dv;
431         CBigNum rem;
432         if (BN_cmp(bn.bn, bn0.bn) == 0)
433             return "0";
434         while (BN_cmp(bn.bn, bn0.bn) > 0)
435         {
436             if (!BN_div(dv.bn, rem.bn, bn.bn, bnBase.bn, pctx))
437                 throw bignum_error("CBigNum::ToString() : BN_div failed");
438             bn = dv;
439             uint32_t c = rem.getuint32();
440             str += "0123456789abcdef"[c];
441         }
442         if (BN_is_negative(bn.bn))
443             str += "-";
444         std::reverse(str.begin(), str.end());
445         return str;
446     }
447
448     std::string GetHex() const
449     {
450         return ToString(16);
451     }
452
453     BIGNUM* get() const {
454         return BN_dup(bn);
455     }
456
457     unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
458     {
459         return ::GetSerializeSize(getvch(), nType, nVersion);
460     }
461
462     template<typename Stream>
463     void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
464     {
465         ::Serialize(s, getvch(), nType, nVersion);
466     }
467
468     template<typename Stream>
469     void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
470     {
471         std::vector<uint8_t> vch;
472         ::Unserialize(s, vch, nType, nVersion);
473         setvch(vch);
474     }
475
476     bool operator!() const
477     {
478         return BN_is_zero(bn);
479     }
480
481     CBigNum& operator+=(const CBigNum& b)
482     {
483         if (!BN_add(bn, bn, b.bn))
484             throw bignum_error("CBigNum::operator+= : BN_add failed");
485         return *this;
486     }
487
488     CBigNum& operator-=(const CBigNum& b)
489     {
490         *this = *this - b;
491         return *this;
492     }
493
494     CBigNum& operator*=(const CBigNum& b)
495     {
496         CAutoBN_CTX pctx;
497         if (!BN_mul(bn, bn, b.bn, pctx))
498             throw bignum_error("CBigNum::operator*= : BN_mul failed");
499         return *this;
500     }
501
502     CBigNum& operator/=(const CBigNum& b)
503     {
504         *this = *this / b;
505         return *this;
506     }
507
508     CBigNum& operator%=(const CBigNum& b)
509     {
510         *this = *this % b;
511         return *this;
512     }
513
514     CBigNum& operator<<=(unsigned int shift)
515     {
516         if (!BN_lshift(bn, bn, shift))
517             throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
518         return *this;
519     }
520
521     CBigNum& operator>>=(unsigned int shift)
522     {
523         // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
524         //   if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
525         CBigNum a = 1;
526         a <<= shift;
527         if (BN_cmp(a.bn, bn) > 0)
528         {
529             *this = 0;
530             return *this;
531         }
532
533         if (!BN_rshift(bn, bn, shift))
534             throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
535         return *this;
536     }
537
538     CBigNum& operator++()
539     {
540         // prefix operator
541         if (!BN_add(bn, bn, BN_value_one()))
542             throw bignum_error("CBigNum::operator++ : BN_add failed");
543         return *this;
544     }
545
546     const CBigNum operator++(int)
547     {
548         // postfix operator
549         const CBigNum ret = *this;
550         ++(*this);
551         return ret;
552     }
553
554     CBigNum& operator--()
555     {
556         // prefix operator
557         CBigNum r;
558         if (!BN_sub(r.bn, bn, BN_value_one()))
559             throw bignum_error("CBigNum::operator-- : BN_sub failed");
560         *this = r;
561         return *this;
562     }
563
564     const CBigNum operator--(int)
565     {
566         // postfix operator
567         const CBigNum ret = *this;
568         --(*this);
569         return ret;
570     }
571
572     friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
573     friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
574     friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
575     friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b);
576     friend inline const CBigNum operator+(const CBigNum& a, const CBigNum& b);
577     friend inline const CBigNum operator*(const CBigNum& a);
578     
579     friend inline const CBigNum operator-(const CBigNum& a);
580     friend inline const CBigNum operator<<(const CBigNum& a, unsigned int shift);
581     
582     friend inline bool operator==(const CBigNum& a, const CBigNum& b);
583     friend inline bool operator!=(const CBigNum& a, const CBigNum& b);
584     friend inline bool operator<=(const CBigNum& a, const CBigNum& b);
585     friend inline bool operator>=(const CBigNum& a, const CBigNum& b);
586     friend inline bool operator<(const CBigNum& a, const CBigNum& b);
587     friend inline bool operator>(const CBigNum& a, const CBigNum& b);
588     friend inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b);
589 };
590
591
592 inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
593 {
594     CBigNum r;
595     if (!BN_add(r.bn, a.bn, b.bn))
596         throw bignum_error("CBigNum::operator+ : BN_add failed");
597     return r;
598 }
599
600 inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
601 {
602     CBigNum r;
603     if (!BN_sub(r.bn, a.bn, b.bn))
604         throw bignum_error("CBigNum::operator- : BN_sub failed");
605     return r;
606 }
607
608 inline const CBigNum operator-(const CBigNum& a)
609 {
610     CBigNum r(a);
611     BN_set_negative(r.bn, !BN_is_negative(r.bn));
612     return r;
613 }
614
615 inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
616 {
617     CAutoBN_CTX pctx;
618     CBigNum r;
619     if (!BN_mul(r.bn, a.bn, b.bn, pctx))
620         throw bignum_error("CBigNum::operator* : BN_mul failed");
621     return r;
622 }
623
624 inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
625 {
626     CAutoBN_CTX pctx;
627     CBigNum r;
628     if (!BN_div(r.bn, NULL, a.bn, b.bn, pctx))
629         throw bignum_error("CBigNum::operator/ : BN_div failed");
630     return r;
631 }
632
633 inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
634 {
635     CAutoBN_CTX pctx;
636     CBigNum r;
637     if (!BN_nnmod(r.bn, a.bn, b.bn, pctx))
638         throw bignum_error("CBigNum::operator% : BN_div failed");
639     return r;
640 }
641
642 inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
643 {
644     CBigNum r;
645     if (!BN_lshift(r.bn, a.bn, shift))
646         throw bignum_error("CBigNum:operator<< : BN_lshift failed");
647     return r;
648 }
649
650 inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
651 {
652     CBigNum r = a;
653     r >>= shift;
654     return r;
655 }
656
657 inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) == 0); }
658 inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) != 0); }
659 inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) <= 0); }
660 inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) >= 0); }
661 inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(a.bn, b.bn) < 0); }
662 inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(a.bn, b.bn) > 0); }
663
664 inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); }
665
666 #endif