]> Git Repo - VerusCoin.git/blobdiff - bignum.h
propset svn:eol-style native
[VerusCoin.git] / bignum.h
index 0701f7930fe1b587107a0781e4a17344a1fdc50b..450e809d3de6655067c2eab95dbd6e2bd227bf16 100644 (file)
--- a/bignum.h
+++ b/bignum.h
-// Copyright (c) 2009-2010 Satoshi Nakamoto\r
-// Distributed under the MIT/X11 software license, see the accompanying\r
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
-\r
-#include <stdexcept>\r
-#include <vector>\r
-#include <openssl/bn.h>\r
-\r
-\r
-\r
-\r
-\r
-class bignum_error : public std::runtime_error\r
-{\r
-public:\r
-    explicit bignum_error(const std::string& str) : std::runtime_error(str) {}\r
-};\r
-\r
-\r
-\r
-class CAutoBN_CTX\r
-{\r
-protected:\r
-    BN_CTX* pctx;\r
-    BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }\r
-\r
-public:\r
-    CAutoBN_CTX()\r
-    {\r
-        pctx = BN_CTX_new();\r
-        if (pctx == NULL)\r
-            throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");\r
-    }\r
-\r
-    ~CAutoBN_CTX()\r
-    {\r
-        if (pctx != NULL)\r
-            BN_CTX_free(pctx);\r
-    }\r
-\r
-    operator BN_CTX*() { return pctx; }\r
-    BN_CTX& operator*() { return *pctx; }\r
-    BN_CTX** operator&() { return &pctx; }\r
-    bool operator!() { return (pctx == NULL); }\r
-};\r
-\r
-\r
-\r
-class CBigNum : public BIGNUM\r
-{\r
-public:\r
-    CBigNum()\r
-    {\r
-        BN_init(this);\r
-    }\r
-\r
-    CBigNum(const CBigNum& b)\r
-    {\r
-        BN_init(this);\r
-        if (!BN_copy(this, &b))\r
-        {\r
-            BN_clear_free(this);\r
-            throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");\r
-        }\r
-    }\r
-\r
-    CBigNum& operator=(const CBigNum& b)\r
-    {\r
-        if (!BN_copy(this, &b))\r
-            throw bignum_error("CBigNum::operator= : BN_copy failed");\r
-        return (*this);\r
-    }\r
-\r
-    ~CBigNum()\r
-    {\r
-        BN_clear_free(this);\r
-    }\r
-\r
-    CBigNum(char n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }\r
-    CBigNum(short n)            { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }\r
-    CBigNum(int n)              { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }\r
-    CBigNum(long n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }\r
-    CBigNum(int64 n)            { BN_init(this); setint64(n); }\r
-    CBigNum(unsigned char n)    { BN_init(this); setulong(n); }\r
-    CBigNum(unsigned short n)   { BN_init(this); setulong(n); }\r
-    CBigNum(unsigned int n)     { BN_init(this); setulong(n); }\r
-    CBigNum(unsigned long n)    { BN_init(this); setulong(n); }\r
-    CBigNum(uint64 n)           { BN_init(this); setuint64(n); }\r
-    explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }\r
-\r
-    explicit CBigNum(const std::vector<unsigned char>& vch)\r
-    {\r
-        BN_init(this);\r
-        setvch(vch);\r
-    }\r
-\r
-    void setulong(unsigned long n)\r
-    {\r
-        if (!BN_set_word(this, n))\r
-            throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");\r
-    }\r
-\r
-    unsigned long getulong() const\r
-    {\r
-        return BN_get_word(this);\r
-    }\r
-\r
-    unsigned int getuint() const\r
-    {\r
-        return BN_get_word(this);\r
-    }\r
-\r
-    int getint() const\r
-    {\r
-        unsigned long n = BN_get_word(this);\r
-        if (!BN_is_negative(this))\r
-            return (n > INT_MAX ? INT_MAX : n);\r
-        else\r
-            return (n > INT_MAX ? INT_MIN : -(int)n);\r
-    }\r
-\r
-    void setint64(int64 n)\r
-    {\r
-        unsigned char pch[sizeof(n) + 6];\r
-        unsigned char* p = pch + 4;\r
-        bool fNegative = false;\r
-        if (n < (int64)0)\r
-        {\r
-            n = -n;\r
-            fNegative = true;\r
-        }\r
-        bool fLeadingZeroes = true;\r
-        for (int i = 0; i < 8; i++)\r
-        {\r
-            unsigned char c = (n >> 56) & 0xff;\r
-            n <<= 8;\r
-            if (fLeadingZeroes)\r
-            {\r
-                if (c == 0)\r
-                    continue;\r
-                if (c & 0x80)\r
-                    *p++ = (fNegative ? 0x80 : 0);\r
-                else if (fNegative)\r
-                    c |= 0x80;\r
-                fLeadingZeroes = false;\r
-            }\r
-            *p++ = c;\r
-        }\r
-        unsigned int nSize = p - (pch + 4);\r
-        pch[0] = (nSize >> 24) & 0xff;\r
-        pch[1] = (nSize >> 16) & 0xff;\r
-        pch[2] = (nSize >> 8) & 0xff;\r
-        pch[3] = (nSize) & 0xff;\r
-        BN_mpi2bn(pch, p - pch, this);\r
-    }\r
-\r
-    void setuint64(uint64 n)\r
-    {\r
-        unsigned char pch[sizeof(n) + 6];\r
-        unsigned char* p = pch + 4;\r
-        bool fLeadingZeroes = true;\r
-        for (int i = 0; i < 8; i++)\r
-        {\r
-            unsigned char c = (n >> 56) & 0xff;\r
-            n <<= 8;\r
-            if (fLeadingZeroes)\r
-            {\r
-                if (c == 0)\r
-                    continue;\r
-                if (c & 0x80)\r
-                    *p++ = 0;\r
-                fLeadingZeroes = false;\r
-            }\r
-            *p++ = c;\r
-        }\r
-        unsigned int nSize = p - (pch + 4);\r
-        pch[0] = (nSize >> 24) & 0xff;\r
-        pch[1] = (nSize >> 16) & 0xff;\r
-        pch[2] = (nSize >> 8) & 0xff;\r
-        pch[3] = (nSize) & 0xff;\r
-        BN_mpi2bn(pch, p - pch, this);\r
-    }\r
-\r
-    void setuint256(uint256 n)\r
-    {\r
-        unsigned char pch[sizeof(n) + 6];\r
-        unsigned char* p = pch + 4;\r
-        bool fLeadingZeroes = true;\r
-        unsigned char* pbegin = (unsigned char*)&n;\r
-        unsigned char* psrc = pbegin + sizeof(n);\r
-        while (psrc != pbegin)\r
-        {\r
-            unsigned char c = *(--psrc);\r
-            if (fLeadingZeroes)\r
-            {\r
-                if (c == 0)\r
-                    continue;\r
-                if (c & 0x80)\r
-                    *p++ = 0;\r
-                fLeadingZeroes = false;\r
-            }\r
-            *p++ = c;\r
-        }\r
-        unsigned int nSize = p - (pch + 4);\r
-        pch[0] = (nSize >> 24) & 0xff;\r
-        pch[1] = (nSize >> 16) & 0xff;\r
-        pch[2] = (nSize >> 8) & 0xff;\r
-        pch[3] = (nSize >> 0) & 0xff;\r
-        BN_mpi2bn(pch, p - pch, this);\r
-    }\r
-\r
-    uint256 getuint256()\r
-    {\r
-        unsigned int nSize = BN_bn2mpi(this, NULL);\r
-        if (nSize < 4)\r
-            return 0;\r
-        std::vector<unsigned char> vch(nSize);\r
-        BN_bn2mpi(this, &vch[0]);\r
-        if (vch.size() > 4)\r
-            vch[4] &= 0x7f;\r
-        uint256 n = 0;\r
-        for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)\r
-            ((unsigned char*)&n)[i] = vch[j];\r
-        return n;\r
-    }\r
-\r
-    void setvch(const std::vector<unsigned char>& vch)\r
-    {\r
-        std::vector<unsigned char> vch2(vch.size() + 4);\r
-        unsigned int nSize = vch.size();\r
-        vch2[0] = (nSize >> 24) & 0xff;\r
-        vch2[1] = (nSize >> 16) & 0xff;\r
-        vch2[2] = (nSize >> 8) & 0xff;\r
-        vch2[3] = (nSize >> 0) & 0xff;\r
-        reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);\r
-        BN_mpi2bn(&vch2[0], vch2.size(), this);\r
-    }\r
-\r
-    std::vector<unsigned char> getvch() const\r
-    {\r
-        unsigned int nSize = BN_bn2mpi(this, NULL);\r
-        if (nSize < 4)\r
-            return std::vector<unsigned char>();\r
-        std::vector<unsigned char> vch(nSize);\r
-        BN_bn2mpi(this, &vch[0]);\r
-        vch.erase(vch.begin(), vch.begin() + 4);\r
-        reverse(vch.begin(), vch.end());\r
-        return vch;\r
-    }\r
-\r
-    CBigNum& SetCompact(unsigned int nCompact)\r
-    {\r
-        unsigned int nSize = nCompact >> 24;\r
-        std::vector<unsigned char> vch(4 + nSize);\r
-        vch[3] = nSize;\r
-        if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;\r
-        if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;\r
-        if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;\r
-        BN_mpi2bn(&vch[0], vch.size(), this);\r
-        return *this;\r
-    }\r
-\r
-    unsigned int GetCompact() const\r
-    {\r
-        unsigned int nSize = BN_bn2mpi(this, NULL);\r
-        std::vector<unsigned char> vch(nSize);\r
-        nSize -= 4;\r
-        BN_bn2mpi(this, &vch[0]);\r
-        unsigned int nCompact = nSize << 24;\r
-        if (nSize >= 1) nCompact |= (vch[4] << 16);\r
-        if (nSize >= 2) nCompact |= (vch[5] << 8);\r
-        if (nSize >= 3) nCompact |= (vch[6] << 0);\r
-        return nCompact;\r
-    }\r
-\r
-    void SetHex(const std::string& str)\r
-    {\r
-        // skip 0x\r
-        const char* psz = str.c_str();\r
-        while (isspace(*psz))\r
-            psz++;\r
-        bool fNegative = false;\r
-        if (*psz == '-')\r
-        {\r
-            fNegative = true;\r
-            psz++;\r
-        }\r
-        if (psz[0] == '0' && tolower(psz[1]) == 'x')\r
-            psz += 2;\r
-        while (isspace(*psz))\r
-            psz++;\r
-\r
-        // hex string to bignum\r
-        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 };\r
-        *this = 0;\r
-        while (isxdigit(*psz))\r
-        {\r
-            *this <<= 4;\r
-            int n = phexdigit[*psz++];\r
-            *this += n;\r
-        }\r
-        if (fNegative)\r
-            *this = 0 - *this;\r
-    }\r
-\r
-    std::string ToString(int nBase=10) const\r
-    {\r
-        CAutoBN_CTX pctx;\r
-        CBigNum bnBase = nBase;\r
-        CBigNum bn0 = 0;\r
-        string str;\r
-        CBigNum bn = *this;\r
-        BN_set_negative(&bn, false);\r
-        CBigNum dv;\r
-        CBigNum rem;\r
-        if (BN_cmp(&bn, &bn0) == 0)\r
-            return "0";\r
-        while (BN_cmp(&bn, &bn0) > 0)\r
-        {\r
-            if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))\r
-                throw bignum_error("CBigNum::ToString() : BN_div failed");\r
-            bn = dv;\r
-            unsigned int c = rem.getulong();\r
-            str += "0123456789abcdef"[c];\r
-        }\r
-        if (BN_is_negative(this))\r
-            str += "-";\r
-        reverse(str.begin(), str.end());\r
-        return str;\r
-    }\r
-\r
-    std::string GetHex() const\r
-    {\r
-        return ToString(16);\r
-    }\r
-\r
-    unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const\r
-    {\r
-        return ::GetSerializeSize(getvch(), nType, nVersion);\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const\r
-    {\r
-        ::Serialize(s, getvch(), nType, nVersion);\r
-    }\r
-\r
-    template<typename Stream>\r
-    void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)\r
-    {\r
-        vector<unsigned char> vch;\r
-        ::Unserialize(s, vch, nType, nVersion);\r
-        setvch(vch);\r
-    }\r
-\r
-\r
-    bool operator!() const\r
-    {\r
-        return BN_is_zero(this);\r
-    }\r
-\r
-    CBigNum& operator+=(const CBigNum& b)\r
-    {\r
-        if (!BN_add(this, this, &b))\r
-            throw bignum_error("CBigNum::operator+= : BN_add failed");\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator-=(const CBigNum& b)\r
-    {\r
-        *this = *this - b;\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator*=(const CBigNum& b)\r
-    {\r
-        CAutoBN_CTX pctx;\r
-        if (!BN_mul(this, this, &b, pctx))\r
-            throw bignum_error("CBigNum::operator*= : BN_mul failed");\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator/=(const CBigNum& b)\r
-    {\r
-        *this = *this / b;\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator%=(const CBigNum& b)\r
-    {\r
-        *this = *this % b;\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator<<=(unsigned int shift)\r
-    {\r
-        if (!BN_lshift(this, this, shift))\r
-            throw bignum_error("CBigNum:operator<<= : BN_lshift failed");\r
-        return *this;\r
-    }\r
-\r
-    CBigNum& operator>>=(unsigned int shift)\r
-    {\r
-        // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number\r
-        //   if built on ubuntu 9.04 or 9.10, probably depends on version of openssl\r
-        CBigNum a = 1;\r
-        a <<= shift;\r
-        if (BN_cmp(&a, this) > 0)\r
-        {\r
-            *this = 0;\r
-            return *this;\r
-        }\r
-\r
-        if (!BN_rshift(this, this, shift))\r
-            throw bignum_error("CBigNum:operator>>= : BN_rshift failed");\r
-        return *this;\r
-    }\r
-\r
-\r
-    CBigNum& operator++()\r
-    {\r
-        // prefix operator\r
-        if (!BN_add(this, this, BN_value_one()))\r
-            throw bignum_error("CBigNum::operator++ : BN_add failed");\r
-        return *this;\r
-    }\r
-\r
-    const CBigNum operator++(int)\r
-    {\r
-        // postfix operator\r
-        const CBigNum ret = *this;\r
-        ++(*this);\r
-        return ret;\r
-    }\r
-\r
-    CBigNum& operator--()\r
-    {\r
-        // prefix operator\r
-        CBigNum r;\r
-        if (!BN_sub(&r, this, BN_value_one()))\r
-            throw bignum_error("CBigNum::operator-- : BN_sub failed");\r
-        *this = r;\r
-        return *this;\r
-    }\r
-\r
-    const CBigNum operator--(int)\r
-    {\r
-        // postfix operator\r
-        const CBigNum ret = *this;\r
-        --(*this);\r
-        return ret;\r
-    }\r
-\r
-\r
-    friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);\r
-    friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);\r
-    friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);\r
-};\r
-\r
-\r
-\r
-inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)\r
-{\r
-    CBigNum r;\r
-    if (!BN_add(&r, &a, &b))\r
-        throw bignum_error("CBigNum::operator+ : BN_add failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)\r
-{\r
-    CBigNum r;\r
-    if (!BN_sub(&r, &a, &b))\r
-        throw bignum_error("CBigNum::operator- : BN_sub failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator-(const CBigNum& a)\r
-{\r
-    CBigNum r(a);\r
-    BN_set_negative(&r, !BN_is_negative(&r));\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)\r
-{\r
-    CAutoBN_CTX pctx;\r
-    CBigNum r;\r
-    if (!BN_mul(&r, &a, &b, pctx))\r
-        throw bignum_error("CBigNum::operator* : BN_mul failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)\r
-{\r
-    CAutoBN_CTX pctx;\r
-    CBigNum r;\r
-    if (!BN_div(&r, NULL, &a, &b, pctx))\r
-        throw bignum_error("CBigNum::operator/ : BN_div failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)\r
-{\r
-    CAutoBN_CTX pctx;\r
-    CBigNum r;\r
-    if (!BN_mod(&r, &a, &b, pctx))\r
-        throw bignum_error("CBigNum::operator% : BN_div failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)\r
-{\r
-    CBigNum r;\r
-    if (!BN_lshift(&r, &a, shift))\r
-        throw bignum_error("CBigNum:operator<< : BN_lshift failed");\r
-    return r;\r
-}\r
-\r
-inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)\r
-{\r
-    CBigNum r = a;\r
-    r >>= shift;\r
-    return r;\r
-}\r
-\r
-inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }\r
-inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }\r
-inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }\r
-inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }\r
-inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) < 0); }\r
-inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) > 0); }\r
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+#include <stdexcept>
+#include <vector>
+#include <openssl/bn.h>
+
+
+
+
+
+class bignum_error : public std::runtime_error
+{
+public:
+    explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
+};
+
+
+
+class CAutoBN_CTX
+{
+protected:
+    BN_CTX* pctx;
+    BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
+
+public:
+    CAutoBN_CTX()
+    {
+        pctx = BN_CTX_new();
+        if (pctx == NULL)
+            throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
+    }
+
+    ~CAutoBN_CTX()
+    {
+        if (pctx != NULL)
+            BN_CTX_free(pctx);
+    }
+
+    operator BN_CTX*() { return pctx; }
+    BN_CTX& operator*() { return *pctx; }
+    BN_CTX** operator&() { return &pctx; }
+    bool operator!() { return (pctx == NULL); }
+};
+
+
+
+class CBigNum : public BIGNUM
+{
+public:
+    CBigNum()
+    {
+        BN_init(this);
+    }
+
+    CBigNum(const CBigNum& b)
+    {
+        BN_init(this);
+        if (!BN_copy(this, &b))
+        {
+            BN_clear_free(this);
+            throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
+        }
+    }
+
+    CBigNum& operator=(const CBigNum& b)
+    {
+        if (!BN_copy(this, &b))
+            throw bignum_error("CBigNum::operator= : BN_copy failed");
+        return (*this);
+    }
+
+    ~CBigNum()
+    {
+        BN_clear_free(this);
+    }
+
+    CBigNum(char n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
+    CBigNum(short n)            { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
+    CBigNum(int n)              { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
+    CBigNum(long n)             { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
+    CBigNum(int64 n)            { BN_init(this); setint64(n); }
+    CBigNum(unsigned char n)    { BN_init(this); setulong(n); }
+    CBigNum(unsigned short n)   { BN_init(this); setulong(n); }
+    CBigNum(unsigned int n)     { BN_init(this); setulong(n); }
+    CBigNum(unsigned long n)    { BN_init(this); setulong(n); }
+    CBigNum(uint64 n)           { BN_init(this); setuint64(n); }
+    explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
+
+    explicit CBigNum(const std::vector<unsigned char>& vch)
+    {
+        BN_init(this);
+        setvch(vch);
+    }
+
+    void setulong(unsigned long n)
+    {
+        if (!BN_set_word(this, n))
+            throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
+    }
+
+    unsigned long getulong() const
+    {
+        return BN_get_word(this);
+    }
+
+    unsigned int getuint() const
+    {
+        return BN_get_word(this);
+    }
+
+    int getint() const
+    {
+        unsigned long n = BN_get_word(this);
+        if (!BN_is_negative(this))
+            return (n > INT_MAX ? INT_MAX : n);
+        else
+            return (n > INT_MAX ? INT_MIN : -(int)n);
+    }
+
+    void setint64(int64 n)
+    {
+        unsigned char pch[sizeof(n) + 6];
+        unsigned char* p = pch + 4;
+        bool fNegative = false;
+        if (n < (int64)0)
+        {
+            n = -n;
+            fNegative = true;
+        }
+        bool fLeadingZeroes = true;
+        for (int i = 0; i < 8; i++)
+        {
+            unsigned char c = (n >> 56) & 0xff;
+            n <<= 8;
+            if (fLeadingZeroes)
+            {
+                if (c == 0)
+                    continue;
+                if (c & 0x80)
+                    *p++ = (fNegative ? 0x80 : 0);
+                else if (fNegative)
+                    c |= 0x80;
+                fLeadingZeroes = false;
+            }
+            *p++ = c;
+        }
+        unsigned int nSize = p - (pch + 4);
+        pch[0] = (nSize >> 24) & 0xff;
+        pch[1] = (nSize >> 16) & 0xff;
+        pch[2] = (nSize >> 8) & 0xff;
+        pch[3] = (nSize) & 0xff;
+        BN_mpi2bn(pch, p - pch, this);
+    }
+
+    void setuint64(uint64 n)
+    {
+        unsigned char pch[sizeof(n) + 6];
+        unsigned char* p = pch + 4;
+        bool fLeadingZeroes = true;
+        for (int i = 0; i < 8; i++)
+        {
+            unsigned char c = (n >> 56) & 0xff;
+            n <<= 8;
+            if (fLeadingZeroes)
+            {
+                if (c == 0)
+                    continue;
+                if (c & 0x80)
+                    *p++ = 0;
+                fLeadingZeroes = false;
+            }
+            *p++ = c;
+        }
+        unsigned int nSize = p - (pch + 4);
+        pch[0] = (nSize >> 24) & 0xff;
+        pch[1] = (nSize >> 16) & 0xff;
+        pch[2] = (nSize >> 8) & 0xff;
+        pch[3] = (nSize) & 0xff;
+        BN_mpi2bn(pch, p - pch, this);
+    }
+
+    void setuint256(uint256 n)
+    {
+        unsigned char pch[sizeof(n) + 6];
+        unsigned char* p = pch + 4;
+        bool fLeadingZeroes = true;
+        unsigned char* pbegin = (unsigned char*)&n;
+        unsigned char* psrc = pbegin + sizeof(n);
+        while (psrc != pbegin)
+        {
+            unsigned char c = *(--psrc);
+            if (fLeadingZeroes)
+            {
+                if (c == 0)
+                    continue;
+                if (c & 0x80)
+                    *p++ = 0;
+                fLeadingZeroes = false;
+            }
+            *p++ = c;
+        }
+        unsigned int nSize = p - (pch + 4);
+        pch[0] = (nSize >> 24) & 0xff;
+        pch[1] = (nSize >> 16) & 0xff;
+        pch[2] = (nSize >> 8) & 0xff;
+        pch[3] = (nSize >> 0) & 0xff;
+        BN_mpi2bn(pch, p - pch, this);
+    }
+
+    uint256 getuint256()
+    {
+        unsigned int nSize = BN_bn2mpi(this, NULL);
+        if (nSize < 4)
+            return 0;
+        std::vector<unsigned char> vch(nSize);
+        BN_bn2mpi(this, &vch[0]);
+        if (vch.size() > 4)
+            vch[4] &= 0x7f;
+        uint256 n = 0;
+        for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
+            ((unsigned char*)&n)[i] = vch[j];
+        return n;
+    }
+
+    void setvch(const std::vector<unsigned char>& vch)
+    {
+        std::vector<unsigned char> vch2(vch.size() + 4);
+        unsigned int nSize = vch.size();
+        vch2[0] = (nSize >> 24) & 0xff;
+        vch2[1] = (nSize >> 16) & 0xff;
+        vch2[2] = (nSize >> 8) & 0xff;
+        vch2[3] = (nSize >> 0) & 0xff;
+        reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
+        BN_mpi2bn(&vch2[0], vch2.size(), this);
+    }
+
+    std::vector<unsigned char> getvch() const
+    {
+        unsigned int nSize = BN_bn2mpi(this, NULL);
+        if (nSize < 4)
+            return std::vector<unsigned char>();
+        std::vector<unsigned char> vch(nSize);
+        BN_bn2mpi(this, &vch[0]);
+        vch.erase(vch.begin(), vch.begin() + 4);
+        reverse(vch.begin(), vch.end());
+        return vch;
+    }
+
+    CBigNum& SetCompact(unsigned int nCompact)
+    {
+        unsigned int nSize = nCompact >> 24;
+        std::vector<unsigned char> vch(4 + nSize);
+        vch[3] = nSize;
+        if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
+        if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
+        if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
+        BN_mpi2bn(&vch[0], vch.size(), this);
+        return *this;
+    }
+
+    unsigned int GetCompact() const
+    {
+        unsigned int nSize = BN_bn2mpi(this, NULL);
+        std::vector<unsigned char> vch(nSize);
+        nSize -= 4;
+        BN_bn2mpi(this, &vch[0]);
+        unsigned int nCompact = nSize << 24;
+        if (nSize >= 1) nCompact |= (vch[4] << 16);
+        if (nSize >= 2) nCompact |= (vch[5] << 8);
+        if (nSize >= 3) nCompact |= (vch[6] << 0);
+        return nCompact;
+    }
+
+    void SetHex(const std::string& str)
+    {
+        // skip 0x
+        const char* psz = str.c_str();
+        while (isspace(*psz))
+            psz++;
+        bool fNegative = false;
+        if (*psz == '-')
+        {
+            fNegative = true;
+            psz++;
+        }
+        if (psz[0] == '0' && tolower(psz[1]) == 'x')
+            psz += 2;
+        while (isspace(*psz))
+            psz++;
+
+        // hex string to bignum
+        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 };
+        *this = 0;
+        while (isxdigit(*psz))
+        {
+            *this <<= 4;
+            int n = phexdigit[*psz++];
+            *this += n;
+        }
+        if (fNegative)
+            *this = 0 - *this;
+    }
+
+    std::string ToString(int nBase=10) const
+    {
+        CAutoBN_CTX pctx;
+        CBigNum bnBase = nBase;
+        CBigNum bn0 = 0;
+        string str;
+        CBigNum bn = *this;
+        BN_set_negative(&bn, false);
+        CBigNum dv;
+        CBigNum rem;
+        if (BN_cmp(&bn, &bn0) == 0)
+            return "0";
+        while (BN_cmp(&bn, &bn0) > 0)
+        {
+            if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
+                throw bignum_error("CBigNum::ToString() : BN_div failed");
+            bn = dv;
+            unsigned int c = rem.getulong();
+            str += "0123456789abcdef"[c];
+        }
+        if (BN_is_negative(this))
+            str += "-";
+        reverse(str.begin(), str.end());
+        return str;
+    }
+
+    std::string GetHex() const
+    {
+        return ToString(16);
+    }
+
+    unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
+    {
+        return ::GetSerializeSize(getvch(), nType, nVersion);
+    }
+
+    template<typename Stream>
+    void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
+    {
+        ::Serialize(s, getvch(), nType, nVersion);
+    }
+
+    template<typename Stream>
+    void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
+    {
+        vector<unsigned char> vch;
+        ::Unserialize(s, vch, nType, nVersion);
+        setvch(vch);
+    }
+
+
+    bool operator!() const
+    {
+        return BN_is_zero(this);
+    }
+
+    CBigNum& operator+=(const CBigNum& b)
+    {
+        if (!BN_add(this, this, &b))
+            throw bignum_error("CBigNum::operator+= : BN_add failed");
+        return *this;
+    }
+
+    CBigNum& operator-=(const CBigNum& b)
+    {
+        *this = *this - b;
+        return *this;
+    }
+
+    CBigNum& operator*=(const CBigNum& b)
+    {
+        CAutoBN_CTX pctx;
+        if (!BN_mul(this, this, &b, pctx))
+            throw bignum_error("CBigNum::operator*= : BN_mul failed");
+        return *this;
+    }
+
+    CBigNum& operator/=(const CBigNum& b)
+    {
+        *this = *this / b;
+        return *this;
+    }
+
+    CBigNum& operator%=(const CBigNum& b)
+    {
+        *this = *this % b;
+        return *this;
+    }
+
+    CBigNum& operator<<=(unsigned int shift)
+    {
+        if (!BN_lshift(this, this, shift))
+            throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
+        return *this;
+    }
+
+    CBigNum& operator>>=(unsigned int shift)
+    {
+        // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
+        //   if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
+        CBigNum a = 1;
+        a <<= shift;
+        if (BN_cmp(&a, this) > 0)
+        {
+            *this = 0;
+            return *this;
+        }
+
+        if (!BN_rshift(this, this, shift))
+            throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
+        return *this;
+    }
+
+
+    CBigNum& operator++()
+    {
+        // prefix operator
+        if (!BN_add(this, this, BN_value_one()))
+            throw bignum_error("CBigNum::operator++ : BN_add failed");
+        return *this;
+    }
+
+    const CBigNum operator++(int)
+    {
+        // postfix operator
+        const CBigNum ret = *this;
+        ++(*this);
+        return ret;
+    }
+
+    CBigNum& operator--()
+    {
+        // prefix operator
+        CBigNum r;
+        if (!BN_sub(&r, this, BN_value_one()))
+            throw bignum_error("CBigNum::operator-- : BN_sub failed");
+        *this = r;
+        return *this;
+    }
+
+    const CBigNum operator--(int)
+    {
+        // postfix operator
+        const CBigNum ret = *this;
+        --(*this);
+        return ret;
+    }
+
+
+    friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
+    friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
+    friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
+};
+
+
+
+inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
+{
+    CBigNum r;
+    if (!BN_add(&r, &a, &b))
+        throw bignum_error("CBigNum::operator+ : BN_add failed");
+    return r;
+}
+
+inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
+{
+    CBigNum r;
+    if (!BN_sub(&r, &a, &b))
+        throw bignum_error("CBigNum::operator- : BN_sub failed");
+    return r;
+}
+
+inline const CBigNum operator-(const CBigNum& a)
+{
+    CBigNum r(a);
+    BN_set_negative(&r, !BN_is_negative(&r));
+    return r;
+}
+
+inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
+{
+    CAutoBN_CTX pctx;
+    CBigNum r;
+    if (!BN_mul(&r, &a, &b, pctx))
+        throw bignum_error("CBigNum::operator* : BN_mul failed");
+    return r;
+}
+
+inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
+{
+    CAutoBN_CTX pctx;
+    CBigNum r;
+    if (!BN_div(&r, NULL, &a, &b, pctx))
+        throw bignum_error("CBigNum::operator/ : BN_div failed");
+    return r;
+}
+
+inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
+{
+    CAutoBN_CTX pctx;
+    CBigNum r;
+    if (!BN_mod(&r, &a, &b, pctx))
+        throw bignum_error("CBigNum::operator% : BN_div failed");
+    return r;
+}
+
+inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
+{
+    CBigNum r;
+    if (!BN_lshift(&r, &a, shift))
+        throw bignum_error("CBigNum:operator<< : BN_lshift failed");
+    return r;
+}
+
+inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
+{
+    CBigNum r = a;
+    r >>= shift;
+    return r;
+}
+
+inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
+inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
+inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
+inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
+inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) < 0); }
+inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) > 0); }
This page took 0.075931 seconds and 4 git commands to generate.