LCOV - code coverage report
Current view: top level - src - base58.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 146 153 95.4 %
Date: 2015-10-12 22:39:14 Functions: 27 31 87.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2014 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "base58.h"
       6             : 
       7             : #include "hash.h"
       8             : #include "uint256.h"
       9             : 
      10             : #include <assert.h>
      11             : #include <stdint.h>
      12             : #include <string.h>
      13             : #include <vector>
      14             : #include <string>
      15             : #include <boost/variant/apply_visitor.hpp>
      16             : #include <boost/variant/static_visitor.hpp>
      17             : 
      18             : /** All alphanumeric characters except for "0", "I", "O", and "l" */
      19             : static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
      20             : 
      21        1107 : bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
      22             : {
      23             :     // Skip leading spaces.
      24        2228 :     while (*psz && isspace(*psz))
      25          14 :         psz++;
      26             :     // Skip and count leading '1's.
      27             :     int zeroes = 0;
      28        1164 :     while (*psz == '1') {
      29          57 :         zeroes++;
      30          57 :         psz++;
      31             :     }
      32             :     // Allocate enough space in big-endian base256 representation.
      33        2214 :     std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
      34             :     // Process the characters.
      35       50102 :     while (*psz && !isspace(*psz)) {
      36             :         // Decode base58 character
      37       95820 :         const char* ch = strchr(pszBase58, *psz);
      38       47910 :         if (ch == NULL)
      39             :             return false;
      40             :         // Apply "b256 = b256 * 58 + ch".
      41       47888 :         int carry = ch - pszBase58;
      42     3589282 :         for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
      43     1770697 :             carry += 58 * (*it);
      44     1770697 :             *it = carry % 256;
      45     1770697 :             carry /= 256;
      46             :         }
      47       47888 :         assert(carry == 0);
      48       47888 :         psz++;
      49             :     }
      50             :     // Skip trailing spaces.
      51        1099 :     while (isspace(*psz))
      52          14 :         psz++;
      53        1085 :     if (*psz != 0)
      54             :         return false;
      55             :     // Skip leading zeroes in b256.
      56        1084 :     std::vector<unsigned char>::iterator it = b256.begin();
      57        4839 :     while (it != b256.end() && *it == 0)
      58         529 :         it++;
      59             :     // Copy result into output vector.
      60        3252 :     vch.reserve(zeroes + (b256.end() - it));
      61             :     vch.assign(zeroes, 0x00);
      62       72264 :     while (it != b256.end())
      63       70096 :         vch.push_back(*(it++));
      64             :     return true;
      65             : }
      66             : 
      67        2297 : std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
      68             : {
      69             :     // Skip & count leading zeroes.
      70        2297 :     int zeroes = 0;
      71        4652 :     while (pbegin != pend && *pbegin == 0) {
      72          58 :         pbegin++;
      73          58 :         zeroes++;
      74             :     }
      75             :     // Allocate enough space in big-endian base58 representation.
      76        4594 :     std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
      77             :     // Process the bytes.
      78       67804 :     while (pbegin != pend) {
      79       63210 :         int carry = *pbegin;
      80             :         // Apply "b58 = b58 * 256 + ch".
      81     5286812 :         for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
      82     2611801 :             carry += 256 * (*it);
      83     2611801 :             *it = carry % 58;
      84     2611801 :             carry /= 58;
      85             :         }
      86       63210 :         assert(carry == 0);
      87       63210 :         pbegin++;
      88             :     }
      89             :     // Skip leading zeroes in base58 result.
      90        2297 :     std::vector<unsigned char>::iterator it = b58.begin();
      91       13767 :     while (it != b58.end() && *it == 0)
      92        2292 :         it++;
      93             :     // Translate the result into a string.
      94             :     std::string str;
      95        6891 :     str.reserve(zeroes + (b58.end() - it));
      96        2297 :     str.assign(zeroes, '1');
      97      176874 :     while (it != b58.end())
      98      172280 :         str += pszBase58[*(it++)];
      99        2297 :     return str;
     100             : }
     101             : 
     102           0 : std::string EncodeBase58(const std::vector<unsigned char>& vch)
     103             : {
     104        2285 :     return EncodeBase58(&vch[0], &vch[0] + vch.size());
     105             : }
     106             : 
     107          12 : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
     108             : {
     109          12 :     return DecodeBase58(str.c_str(), vchRet);
     110             : }
     111             : 
     112        2285 : std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
     113             : {
     114             :     // add 4-byte hash check to the end
     115        2285 :     std::vector<unsigned char> vch(vchIn);
     116        2285 :     uint256 hash = Hash(vch.begin(), vch.end());
     117             :     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
     118        2285 :     return EncodeBase58(vch);
     119             : }
     120             : 
     121        1092 : bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
     122             : {
     123        2163 :     if (!DecodeBase58(psz, vchRet) ||
     124        1071 :         (vchRet.size() < 4)) {
     125             :         vchRet.clear();
     126          26 :         return false;
     127             :     }
     128             :     // re-calculate the checksum, insure it matches the included 4-byte checksum
     129        2132 :     uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
     130        2132 :     if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
     131             :         vchRet.clear();
     132          19 :         return false;
     133             :     }
     134        2094 :     vchRet.resize(vchRet.size() - 4);
     135             :     return true;
     136             : }
     137             : 
     138             : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
     139             : {
     140             :     return DecodeBase58Check(str.c_str(), vchRet);
     141             : }
     142             : 
     143        6344 : CBase58Data::CBase58Data()
     144             : {
     145        3172 :     vchVersion.clear();
     146        3172 :     vchData.clear();
     147        3172 : }
     148             : 
     149        2275 : void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
     150             : {
     151        2275 :     vchVersion = vchVersionIn;
     152        2275 :     vchData.resize(nSize);
     153        4550 :     if (!vchData.empty())
     154        2275 :         memcpy(&vchData[0], pdata, nSize);
     155        2275 : }
     156             : 
     157          24 : void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
     158             : {
     159          24 :     SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
     160          24 : }
     161             : 
     162        1092 : bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
     163             : {
     164             :     std::vector<unsigned char> vchTemp;
     165        1092 :     bool rc58 = DecodeBase58Check(psz, vchTemp);
     166        2139 :     if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
     167          45 :         vchData.clear();
     168          45 :         vchVersion.clear();
     169          45 :         return false;
     170             :     }
     171        3141 :     vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
     172        2094 :     vchData.resize(vchTemp.size() - nVersionBytes);
     173        2094 :     if (!vchData.empty())
     174        3141 :         memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
     175        2094 :     memory_cleanse(&vchTemp[0], vchData.size());
     176             :     return true;
     177             : }
     178             : 
     179         616 : bool CBase58Data::SetString(const std::string& str)
     180             : {
     181         616 :     return SetString(str.c_str());
     182             : }
     183             : 
     184        2285 : std::string CBase58Data::ToString() const
     185             : {
     186        2285 :     std::vector<unsigned char> vch = vchVersion;
     187        6855 :     vch.insert(vch.end(), vchData.begin(), vchData.end());
     188        4570 :     return EncodeBase58Check(vch);
     189             : }
     190             : 
     191         104 : int CBase58Data::CompareTo(const CBase58Data& b58) const
     192             : {
     193         208 :     if (vchVersion < b58.vchVersion)
     194             :         return -1;
     195         208 :     if (vchVersion > b58.vchVersion)
     196             :         return 1;
     197         208 :     if (vchData < b58.vchData)
     198             :         return -1;
     199          82 :     if (vchData > b58.vchData)
     200             :         return 1;
     201           0 :     return 0;
     202             : }
     203             : 
     204             : namespace
     205             : {
     206        1891 : class CBitcoinAddressVisitor : public boost::static_visitor<bool>
     207             : {
     208             : private:
     209             :     CBitcoinAddress* addr;
     210             : 
     211             : public:
     212        1891 :     CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
     213             : 
     214        3654 :     bool operator()(const CKeyID& id) const { return addr->Set(id); }
     215         126 :     bool operator()(const CScriptID& id) const { return addr->Set(id); }
     216           0 :     bool operator()(const CNoDestination& no) const { return false; }
     217             : };
     218             : 
     219             : } // anon namespace
     220             : 
     221           0 : bool CBitcoinAddress::Set(const CKeyID& id)
     222             : {
     223        3654 :     SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
     224           0 :     return true;
     225             : }
     226             : 
     227           0 : bool CBitcoinAddress::Set(const CScriptID& id)
     228             : {
     229         126 :     SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
     230           0 :     return true;
     231             : }
     232             : 
     233        1891 : bool CBitcoinAddress::Set(const CTxDestination& dest)
     234             : {
     235        3782 :     return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
     236             : }
     237             : 
     238         354 : bool CBitcoinAddress::IsValid() const
     239             : {
     240         907 :     return IsValid(Params());
     241             : }
     242             : 
     243         907 : bool CBitcoinAddress::IsValid(const CChainParams& params) const
     244             : {
     245        1814 :     bool fCorrectSize = vchData.size() == 20;
     246        1077 :     bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
     247        1077 :                          vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
     248         907 :     return fCorrectSize && fKnownVersion;
     249             : }
     250             : 
     251         518 : CTxDestination CBitcoinAddress::Get() const
     252             : {
     253         518 :     if (!IsValid())
     254             :         return CNoDestination();
     255             :     uint160 id;
     256         518 :     memcpy(&id, &vchData[0], 20);
     257        1036 :     if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
     258         486 :         return CKeyID(id);
     259          64 :     else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
     260          32 :         return CScriptID(id);
     261             :     else
     262             :         return CNoDestination();
     263             : }
     264             : 
     265           6 : bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
     266             : {
     267          18 :     if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
     268             :         return false;
     269             :     uint160 id;
     270           6 :     memcpy(&id, &vchData[0], 20);
     271           6 :     keyID = CKeyID(id);
     272           6 :     return true;
     273             : }
     274             : 
     275          29 : bool CBitcoinAddress::IsScript() const
     276             : {
     277          58 :     return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
     278             : }
     279             : 
     280         361 : void CBitcoinSecret::SetKey(const CKey& vchSecret)
     281             : {
     282         361 :     assert(vchSecret.IsValid());
     283        1444 :     SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
     284         361 :     if (vchSecret.IsCompressed())
     285         349 :         vchData.push_back(1);
     286         361 : }
     287             : 
     288         371 : CKey CBitcoinSecret::GetKey()
     289             : {
     290             :     CKey ret;
     291         742 :     assert(vchData.size() >= 32);
     292        1484 :     ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
     293         371 :     return ret;
     294             : }
     295             : 
     296         538 : bool CBitcoinSecret::IsValid() const
     297             : {
     298        1076 :     bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
     299        1076 :     bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
     300         538 :     return fExpectedFormat && fCorrectVersion;
     301             : }
     302             : 
     303         448 : bool CBitcoinSecret::SetString(const char* pszSecret)
     304             : {
     305         448 :     return CBase58Data::SetString(pszSecret) && IsValid();
     306             : }
     307             : 
     308         448 : bool CBitcoinSecret::SetString(const std::string& strSecret)
     309             : {
     310         448 :     return SetString(strSecret.c_str());
     311         330 : }

Generated by: LCOV version 1.11