genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 
genesis                 6 
genesis                 7 
genesis                 8 
genesis                 9 
genesis                10 
genesis                11 
genesis                12 
genesis                13 
genesis                14 
genesis                15 #ifndef BITCOIN_BASE58_H
genesis                16 #define BITCOIN_BASE58_H
genesis                17 
genesis                18 #include <string>
genesis                19 #include <vector>
genesis                20 #include "bignum.h"
genesis                21 
genesis                22 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
genesis                23 
genesis                24 
genesis                25 inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
genesis                26 {
genesis                27     CAutoBN_CTX pctx;
genesis                28     CBigNum bn58 = 58;
genesis                29     CBigNum bn0 = 0;
genesis                30 
genesis                31     
genesis                32     
genesis                33     std::vector<unsigned char> vchTmp(pend-pbegin+1, 0);
genesis                34     reverse_copy(pbegin, pend, vchTmp.begin());
genesis                35 
genesis                36     
genesis                37     CBigNum bn;
genesis                38     bn.setvch(vchTmp);
genesis                39 
genesis                40     
genesis                41     std::string str;
genesis                42     
genesis                43     
genesis                44     str.reserve((pend - pbegin) * 138 / 100 + 1);
genesis                45     CBigNum dv;
genesis                46     CBigNum rem;
genesis                47     while (bn > bn0)
genesis                48     {
genesis                49         if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
genesis                50             throw bignum_error("EncodeBase58 : BN_div failed");
genesis                51         bn = dv;
genesis                52         unsigned int c = rem.getulong();
genesis                53         str += pszBase58[c];
genesis                54     }
genesis                55 
genesis                56     
genesis                57     for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
genesis                58         str += pszBase58[0];
genesis                59 
genesis                60     
genesis                61     reverse(str.begin(), str.end());
genesis                62     return str;
genesis                63 }
genesis                64 
genesis                65 
genesis                66 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
genesis                67 {
genesis                68     return EncodeBase58(&vch[0], &vch[0] + vch.size());
genesis                69 }
genesis                70 
genesis                71 
genesis                72 
genesis                73 inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
genesis                74 {
genesis                75     CAutoBN_CTX pctx;
genesis                76     vchRet.clear();
genesis                77     CBigNum bn58 = 58;
genesis                78     CBigNum bn = 0;
genesis                79     CBigNum bnChar;
genesis                80     while (isspace(*psz))
genesis                81         psz++;
genesis                82 
genesis                83     
genesis                84     for (const char* p = psz; *p; p++)
genesis                85     {
genesis                86         const char* p1 = strchr(pszBase58, *p);
genesis                87         if (p1 == NULL)
genesis                88         {
genesis                89             while (isspace(*p))
genesis                90                 p++;
genesis                91             if (*p != '\0')
genesis                92                 return false;
genesis                93             break;
genesis                94         }
genesis                95         bnChar.setulong(p1 - pszBase58);
genesis                96         if (!BN_mul(&bn, &bn, &bn58, pctx))
genesis                97             throw bignum_error("DecodeBase58 : BN_mul failed");
genesis                98         bn += bnChar;
genesis                99     }
genesis               100 
genesis               101     
genesis               102     std::vector<unsigned char> vchTmp = bn.getvch();
genesis               103 
genesis               104     
genesis               105     if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
genesis               106         vchTmp.erase(vchTmp.end()-1);
genesis               107 
genesis               108     
genesis               109     int nLeadingZeros = 0;
genesis               110     for (const char* p = psz; *p == pszBase58[0]; p++)
genesis               111         nLeadingZeros++;
genesis               112     vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
genesis               113 
genesis               114     
genesis               115     reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
genesis               116     return true;
genesis               117 }
genesis               118 
genesis               119 
genesis               120 
genesis               121 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
genesis               122 {
genesis               123     return DecodeBase58(str.c_str(), vchRet);
genesis               124 }
genesis               125 
genesis               126 
genesis               127 
genesis               128 
genesis               129 
genesis               130 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
genesis               131 {
genesis               132     
genesis               133     std::vector<unsigned char> vch(vchIn);
genesis               134     uint256 hash = Hash(vch.begin(), vch.end());
genesis               135     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
genesis               136     return EncodeBase58(vch);
genesis               137 }
genesis               138 
genesis               139 
genesis               140 
genesis               141 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
genesis               142 {
genesis               143     if (!DecodeBase58(psz, vchRet))
genesis               144         return false;
genesis               145     if (vchRet.size() < 4)
genesis               146     {
genesis               147         vchRet.clear();
genesis               148         return false;
genesis               149     }
genesis               150     uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
genesis               151     if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
genesis               152     {
genesis               153         vchRet.clear();
genesis               154         return false;
genesis               155     }
genesis               156     vchRet.resize(vchRet.size()-4);
genesis               157     return true;
genesis               158 }
genesis               159 
genesis               160 
genesis               161 
genesis               162 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
genesis               163 {
genesis               164     return DecodeBase58Check(str.c_str(), vchRet);
genesis               165 }
genesis               166 
genesis               167 
genesis               168 
genesis               169 
genesis               170 
genesis               171 
genesis               172 class CBase58Data
genesis               173 {
genesis               174 protected:
genesis               175     
genesis               176     unsigned char nVersion;
genesis               177 
genesis               178     
genesis               179     std::vector<unsigned char> vchData;
genesis               180 
genesis               181     CBase58Data()
genesis               182     {
genesis               183         nVersion = 0;
genesis               184         vchData.clear();
genesis               185     }
genesis               186 
genesis               187     ~CBase58Data()
genesis               188     {
genesis               189         
genesis               190         if (!vchData.empty())
genesis               191             memset(&vchData[0], 0, vchData.size());
genesis               192     }
genesis               193 
genesis               194     void SetData(int nVersionIn, const void* pdata, size_t nSize)
genesis               195     {
genesis               196         nVersion = nVersionIn;
genesis               197         vchData.resize(nSize);
genesis               198         if (!vchData.empty())
genesis               199             memcpy(&vchData[0], pdata, nSize);
genesis               200     }
genesis               201 
genesis               202     void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
genesis               203     {
genesis               204         SetData(nVersionIn, (void*)pbegin, pend - pbegin);
genesis               205     }
genesis               206 
genesis               207 public:
genesis               208     bool SetString(const char* psz)
genesis               209     {
genesis               210         std::vector<unsigned char> vchTemp;
genesis               211         DecodeBase58Check(psz, vchTemp);
genesis               212         if (vchTemp.empty())
genesis               213         {
genesis               214             vchData.clear();
genesis               215             nVersion = 0;
genesis               216             return false;
genesis               217         }
genesis               218         nVersion = vchTemp[0];
genesis               219         vchData.resize(vchTemp.size() - 1);
genesis               220         if (!vchData.empty())
genesis               221             memcpy(&vchData[0], &vchTemp[1], vchData.size());
genesis               222         memset(&vchTemp[0], 0, vchTemp.size());
genesis               223         return true;
genesis               224     }
genesis               225 
genesis               226     bool SetString(const std::string& str)
genesis               227     {
genesis               228         return SetString(str.c_str());
genesis               229     }
genesis               230 
genesis               231     std::string ToString() const
genesis               232     {
genesis               233         std::vector<unsigned char> vch(1, nVersion);
genesis               234         vch.insert(vch.end(), vchData.begin(), vchData.end());
genesis               235         return EncodeBase58Check(vch);
genesis               236     }
genesis               237 
genesis               238     int CompareTo(const CBase58Data& b58) const
genesis               239     {
genesis               240         if (nVersion < b58.nVersion) return -1;
genesis               241         if (nVersion > b58.nVersion) return  1;
genesis               242         if (vchData < b58.vchData)   return -1;
genesis               243         if (vchData > b58.vchData)   return  1;
genesis               244         return 0;
genesis               245     }
genesis               246 
genesis               247     bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
genesis               248     bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
genesis               249     bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
genesis               250     bool operator< (const CBase58Data& b58) const { return CompareTo(b58) <  0; }
genesis               251     bool operator> (const CBase58Data& b58) const { return CompareTo(b58) >  0; }
genesis               252 };
genesis               253 
genesis               254 
genesis               255 
genesis               256 
genesis               257 class CBitcoinAddress : public CBase58Data
genesis               258 {
genesis               259 public:
genesis               260     bool SetHash160(const uint160& hash160)
genesis               261     {
genesis               262         SetData(fTestNet ? 111 : 0, &hash160, 20);
genesis               263         return true;
genesis               264     }
genesis               265 
genesis               266     bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
genesis               267     {
genesis               268         return SetHash160(Hash160(vchPubKey));
genesis               269     }
genesis               270 
genesis               271     bool IsValid() const
genesis               272     {
genesis               273         int nExpectedSize = 20;
genesis               274         bool fExpectTestNet = false;
genesis               275         switch(nVersion)
genesis               276         {
genesis               277             case 0:
genesis               278                 break;
genesis               279 
genesis               280             case 111:
genesis               281                 fExpectTestNet = true;
genesis               282                 break;
genesis               283 
genesis               284             default:
genesis               285                 return false;
genesis               286         }
genesis               287         return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
genesis               288     }
genesis               289 
genesis               290     CBitcoinAddress()
genesis               291     {
genesis               292     }
genesis               293 
genesis               294     CBitcoinAddress(uint160 hash160In)
genesis               295     {
genesis               296         SetHash160(hash160In);
genesis               297     }
genesis               298 
genesis               299     CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
genesis               300     {
genesis               301         SetPubKey(vchPubKey);
genesis               302     }
genesis               303 
genesis               304     CBitcoinAddress(const std::string& strAddress)
genesis               305     {
genesis               306         SetString(strAddress);
genesis               307     }
genesis               308 
genesis               309     CBitcoinAddress(const char* pszAddress)
genesis               310     {
genesis               311         SetString(pszAddress);
genesis               312     }
genesis               313 
genesis               314     uint160 GetHash160() const
genesis               315     {
genesis               316         assert(vchData.size() == 20);
genesis               317         uint160 hash160;
genesis               318         memcpy(&hash160, &vchData[0], 20);
genesis               319         return hash160;
genesis               320     }
genesis               321 };
genesis               322 
genesis               323 #endif