Branch data Line data Source code
# 1 : : // Copyright (c) 2014-2021 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 : 21256 : {
# 40 : : // Skip leading spaces.
# 41 [ + + ][ + + ]: 21284 : while (*psz && IsSpace(*psz))
# 42 : 28 : psz++;
# 43 : : // Skip and count leading '1's.
# 44 : 21256 : int zeroes = 0;
# 45 : 21256 : int length = 0;
# 46 [ + + ]: 130070 : while (*psz == '1') {
# 47 : 109250 : zeroes++;
# 48 [ + + ]: 109250 : if (zeroes > max_ret_len) return false;
# 49 : 108814 : psz++;
# 50 : 108814 : }
# 51 : : // Allocate enough space in big-endian base256 representation.
# 52 : 20820 : int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
# 53 : 20820 : std::vector<unsigned char> b256(size);
# 54 : : // Process the characters.
# 55 : 20820 : static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
# 56 [ + + ][ + + ]: 1550129 : while (*psz && !IsSpace(*psz)) {
# 57 : : // Decode base58 character
# 58 : 1533025 : int carry = mapBase58[(uint8_t)*psz];
# 59 [ + + ]: 1533025 : if (carry == -1) // Invalid b58 character
# 60 : 1802 : return false;
# 61 : 1531223 : int i = 0;
# 62 [ + + ][ + + ]: 67569218 : for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
# [ + + ][ + - ]
# 63 : 66037995 : carry += 58 * (*it);
# 64 : 66037995 : *it = carry % 256;
# 65 : 66037995 : carry /= 256;
# 66 : 66037995 : }
# 67 : 1531223 : assert(carry == 0);
# 68 : 0 : length = i;
# 69 [ + + ]: 1531223 : if (length + zeroes > max_ret_len) return false;
# 70 : 1529309 : psz++;
# 71 : 1529309 : }
# 72 : : // Skip trailing spaces.
# 73 [ + + ]: 17138 : while (IsSpace(*psz))
# 74 : 34 : psz++;
# 75 [ + + ]: 17104 : if (*psz != 0)
# 76 : 8 : return false;
# 77 : : // Skip leading zeroes in b256.
# 78 : 17096 : std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
# 79 : : // Copy result into output vector.
# 80 : 17096 : vch.reserve(zeroes + (b256.end() - it));
# 81 : 17096 : vch.assign(zeroes, 0x00);
# 82 [ + + ]: 1028434 : while (it != b256.end())
# 83 : 1011338 : vch.push_back(*(it++));
# 84 : 17096 : return true;
# 85 : 17104 : }
# 86 : :
# 87 : : std::string EncodeBase58(Span<const unsigned char> input)
# 88 : 225502 : {
# 89 : : // Skip & count leading zeroes.
# 90 : 225502 : int zeroes = 0;
# 91 : 225502 : int length = 0;
# 92 [ + + ][ + + ]: 288897 : while (input.size() > 0 && input[0] == 0) {
# 93 : 63395 : input = input.subspan(1);
# 94 : 63395 : zeroes++;
# 95 : 63395 : }
# 96 : : // Allocate enough space in big-endian base58 representation.
# 97 : 225502 : int size = input.size() * 138 / 100 + 1; // log(256) / log(58), rounded up.
# 98 : 225502 : std::vector<unsigned char> b58(size);
# 99 : : // Process the bytes.
# 100 [ + + ]: 16989447 : while (input.size() > 0) {
# 101 : 16763945 : int carry = input[0];
# 102 : 16763945 : int i = 0;
# 103 : : // Apply "b58 = b58 * 256 + ch".
# 104 [ + + ][ + + ]: 937609201 : for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
# [ + + ][ + + ]
# 105 : 920845256 : carry += 256 * (*it);
# 106 : 920845256 : *it = carry % 58;
# 107 : 920845256 : carry /= 58;
# 108 : 920845256 : }
# 109 : :
# 110 : 16763945 : assert(carry == 0);
# 111 : 0 : length = i;
# 112 : 16763945 : input = input.subspan(1);
# 113 : 16763945 : }
# 114 : : // Skip leading zeroes in base58 result.
# 115 : 225502 : std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
# 116 [ - + ][ + + ]: 225502 : while (it != b58.end() && *it == 0)
# [ - + ]
# 117 : 0 : it++;
# 118 : : // Translate the result into a string.
# 119 : 225502 : std::string str;
# 120 : 225502 : str.reserve(zeroes + (b58.end() - it));
# 121 : 225502 : str.assign(zeroes, '1');
# 122 [ + + ]: 22935481 : while (it != b58.end())
# 123 : 22709979 : str += pszBase58[*(it++)];
# 124 : 225502 : return str;
# 125 : 225502 : }
# 126 : :
# 127 : : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
# 128 : 604 : {
# 129 [ + + ]: 604 : if (!ValidAsCString(str)) {
# 130 : 6 : return false;
# 131 : 6 : }
# 132 : 598 : return DecodeBase58(str.c_str(), vchRet, max_ret_len);
# 133 : 604 : }
# 134 : :
# 135 : : std::string EncodeBase58Check(Span<const unsigned char> input)
# 136 : 225469 : {
# 137 : : // add 4-byte hash check to the end
# 138 : 225469 : std::vector<unsigned char> vch(input.begin(), input.end());
# 139 : 225469 : uint256 hash = Hash(vch);
# 140 : 225469 : vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
# 141 : 225469 : return EncodeBase58(vch);
# 142 : 225469 : }
# 143 : :
# 144 : : [[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
# 145 : 20658 : {
# 146 [ + + ][ - + ]: 20658 : if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
# 147 [ + + ]: 20658 : (vchRet.size() < 4)) {
# 148 : 3903 : vchRet.clear();
# 149 : 3903 : return false;
# 150 : 3903 : }
# 151 : : // re-calculate the checksum, ensure it matches the included 4-byte checksum
# 152 : 16755 : uint256 hash = Hash(Span{vchRet}.first(vchRet.size() - 4));
# 153 [ + + ]: 16755 : if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
# 154 : 174 : vchRet.clear();
# 155 : 174 : return false;
# 156 : 174 : }
# 157 : 16581 : vchRet.resize(vchRet.size() - 4);
# 158 : 16581 : return true;
# 159 : 16755 : }
# 160 : :
# 161 : : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
# 162 : 20660 : {
# 163 [ + + ]: 20660 : if (!ValidAsCString(str)) {
# 164 : 2 : return false;
# 165 : 2 : }
# 166 : 20658 : return DecodeBase58Check(str.c_str(), vchRet, max_ret);
# 167 : 20660 : }
|