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-04-02 01:23:23 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       13161 : bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
      24             : {
      25             :     // Skip leading spaces.
      26       13175 :     while (*psz && isspace(*psz))
      27          14 :         psz++;
      28             :     // Skip and count leading '1's.
      29             :     int zeroes = 0;
      30       65396 :     int length = 0;
      31       65396 :     while (*psz == '1') {
      32       52454 :         zeroes++;
      33       52454 :         if (zeroes > max_ret_len) return false;
      34       52235 :         psz++;
      35             :     }
      36             :     // Allocate enough space in big-endian base256 representation.
      37       12942 :     int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
      38       26103 :     std::vector<unsigned char> b256(size);
      39             :     // Process the characters.
      40      580155 :     while (*psz && !isspace(*psz)) {
      41             :         // Decode base58 character
      42      569432 :         const char* ch = strchr(pszBase58, *psz);
      43      569432 :         if (ch == nullptr)
      44             :             return false;
      45             :         // Apply "b256 = b256 * 58 + ch".
      46      568082 :         int carry = ch - pszBase58;
      47      568082 :         int i = 0;
      48    19838570 :         for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
      49    19270490 :             carry += 58 * (*it);
      50    19270490 :             *it = carry % 256;
      51    19270490 :             carry /= 256;
      52             :         }
      53      568082 :         assert(carry == 0);
      54      568082 :         length = i;
      55      568082 :         if (length + zeroes > max_ret_len) return false;
      56      567213 :         psz++;
      57             :     }
      58             :     // Skip trailing spaces.
      59       10900 :     while (isspace(*psz))
      60         177 :         psz++;
      61       10723 :     if (*psz != 0)
      62             :         return false;
      63             :     // Skip leading zeroes in b256.
      64       10721 :     std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
      65             :     // Copy result into output vector.
      66       10721 :     vch.reserve(zeroes + (b256.end() - it));
      67       10721 :     vch.assign(zeroes, 0x00);
      68      372575 :     while (it != b256.end())
      69      361854 :         vch.push_back(*(it++));
      70             :     return true;
      71             : }
      72             : 
      73     1897255 : std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
      74             : {
      75             :     // Skip & count leading zeroes.
      76     1897255 :     int zeroes = 0;
      77     1897255 :     int length = 0;
      78     1928541 :     while (pbegin != pend && *pbegin == 0) {
      79       31286 :         pbegin++;
      80       31286 :         zeroes++;
      81             :     }
      82             :     // Allocate enough space in big-endian base58 representation.
      83     1897255 :     int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
      84     1897255 :     std::vector<unsigned char> b58(size);
      85             :     // Process the bytes.
      86    49431768 :     while (pbegin != pend) {
      87    47534533 :         int carry = *pbegin;
      88    47534533 :         int i = 0;
      89             :         // Apply "b58 = b58 * 256 + ch".
      90   916505800 :         for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
      91   868971500 :             carry += 256 * (*it);
      92   868971500 :             *it = carry % 58;
      93   868971500 :             carry /= 58;
      94             :         }
      95             : 
      96    47534533 :         assert(carry == 0);
      97    47534533 :         length = i;
      98    47534533 :         pbegin++;
      99             :     }
     100             :     // Skip leading zeroes in base58 result.
     101     1897255 :     std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
     102     1897253 :     while (it != b58.end() && *it == 0)
     103     1897255 :         it++;
     104             :     // Translate the result into a string.
     105     1897255 :     std::string str;
     106     1897255 :     str.reserve(zeroes + (b58.end() - it));
     107     1897255 :     str.assign(zeroes, '1');
     108    66545692 :     while (it != b58.end())
     109    64648357 :         str += pszBase58[*(it++)];
     110     3794520 :     return str;
     111             : }
     112             : 
     113     1897243 : std::string EncodeBase58(const std::vector<unsigned char>& vch)
     114             : {
     115     1897243 :     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     1897243 : std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
     127             : {
     128             :     // add 4-byte hash check to the end
     129     1897243 :     std::vector<unsigned char> vch(vchIn);
     130     1897243 :     uint256 hash = Hash(vch.begin(), vch.end());
     131     1897243 :     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
     132     3794496 :     return EncodeBase58(vch);
     133             : }
     134             : 
     135       13141 : bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
     136             : {
     137       13141 :     if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
     138       10706 :         (vchRet.size() < 4)) {
     139        2440 :         vchRet.clear();
     140        2440 :         return false;
     141             :     }
     142             :     // re-calculate the checksum, insure it matches the included 4-byte checksum
     143       10701 :     uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
     144       10701 :     if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
     145          17 :         vchRet.clear();
     146          17 :         return false;
     147             :     }
     148       10684 :     vchRet.resize(vchRet.size() - 4);
     149             :     return true;
     150             : }
     151             : 
     152       13142 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
     153             : {
     154       13142 :     if (!ValidAsCString(str)) {
     155             :         return false;
     156             :     }
     157       13141 :     return DecodeBase58Check(str.c_str(), vchRet, max_ret);
     158             : }

Generated by: LCOV version 1.14