LCOV - code coverage report
Current view: top level - src - base58.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 101 102 99.0 %
Date: 2021-06-29 14:35:33 Functions: 6 6 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 60 64 93.8 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2014-2020 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                 :            : #include <util/strencodings.h>
#      10                 :            : #include <util/string.h>
#      11                 :            : 
#      12                 :            : #include <assert.h>
#      13                 :            : #include <string.h>
#      14                 :            : 
#      15                 :            : #include <limits>
#      16                 :            : 
#      17                 :            : /** All alphanumeric characters except for "0", "I", "O", and "l" */
#      18                 :            : static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
#      19                 :            : static const int8_t mapBase58[256] = {
#      20                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      21                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      22                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      23                 :            :     -1, 0, 1, 2, 3, 4, 5, 6,  7, 8,-1,-1,-1,-1,-1,-1,
#      24                 :            :     -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
#      25                 :            :     22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
#      26                 :            :     -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
#      27                 :            :     47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
#      28                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      29                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      30                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      31                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      32                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      33                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      34                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      35                 :            :     -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
#      36                 :            : };
#      37                 :            : 
#      38                 :            : [[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
#      39                 :      43939 : {
#      40                 :            :     // Skip leading spaces.
#      41 [ +  + ][ +  + ]:      43967 :     while (*psz && IsSpace(*psz))
#      42                 :         28 :         psz++;
#      43                 :            :     // Skip and count leading '1's.
#      44                 :      43939 :     int zeroes = 0;
#      45                 :      43939 :     int length = 0;
#      46         [ +  + ]:     161074 :     while (*psz == '1') {
#      47                 :     117583 :         zeroes++;
#      48         [ +  + ]:     117583 :         if (zeroes > max_ret_len) return false;
#      49                 :     117135 :         psz++;
#      50                 :     117135 :     }
#      51                 :            :     // Allocate enough space in big-endian base256 representation.
#      52                 :      43939 :     int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
#      53                 :      43491 :     std::vector<unsigned char> b256(size);
#      54                 :            :     // Process the characters.
#      55                 :      43491 :     static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
#      56 [ +  + ][ +  + ]:    1666144 :     while (*psz && !IsSpace(*psz)) {
#      57                 :            :         // Decode base58 character
#      58                 :    1653165 :         int carry = mapBase58[(uint8_t)*psz];
#      59         [ +  + ]:    1653165 :         if (carry == -1)  // Invalid b58 character
#      60                 :      24258 :             return false;
#      61                 :    1628907 :         int i = 0;
#      62 [ +  + ][ +  + ]:   55930512 :         for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
#         [ +  + ][ +  - ]
#      63                 :   54301605 :             carry += 58 * (*it);
#      64                 :   54301605 :             *it = carry % 256;
#      65                 :   54301605 :             carry /= 256;
#      66                 :   54301605 :         }
#      67                 :    1628907 :         assert(carry == 0);
#      68                 :    1628907 :         length = i;
#      69         [ +  + ]:    1628907 :         if (length + zeroes > max_ret_len) return false;
#      70                 :    1622653 :         psz++;
#      71                 :    1622653 :     }
#      72                 :            :     // Skip trailing spaces.
#      73         [ +  + ]:      43491 :     while (IsSpace(*psz))
#      74                 :         31 :         psz++;
#      75         [ +  + ]:      12979 :     if (*psz != 0)
#      76                 :          5 :         return false;
#      77                 :            :     // Skip leading zeroes in b256.
#      78                 :      12974 :     std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
#      79                 :            :     // Copy result into output vector.
#      80                 :      12974 :     vch.reserve(zeroes + (b256.end() - it));
#      81                 :      12974 :     vch.assign(zeroes, 0x00);
#      82         [ +  + ]:     724003 :     while (it != b256.end())
#      83                 :     711029 :         vch.push_back(*(it++));
#      84                 :      12974 :     return true;
#      85                 :      12974 : }
#      86                 :            : 
#      87                 :            : std::string EncodeBase58(Span<const unsigned char> input)
#      88                 :     155227 : {
#      89                 :            :     // Skip & count leading zeroes.
#      90                 :     155227 :     int zeroes = 0;
#      91                 :     155227 :     int length = 0;
#      92 [ +  + ][ +  + ]:     223698 :     while (input.size() > 0 && input[0] == 0) {
#      93                 :      68471 :         input = input.subspan(1);
#      94                 :      68471 :         zeroes++;
#      95                 :      68471 :     }
#      96                 :            :     // Allocate enough space in big-endian base58 representation.
#      97                 :     155227 :     int size = input.size() * 138 / 100 + 1; // log(256) / log(58), rounded up.
#      98                 :     155227 :     std::vector<unsigned char> b58(size);
#      99                 :            :     // Process the bytes.
#     100         [ +  + ]:   10452679 :     while (input.size() > 0) {
#     101                 :   10297452 :         int carry = input[0];
#     102                 :   10297452 :         int i = 0;
#     103                 :            :         // Apply "b58 = b58 * 256 + ch".
#     104 [ +  + ][ +  + ]:  556360191 :         for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
#         [ +  + ][ +  + ]
#     105                 :  546062739 :             carry += 256 * (*it);
#     106                 :  546062739 :             *it = carry % 58;
#     107                 :  546062739 :             carry /= 58;
#     108                 :  546062739 :         }
#     109                 :            : 
#     110                 :   10297452 :         assert(carry == 0);
#     111                 :   10297452 :         length = i;
#     112                 :   10297452 :         input = input.subspan(1);
#     113                 :   10297452 :     }
#     114                 :            :     // Skip leading zeroes in base58 result.
#     115                 :     155227 :     std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
#     116 [ -  + ][ +  + ]:     155227 :     while (it != b58.end() && *it == 0)
#                 [ -  + ]
#     117                 :          0 :         it++;
#     118                 :            :     // Translate the result into a string.
#     119                 :     155227 :     std::string str;
#     120                 :     155227 :     str.reserve(zeroes + (b58.end() - it));
#     121                 :     155227 :     str.assign(zeroes, '1');
#     122         [ +  + ]:   14111898 :     while (it != b58.end())
#     123                 :   13956671 :         str += pszBase58[*(it++)];
#     124                 :     155227 :     return str;
#     125                 :     155227 : }
#     126                 :            : 
#     127                 :            : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
#     128                 :         46 : {
#     129         [ +  + ]:         46 :     if (!ValidAsCString(str)) {
#     130                 :          6 :         return false;
#     131                 :          6 :     }
#     132                 :         40 :     return DecodeBase58(str.c_str(), vchRet, max_ret_len);
#     133                 :         40 : }
#     134                 :            : 
#     135                 :            : std::string EncodeBase58Check(Span<const unsigned char> input)
#     136                 :     155199 : {
#     137                 :            :     // add 4-byte hash check to the end
#     138                 :     155199 :     std::vector<unsigned char> vch(input.begin(), input.end());
#     139                 :     155199 :     uint256 hash = Hash(vch);
#     140                 :     155199 :     vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
#     141                 :     155199 :     return EncodeBase58(vch);
#     142                 :     155199 : }
#     143                 :            : 
#     144                 :            : [[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
#     145                 :      43899 : {
#     146 [ +  + ][ -  + ]:      43899 :     if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
#     147         [ +  + ]:      43899 :         (vchRet.size() < 4)) {
#     148                 :      30995 :         vchRet.clear();
#     149                 :      30995 :         return false;
#     150                 :      30995 :     }
#     151                 :            :     // re-calculate the checksum, ensure it matches the included 4-byte checksum
#     152                 :      12904 :     uint256 hash = Hash(MakeSpan(vchRet).first(vchRet.size() - 4));
#     153         [ +  + ]:      12904 :     if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
#     154                 :        203 :         vchRet.clear();
#     155                 :        203 :         return false;
#     156                 :        203 :     }
#     157                 :      12701 :     vchRet.resize(vchRet.size() - 4);
#     158                 :      12701 :     return true;
#     159                 :      12701 : }
#     160                 :            : 
#     161                 :            : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
#     162                 :      43901 : {
#     163         [ +  + ]:      43901 :     if (!ValidAsCString(str)) {
#     164                 :          2 :         return false;
#     165                 :          2 :     }
#     166                 :      43899 :     return DecodeBase58Check(str.c_str(), vchRet, max_ret);
#     167                 :      43899 : }

Generated by: LCOV version 1.14