LCOV - code coverage report
Current view: top level - src - base58.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 81 81 100.0 %
Date: 2025-02-23 09:33:43 Functions: 7 7 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2014 The Bitcoin developers
       2             : // Copyright (c) 2017-2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "base58.h"
       7             : 
       8             : #include "hash.h"
       9             : #include "util/string.h"
      10             : 
      11             : #include "uint256.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <assert.h>
      15             : #include <sstream>
      16             : #include <vector>
      17             : 
      18             : #include <limits>
      19             : 
      20             : /** All alphanumeric characters except for "0", "I", "O", and "l" */
      21             : static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
      22             : 
      23       13157 : bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
      24             : {
      25             :     // Skip leading spaces.
      26       13171 :     while (*psz && isspace(*psz))
      27          14 :         psz++;
      28             :     // Skip and count leading '1's.
      29             :     int zeroes = 0;
      30       64229 :     int length = 0;
      31       64229 :     while (*psz == '1') {
      32       51275 :         zeroes++;
      33       51275 :         if (zeroes > max_ret_len) return false;
      34       51072 :         psz++;
      35             :     }
      36             :     // Allocate enough space in big-endian base256 representation.
      37       12954 :     int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
      38       26111 :     std::vector<unsigned char> b256(size);
      39             :     // Process the characters.
      40      583862 :     while (*psz && !isspace(*psz)) {
      41             :         // Decode base58 character
      42      573142 :         const char* ch = strchr(pszBase58, *psz);
      43      573142 :         if (ch == nullptr)
      44             :             return false;
      45             :         // Apply "b256 = b256 * 58 + ch".
      46      571793 :         int carry = ch - pszBase58;
      47      571793 :         int i = 0;
      48    20106170 :         for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
      49    19534420 :             carry += 58 * (*it);
      50    19534420 :             *it = carry % 256;
      51    19534420 :             carry /= 256;
      52             :         }
      53      571793 :         assert(carry == 0);
      54      571793 :         length = i;
      55      571793 :         if (length + zeroes > max_ret_len) return false;
      56      570908 :         psz++;
      57             :     }
      58             :     // Skip trailing spaces.
      59       10897 :     while (isspace(*psz))
      60         177 :         psz++;
      61       10720 :     if (*psz != 0)
      62             :         return false;
      63             :     // Skip leading zeroes in b256.
      64       10718 :     std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
      65             :     // Copy result into output vector.
      66       10718 :     vch.reserve(zeroes + (b256.end() - it));
      67       10718 :     vch.assign(zeroes, 0x00);
      68      373056 :     while (it != b256.end())
      69      362338 :         vch.push_back(*(it++));
      70             :     return true;
      71             : }
      72             : 
      73     1993256 : std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
      74             : {
      75             :     // Skip & count leading zeroes.
      76     1993256 :     int zeroes = 0;
      77     1993256 :     int length = 0;
      78     2023907 :     while (pbegin != pend && *pbegin == 0) {
      79       30651 :         pbegin++;
      80       30651 :         zeroes++;
      81             :     }
      82             :     // Allocate enough space in big-endian base58 representation.
      83     1993256 :     int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
      84     1993256 :     std::vector<unsigned char> b58(size);
      85             :     // Process the bytes.
      86    51928166 :     while (pbegin != pend) {
      87    49934930 :         int carry = *pbegin;
      88    49934930 :         int i = 0;
      89             :         // Apply "b58 = b58 * 256 + ch".
      90   962424200 :         for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
      91   912489300 :             carry += 256 * (*it);
      92   912489300 :             *it = carry % 58;
      93   912489300 :             carry /= 58;
      94             :         }
      95             : 
      96    49934930 :         assert(carry == 0);
      97    49934930 :         length = i;
      98    49934930 :         pbegin++;
      99             :     }
     100             :     // Skip leading zeroes in base58 result.
     101     1993256 :     std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
     102     1993254 :     while (it != b58.end() && *it == 0)
     103     1993256 :         it++;
     104             :     // Translate the result into a string.
     105     1993256 :     std::string str;
     106     1993256 :     str.reserve(zeroes + (b58.end() - it));
     107     1993256 :     str.assign(zeroes, '1');
     108    69906239 :     while (it != b58.end())
     109    67913003 :         str += pszBase58[*(it++)];
     110     3986512 :     return str;
     111             : }
     112             : 
     113     1993244 : std::string EncodeBase58(const std::vector<unsigned char>& vch)
     114             : {
     115     1993244 :     return EncodeBase58(vch.data(), vch.data() + vch.size());
     116             : }
     117             : 
     118          18 : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
     119             : {
     120          18 :     if (!ValidAsCString(str)) {
     121             :         return false;
     122             :     }
     123          16 :     return DecodeBase58(str.c_str(), vchRet, max_ret_len);
     124             : }
     125             : 
     126     1993244 : std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
     127             : {
     128             :     // add 4-byte hash check to the end
     129     1993244 :     std::vector<unsigned char> vch(vchIn);
     130     1993244 :     uint256 hash = Hash(vch.begin(), vch.end());
     131     1993244 :     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
     132     3986478 :     return EncodeBase58(vch);
     133             : }
     134             : 
     135       13137 : bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
     136             : {
     137       13137 :     if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
     138       10703 :         (vchRet.size() < 4)) {
     139        2439 :         vchRet.clear();
     140        2439 :         return false;
     141             :     }
     142             :     // re-calculate the checksum, insure it matches the included 4-byte checksum
     143       10698 :     uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
     144       10698 :     if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
     145          17 :         vchRet.clear();
     146          17 :         return false;
     147             :     }
     148       10681 :     vchRet.resize(vchRet.size() - 4);
     149             :     return true;
     150             : }
     151             : 
     152       13138 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
     153             : {
     154       13138 :     if (!ValidAsCString(str)) {
     155             :         return false;
     156             :     }
     157       13137 :     return DecodeBase58Check(str.c_str(), vchRet, max_ret);
     158             : }

Generated by: LCOV version 1.14