genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 #ifndef BITCOIN_BIGNUM_H
genesis                 6 #define BITCOIN_BIGNUM_H
genesis                 7 
genesis                 8 #include <stdexcept>
genesis                 9 #include <vector>
genesis                10 #include <openssl/bn.h>
genesis                11 
genesis                12 #include "util.h"
genesis                13 
genesis                14 class bignum_error : public std::runtime_error
genesis                15 {
genesis                16 public:
genesis                17     explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
genesis                18 };
genesis                19 
genesis                20 
genesis                21 
genesis                22 class CAutoBN_CTX
genesis                23 {
genesis                24 protected:
genesis                25     BN_CTX* pctx;
genesis                26     BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
genesis                27 
genesis                28 public:
genesis                29     CAutoBN_CTX()
genesis                30     {
genesis                31         pctx = BN_CTX_new();
genesis                32         if (pctx == NULL)
genesis                33             throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
genesis                34     }
genesis                35 
genesis                36     ~CAutoBN_CTX()
genesis                37     {
genesis                38         if (pctx != NULL)
genesis                39             BN_CTX_free(pctx);
genesis                40     }
genesis                41 
genesis                42     operator BN_CTX*() { return pctx; }
genesis                43     BN_CTX& operator*() { return *pctx; }
genesis                44     BN_CTX** operator&() { return &pctx; }
genesis                45     bool operator!() { return (pctx == NULL); }
genesis                46 };
genesis                47 
genesis                48 
genesis                49 
genesis                50 class CBigNum : public BIGNUM
genesis                51 {
genesis                52 public:
genesis                53     CBigNum()
genesis                54     {
genesis                55         BN_init(this);
genesis                56     }
genesis                57 
genesis                58     CBigNum(const CBigNum& b)
genesis                59     {
genesis                60         BN_init(this);
genesis                61         if (!BN_copy(this, &b))
genesis                62         {
genesis                63             BN_clear_free(this);
genesis                64             throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
genesis                65         }
genesis                66     }
genesis                67 
genesis                68     CBigNum& operator=(const CBigNum& b)
genesis                69     {
genesis                70         if (!BN_copy(this, &b))
genesis                71             throw bignum_error("CBigNum::operator= : BN_copy failed");
genesis                72         return (*this);
genesis                73     }
genesis                74 
genesis                75     ~CBigNum()
genesis                76     {
genesis                77         BN_clear_free(this);
genesis                78     }
genesis                79 
genesis                80     CBigNum(char n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
genesis                81     CBigNum(short n)            { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
genesis                82     CBigNum(int n)              { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
genesis                83     CBigNum(long n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
genesis                84     CBigNum(int64 n)            { BN_init(this); setint64(n); }
genesis                85     CBigNum(unsigned char n)    { BN_init(this); setulong(n); }
genesis                86     CBigNum(unsigned short n)   { BN_init(this); setulong(n); }
genesis                87     CBigNum(unsigned int n)     { BN_init(this); setulong(n); }
genesis                88     CBigNum(unsigned long n)    { BN_init(this); setulong(n); }
genesis                89     CBigNum(uint64 n)           { BN_init(this); setuint64(n); }
genesis                90     explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
genesis                91 
genesis                92     explicit CBigNum(const std::vector<unsigned char>& vch)
genesis                93     {
genesis                94         BN_init(this);
genesis                95         setvch(vch);
genesis                96     }
genesis                97 
genesis                98     void setulong(unsigned long n)
genesis                99     {
genesis               100         if (!BN_set_word(this, n))
genesis               101             throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
genesis               102     }
genesis               103 
genesis               104     unsigned long getulong() const
genesis               105     {
genesis               106         return BN_get_word(this);
genesis               107     }
genesis               108 
genesis               109     unsigned int getuint() const
genesis               110     {
genesis               111         return BN_get_word(this);
genesis               112     }
genesis               113 
genesis               114     int getint() const
genesis               115     {
genesis               116         unsigned long n = BN_get_word(this);
genesis               117         if (!BN_is_negative(this))
genesis               118             return (n > INT_MAX ? INT_MAX : n);
genesis               119         else
genesis               120             return (n > INT_MAX ? INT_MIN : -(int)n);
genesis               121     }
genesis               122 
genesis               123     void setint64(int64 n)
genesis               124     {
genesis               125         unsigned char pch[sizeof(n) + 6];
genesis               126         unsigned char* p = pch + 4;
genesis               127         bool fNegative = false;
genesis               128         if (n < (int64)0)
genesis               129         {
genesis               130             n = -n;
genesis               131             fNegative = true;
genesis               132         }
genesis               133         bool fLeadingZeroes = true;
genesis               134         for (int i = 0; i < 8; i++)
genesis               135         {
genesis               136             unsigned char c = (n >> 56) & 0xff;
genesis               137             n <<= 8;
genesis               138             if (fLeadingZeroes)
genesis               139             {
genesis               140                 if (c == 0)
genesis               141                     continue;
genesis               142                 if (c & 0x80)
genesis               143                     *p++ = (fNegative ? 0x80 : 0);
genesis               144                 else if (fNegative)
genesis               145                     c |= 0x80;
genesis               146                 fLeadingZeroes = false;
genesis               147             }
genesis               148             *p++ = c;
genesis               149         }
genesis               150         unsigned int nSize = p - (pch + 4);
genesis               151         pch[0] = (nSize >> 24) & 0xff;
genesis               152         pch[1] = (nSize >> 16) & 0xff;
genesis               153         pch[2] = (nSize >> 8) & 0xff;
genesis               154         pch[3] = (nSize) & 0xff;
genesis               155         BN_mpi2bn(pch, p - pch, this);
genesis               156     }
genesis               157 
genesis               158     void setuint64(uint64 n)
genesis               159     {
genesis               160         unsigned char pch[sizeof(n) + 6];
genesis               161         unsigned char* p = pch + 4;
genesis               162         bool fLeadingZeroes = true;
genesis               163         for (int i = 0; i < 8; i++)
genesis               164         {
genesis               165             unsigned char c = (n >> 56) & 0xff;
genesis               166             n <<= 8;
genesis               167             if (fLeadingZeroes)
genesis               168             {
genesis               169                 if (c == 0)
genesis               170                     continue;
genesis               171                 if (c & 0x80)
genesis               172                     *p++ = 0;
genesis               173                 fLeadingZeroes = false;
genesis               174             }
genesis               175             *p++ = c;
genesis               176         }
genesis               177         unsigned int nSize = p - (pch + 4);
genesis               178         pch[0] = (nSize >> 24) & 0xff;
genesis               179         pch[1] = (nSize >> 16) & 0xff;
genesis               180         pch[2] = (nSize >> 8) & 0xff;
genesis               181         pch[3] = (nSize) & 0xff;
genesis               182         BN_mpi2bn(pch, p - pch, this);
genesis               183     }
genesis               184 
genesis               185     void setuint256(uint256 n)
genesis               186     {
genesis               187         unsigned char pch[sizeof(n) + 6];
genesis               188         unsigned char* p = pch + 4;
genesis               189         bool fLeadingZeroes = true;
genesis               190         unsigned char* pbegin = (unsigned char*)&n;
genesis               191         unsigned char* psrc = pbegin + sizeof(n);
genesis               192         while (psrc != pbegin)
genesis               193         {
genesis               194             unsigned char c = *(--psrc);
genesis               195             if (fLeadingZeroes)
genesis               196             {
genesis               197                 if (c == 0)
genesis               198                     continue;
genesis               199                 if (c & 0x80)
genesis               200                     *p++ = 0;
genesis               201                 fLeadingZeroes = false;
genesis               202             }
genesis               203             *p++ = c;
genesis               204         }
genesis               205         unsigned int nSize = p - (pch + 4);
genesis               206         pch[0] = (nSize >> 24) & 0xff;
genesis               207         pch[1] = (nSize >> 16) & 0xff;
genesis               208         pch[2] = (nSize >> 8) & 0xff;
genesis               209         pch[3] = (nSize >> 0) & 0xff;
genesis               210         BN_mpi2bn(pch, p - pch, this);
genesis               211     }
genesis               212 
genesis               213     uint256 getuint256()
genesis               214     {
genesis               215         unsigned int nSize = BN_bn2mpi(this, NULL);
genesis               216         if (nSize < 4)
genesis               217             return 0;
genesis               218         std::vector<unsigned char> vch(nSize);
genesis               219         BN_bn2mpi(this, &vch[0]);
genesis               220         if (vch.size() > 4)
genesis               221             vch[4] &= 0x7f;
genesis               222         uint256 n = 0;
genesis               223         for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
genesis               224             ((unsigned char*)&n)[i] = vch[j];
genesis               225         return n;
genesis               226     }
genesis               227 
genesis               228     void setvch(const std::vector<unsigned char>& vch)
genesis               229     {
genesis               230         std::vector<unsigned char> vch2(vch.size() + 4);
genesis               231         unsigned int nSize = vch.size();
genesis               232         
genesis               233         
genesis               234         vch2[0] = (nSize >> 24) & 0xff;
genesis               235         vch2[1] = (nSize >> 16) & 0xff;
genesis               236         vch2[2] = (nSize >> 8) & 0xff;
genesis               237         vch2[3] = (nSize >> 0) & 0xff;
genesis               238         
genesis               239         reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
genesis               240         BN_mpi2bn(&vch2[0], vch2.size(), this);
genesis               241     }
genesis               242 
genesis               243     std::vector<unsigned char> getvch() const
genesis               244     {
genesis               245         unsigned int nSize = BN_bn2mpi(this, NULL);
genesis               246         if (nSize < 4)
genesis               247             return std::vector<unsigned char>();
genesis               248         std::vector<unsigned char> vch(nSize);
genesis               249         BN_bn2mpi(this, &vch[0]);
genesis               250         vch.erase(vch.begin(), vch.begin() + 4);
genesis               251         reverse(vch.begin(), vch.end());
genesis               252         return vch;
genesis               253     }
genesis               254 
genesis               255     CBigNum& SetCompact(unsigned int nCompact)
genesis               256     {
genesis               257         unsigned int nSize = nCompact >> 24;
genesis               258         std::vector<unsigned char> vch(4 + nSize);
genesis               259         vch[3] = nSize;
genesis               260         if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
genesis               261         if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
genesis               262         if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
genesis               263         BN_mpi2bn(&vch[0], vch.size(), this);
genesis               264         return *this;
genesis               265     }
genesis               266 
genesis               267     unsigned int GetCompact() const
genesis               268     {
genesis               269         unsigned int nSize = BN_bn2mpi(this, NULL);
genesis               270         std::vector<unsigned char> vch(nSize);
genesis               271         nSize -= 4;
genesis               272         BN_bn2mpi(this, &vch[0]);
genesis               273         unsigned int nCompact = nSize << 24;
genesis               274         if (nSize >= 1) nCompact |= (vch[4] << 16);
genesis               275         if (nSize >= 2) nCompact |= (vch[5] << 8);
genesis               276         if (nSize >= 3) nCompact |= (vch[6] << 0);
genesis               277         return nCompact;
genesis               278     }
genesis               279 
genesis               280     void SetHex(const std::string& str)
genesis               281     {
genesis               282         
genesis               283         const char* psz = str.c_str();
genesis               284         while (isspace(*psz))
genesis               285             psz++;
genesis               286         bool fNegative = false;
genesis               287         if (*psz == '-')
genesis               288         {
genesis               289             fNegative = true;
genesis               290             psz++;
genesis               291         }
genesis               292         if (psz[0] == '0' && tolower(psz[1]) == 'x')
genesis               293             psz += 2;
genesis               294         while (isspace(*psz))
genesis               295             psz++;
genesis               296 
genesis               297         
genesis               298         static 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 };
genesis               299         *this = 0;
genesis               300         while (isxdigit(*psz))
genesis               301         {
genesis               302             *this <<= 4;
genesis               303             int n = phexdigit[*psz++];
genesis               304             *this += n;
genesis               305         }
genesis               306         if (fNegative)
genesis               307             *this = 0 - *this;
genesis               308     }
genesis               309 
genesis               310     std::string ToString(int nBase=10) const
genesis               311     {
genesis               312         CAutoBN_CTX pctx;
genesis               313         CBigNum bnBase = nBase;
genesis               314         CBigNum bn0 = 0;
genesis               315         std::string str;
genesis               316         CBigNum bn = *this;
genesis               317         BN_set_negative(&bn, false);
genesis               318         CBigNum dv;
genesis               319         CBigNum rem;
genesis               320         if (BN_cmp(&bn, &bn0) == 0)
genesis               321             return "0";
genesis               322         while (BN_cmp(&bn, &bn0) > 0)
genesis               323         {
genesis               324             if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
genesis               325                 throw bignum_error("CBigNum::ToString() : BN_div failed");
genesis               326             bn = dv;
genesis               327             unsigned int c = rem.getulong();
genesis               328             str += "0123456789abcdef"[c];
genesis               329         }
genesis               330         if (BN_is_negative(this))
genesis               331             str += "-";
genesis               332         reverse(str.begin(), str.end());
genesis               333         return str;
genesis               334     }
genesis               335 
genesis               336     std::string GetHex() const
genesis               337     {
genesis               338         return ToString(16);
genesis               339     }
genesis               340 
genesis               341     unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
genesis               342     {
genesis               343         return ::GetSerializeSize(getvch(), nType, nVersion);
genesis               344     }
genesis               345 
genesis               346     template<typename Stream>
genesis               347     void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
genesis               348     {
genesis               349         ::Serialize(s, getvch(), nType, nVersion);
genesis               350     }
genesis               351 
genesis               352     template<typename Stream>
genesis               353     void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
genesis               354     {
genesis               355         std::vector<unsigned char> vch;
genesis               356         ::Unserialize(s, vch, nType, nVersion);
genesis               357         setvch(vch);
genesis               358     }
genesis               359 
genesis               360 
genesis               361     bool operator!() const
genesis               362     {
genesis               363         return BN_is_zero(this);
genesis               364     }
genesis               365 
genesis               366     CBigNum& operator+=(const CBigNum& b)
genesis               367     {
genesis               368         if (!BN_add(this, this, &b))
genesis               369             throw bignum_error("CBigNum::operator+= : BN_add failed");
genesis               370         return *this;
genesis               371     }
genesis               372 
genesis               373     CBigNum& operator-=(const CBigNum& b)
genesis               374     {
genesis               375         *this = *this - b;
genesis               376         return *this;
genesis               377     }
genesis               378 
genesis               379     CBigNum& operator*=(const CBigNum& b)
genesis               380     {
genesis               381         CAutoBN_CTX pctx;
genesis               382         if (!BN_mul(this, this, &b, pctx))
genesis               383             throw bignum_error("CBigNum::operator*= : BN_mul failed");
genesis               384         return *this;
genesis               385     }
genesis               386 
genesis               387     CBigNum& operator/=(const CBigNum& b)
genesis               388     {
genesis               389         *this = *this / b;
genesis               390         return *this;
genesis               391     }
genesis               392 
genesis               393     CBigNum& operator%=(const CBigNum& b)
genesis               394     {
genesis               395         *this = *this % b;
genesis               396         return *this;
genesis               397     }
genesis               398 
genesis               399     CBigNum& operator<<=(unsigned int shift)
genesis               400     {
genesis               401         if (!BN_lshift(this, this, shift))
genesis               402             throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
genesis               403         return *this;
genesis               404     }
genesis               405 
genesis               406     CBigNum& operator>>=(unsigned int shift)
genesis               407     {
genesis               408         
genesis               409         
genesis               410         CBigNum a = 1;
genesis               411         a <<= shift;
genesis               412         if (BN_cmp(&a, this) > 0)
genesis               413         {
genesis               414             *this = 0;
genesis               415             return *this;
genesis               416         }
genesis               417 
genesis               418         if (!BN_rshift(this, this, shift))
genesis               419             throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
genesis               420         return *this;
genesis               421     }
genesis               422 
genesis               423 
genesis               424     CBigNum& operator++()
genesis               425     {
genesis               426         
genesis               427         if (!BN_add(this, this, BN_value_one()))
genesis               428             throw bignum_error("CBigNum::operator++ : BN_add failed");
genesis               429         return *this;
genesis               430     }
genesis               431 
genesis               432     const CBigNum operator++(int)
genesis               433     {
genesis               434         
genesis               435         const CBigNum ret = *this;
genesis               436         ++(*this);
genesis               437         return ret;
genesis               438     }
genesis               439 
genesis               440     CBigNum& operator--()
genesis               441     {
genesis               442         
genesis               443         CBigNum r;
genesis               444         if (!BN_sub(&r, this, BN_value_one()))
genesis               445             throw bignum_error("CBigNum::operator-- : BN_sub failed");
genesis               446         *this = r;
genesis               447         return *this;
genesis               448     }
genesis               449 
genesis               450     const CBigNum operator--(int)
genesis               451     {
genesis               452         
genesis               453         const CBigNum ret = *this;
genesis               454         --(*this);
genesis               455         return ret;
genesis               456     }
genesis               457 
genesis               458 
genesis               459     friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
genesis               460     friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
genesis               461     friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
genesis               462 };
genesis               463 
genesis               464 
genesis               465 
genesis               466 inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
genesis               467 {
genesis               468     CBigNum r;
genesis               469     if (!BN_add(&r, &a, &b))
genesis               470         throw bignum_error("CBigNum::operator+ : BN_add failed");
genesis               471     return r;
genesis               472 }
genesis               473 
genesis               474 inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
genesis               475 {
genesis               476     CBigNum r;
genesis               477     if (!BN_sub(&r, &a, &b))
genesis               478         throw bignum_error("CBigNum::operator- : BN_sub failed");
genesis               479     return r;
genesis               480 }
genesis               481 
genesis               482 inline const CBigNum operator-(const CBigNum& a)
genesis               483 {
genesis               484     CBigNum r(a);
genesis               485     BN_set_negative(&r, !BN_is_negative(&r));
genesis               486     return r;
genesis               487 }
genesis               488 
genesis               489 inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
genesis               490 {
genesis               491     CAutoBN_CTX pctx;
genesis               492     CBigNum r;
genesis               493     if (!BN_mul(&r, &a, &b, pctx))
genesis               494         throw bignum_error("CBigNum::operator* : BN_mul failed");
genesis               495     return r;
genesis               496 }
genesis               497 
genesis               498 inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
genesis               499 {
genesis               500     CAutoBN_CTX pctx;
genesis               501     CBigNum r;
genesis               502     if (!BN_div(&r, NULL, &a, &b, pctx))
genesis               503         throw bignum_error("CBigNum::operator/ : BN_div failed");
genesis               504     return r;
genesis               505 }
genesis               506 
genesis               507 inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
genesis               508 {
genesis               509     CAutoBN_CTX pctx;
genesis               510     CBigNum r;
genesis               511     if (!BN_mod(&r, &a, &b, pctx))
genesis               512         throw bignum_error("CBigNum::operator% : BN_div failed");
genesis               513     return r;
genesis               514 }
genesis               515 
genesis               516 inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
genesis               517 {
genesis               518     CBigNum r;
genesis               519     if (!BN_lshift(&r, &a, shift))
genesis               520         throw bignum_error("CBigNum:operator<< : BN_lshift failed");
genesis               521     return r;
genesis               522 }
genesis               523 
genesis               524 inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
genesis               525 {
genesis               526     CBigNum r = a;
genesis               527     r >>= shift;
genesis               528     return r;
genesis               529 }
genesis               530 
genesis               531 inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
genesis               532 inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
genesis               533 inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
genesis               534 inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
genesis               535 inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) < 0); }
genesis               536 inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) > 0); }
genesis               537 
genesis               538 #endif