-
+ C9414DD278719A028B904826086E3D241AC1402BBCBAF265C6E03B2DFE0451833A8E6CC11CDCC90E67E64C41056C9A2725CEC1F0A6E251A0EF76835BA3D173B4bitcoin/src/base58.h(0 . 0)(1 . 323)
   53 // Copyright (c) 2009-2010 Satoshi Nakamoto
   54 // Copyright (c) 2011 The Bitcoin Developers
   55 // Distributed under the MIT/X11 software license, see the accompanying
   56 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
   57 
   58 
   59 //
   60 // Why base-58 instead of standard base-64 encoding?
   61 // - Don't want 0OIl characters that look the same in some fonts and
   62 //      could be used to create visually identical looking account numbers.
   63 // - A string with non-alphanumeric characters is not as easily accepted as an account number.
   64 // - E-mail usually won't line-break if there's no punctuation to break at.
   65 // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
   66 //
   67 #ifndef BITCOIN_BASE58_H
   68 #define BITCOIN_BASE58_H
   69 
   70 #include <string>
   71 #include <vector>
   72 #include "bignum.h"
   73 
   74 static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
   75 
   76 // Encode a byte sequence as a base58-encoded string
   77 inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
   78 {
   79     CAutoBN_CTX pctx;
   80     CBigNum bn58 = 58;
   81     CBigNum bn0 = 0;
   82 
   83     // Convert big endian data to little endian
   84     // Extra zero at the end make sure bignum will interpret as a positive number
   85     std::vector<unsigned char> vchTmp(pend-pbegin+1, 0);
   86     reverse_copy(pbegin, pend, vchTmp.begin());
   87 
   88     // Convert little endian data to bignum
   89     CBigNum bn;
   90     bn.setvch(vchTmp);
   91 
   92     // Convert bignum to std::string
   93     std::string str;
   94     // Expected size increase from base58 conversion is approximately 137%
   95     // use 138% to be safe
   96     str.reserve((pend - pbegin) * 138 / 100 + 1);
   97     CBigNum dv;
   98     CBigNum rem;
   99     while (bn > bn0)
  100     {
  101         if (!BN_div(&dv, &rem, &bn, &bn58, pctx))
  102             throw bignum_error("EncodeBase58 : BN_div failed");
  103         bn = dv;
  104         unsigned int c = rem.getulong();
  105         str += pszBase58[c];
  106     }
  107 
  108     // Leading zeroes encoded as base58 zeros
  109     for (const unsigned char* p = pbegin; p < pend && *p == 0; p++)
  110         str += pszBase58[0];
  111 
  112     // Convert little endian std::string to big endian
  113     reverse(str.begin(), str.end());
  114     return str;
  115 }
  116 
  117 // Encode a byte vector as a base58-encoded string
  118 inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
  119 {
  120     return EncodeBase58(&vch[0], &vch[0] + vch.size());
  121 }
  122 
  123 // Decode a base58-encoded string psz into byte vector vchRet
  124 // returns true if decoding is succesful
  125 inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
  126 {
  127     CAutoBN_CTX pctx;
  128     vchRet.clear();
  129     CBigNum bn58 = 58;
  130     CBigNum bn = 0;
  131     CBigNum bnChar;
  132     while (isspace(*psz))
  133         psz++;
  134 
  135     // Convert big endian string to bignum
  136     for (const char* p = psz; *p; p++)
  137     {
  138         const char* p1 = strchr(pszBase58, *p);
  139         if (p1 == NULL)
  140         {
  141             while (isspace(*p))
  142                 p++;
  143             if (*p != '\0')
  144                 return false;
  145             break;
  146         }
  147         bnChar.setulong(p1 - pszBase58);
  148         if (!BN_mul(&bn, &bn, &bn58, pctx))
  149             throw bignum_error("DecodeBase58 : BN_mul failed");
  150         bn += bnChar;
  151     }
  152 
  153     // Get bignum as little endian data
  154     std::vector<unsigned char> vchTmp = bn.getvch();
  155 
  156     // Trim off sign byte if present
  157     if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80)
  158         vchTmp.erase(vchTmp.end()-1);
  159 
  160     // Restore leading zeros
  161     int nLeadingZeros = 0;
  162     for (const char* p = psz; *p == pszBase58[0]; p++)
  163         nLeadingZeros++;
  164     vchRet.assign(nLeadingZeros + vchTmp.size(), 0);
  165 
  166     // Convert little endian data to big endian
  167     reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size());
  168     return true;
  169 }
  170 
  171 // Decode a base58-encoded string str into byte vector vchRet
  172 // returns true if decoding is succesful
  173 inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
  174 {
  175     return DecodeBase58(str.c_str(), vchRet);
  176 }
  177 
  178 
  179 
  180 
  181 // Encode a byte vector to a base58-encoded string, including checksum
  182 inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
  183 {
  184     // add 4-byte hash check to the end
  185     std::vector<unsigned char> vch(vchIn);
  186     uint256 hash = Hash(vch.begin(), vch.end());
  187     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
  188     return EncodeBase58(vch);
  189 }
  190 
  191 // Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
  192 // returns true if decoding is succesful
  193 inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
  194 {
  195     if (!DecodeBase58(psz, vchRet))
  196         return false;
  197     if (vchRet.size() < 4)
  198     {
  199         vchRet.clear();
  200         return false;
  201     }
  202     uint256 hash = Hash(vchRet.begin(), vchRet.end()-4);
  203     if (memcmp(&hash, &vchRet.end()[-4], 4) != 0)
  204     {
  205         vchRet.clear();
  206         return false;
  207     }
  208     vchRet.resize(vchRet.size()-4);
  209     return true;
  210 }
  211 
  212 // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
  213 // returns true if decoding is succesful
  214 inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
  215 {
  216     return DecodeBase58Check(str.c_str(), vchRet);
  217 }
  218 
  219 
  220 
  221 
  222 
  223 // Base class for all base58-encoded data
  224 class CBase58Data
  225 {
  226 protected:
  227     // the version byte
  228     unsigned char nVersion;
  229 
  230     // the actually encoded data
  231     std::vector<unsigned char> vchData;
  232 
  233     CBase58Data()
  234     {
  235         nVersion = 0;
  236         vchData.clear();
  237     }
  238 
  239     ~CBase58Data()
  240     {
  241         // zero the memory, as it may contain sensitive data
  242         if (!vchData.empty())
  243             memset(&vchData[0], 0, vchData.size());
  244     }
  245 
  246     void SetData(int nVersionIn, const void* pdata, size_t nSize)
  247     {
  248         nVersion = nVersionIn;
  249         vchData.resize(nSize);
  250         if (!vchData.empty())
  251             memcpy(&vchData[0], pdata, nSize);
  252     }
  253 
  254     void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend)
  255     {
  256         SetData(nVersionIn, (void*)pbegin, pend - pbegin);
  257     }
  258 
  259 public:
  260     bool SetString(const char* psz)
  261     {
  262         std::vector<unsigned char> vchTemp;
  263         DecodeBase58Check(psz, vchTemp);
  264         if (vchTemp.empty())
  265         {
  266             vchData.clear();
  267             nVersion = 0;
  268             return false;
  269         }
  270         nVersion = vchTemp[0];
  271         vchData.resize(vchTemp.size() - 1);
  272         if (!vchData.empty())
  273             memcpy(&vchData[0], &vchTemp[1], vchData.size());
  274         memset(&vchTemp[0], 0, vchTemp.size());
  275         return true;
  276     }
  277 
  278     bool SetString(const std::string& str)
  279     {
  280         return SetString(str.c_str());
  281     }
  282 
  283     std::string ToString() const
  284     {
  285         std::vector<unsigned char> vch(1, nVersion);
  286         vch.insert(vch.end(), vchData.begin(), vchData.end());
  287         return EncodeBase58Check(vch);
  288     }
  289 
  290     int CompareTo(const CBase58Data& b58) const
  291     {
  292         if (nVersion < b58.nVersion) return -1;
  293         if (nVersion > b58.nVersion) return  1;
  294         if (vchData < b58.vchData)   return -1;
  295         if (vchData > b58.vchData)   return  1;
  296         return 0;
  297     }
  298 
  299     bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
  300     bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
  301     bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
  302     bool operator< (const CBase58Data& b58) const { return CompareTo(b58) <  0; }
  303     bool operator> (const CBase58Data& b58) const { return CompareTo(b58) >  0; }
  304 };
  305 
  306 // base58-encoded bitcoin addresses
  307 // Addresses have version 0 or 111 (testnet)
  308 // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key
  309 class CBitcoinAddress : public CBase58Data
  310 {
  311 public:
  312     bool SetHash160(const uint160& hash160)
  313     {
  314         SetData(fTestNet ? 111 : 0, &hash160, 20);
  315         return true;
  316     }
  317 
  318     bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
  319     {
  320         return SetHash160(Hash160(vchPubKey));
  321     }
  322 
  323     bool IsValid() const
  324     {
  325         int nExpectedSize = 20;
  326         bool fExpectTestNet = false;
  327         switch(nVersion)
  328         {
  329             case 0:
  330                 break;
  331 
  332             case 111:
  333                 fExpectTestNet = true;
  334                 break;
  335 
  336             default:
  337                 return false;
  338         }
  339         return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
  340     }
  341 
  342     CBitcoinAddress()
  343     {
  344     }
  345 
  346     CBitcoinAddress(uint160 hash160In)
  347     {
  348         SetHash160(hash160In);
  349     }
  350 
  351     CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
  352     {
  353         SetPubKey(vchPubKey);
  354     }
  355 
  356     CBitcoinAddress(const std::string& strAddress)
  357     {
  358         SetString(strAddress);
  359     }
  360 
  361     CBitcoinAddress(const char* pszAddress)
  362     {
  363         SetString(pszAddress);
  364     }
  365 
  366     uint160 GetHash160() const
  367     {
  368         assert(vchData.size() == 20);
  369         uint160 hash160;
  370         memcpy(&hash160, &vchData[0], 20);
  371         return hash160;
  372     }
  373 };
  374 
  375 #endif