Branch data Line data Source code
1 : : // Copyright (c) 2014-2022 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 : : using util::ContainsNoNUL;
18 : :
19 : : /** All alphanumeric characters except for "0", "I", "O", and "l" */
20 : : static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
21 : : static const int8_t mapBase58[256] = {
22 : : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
23 : : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
24 : : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
25 : : -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
26 : : -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
27 : : 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
28 : : -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
29 : : 47,48,49,50,51,52,53,54, 55,56,57,-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 : : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
37 : : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
38 : : };
39 : :
40 : 516500 : [[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
41 : : {
42 : : // Skip leading spaces.
43 [ + + + + ]: 1892305 : while (*psz && IsSpace(*psz))
44 : 1375805 : psz++;
45 : : // Skip and count leading '1's.
46 : : int zeroes = 0;
47 : 542586 : int length = 0;
48 [ + + ]: 542586 : while (*psz == '1') {
49 : 26215 : zeroes++;
50 [ + + ]: 26215 : if (zeroes > max_ret_len) return false;
51 : 26086 : psz++;
52 : : }
53 : : // Allocate enough space in big-endian base256 representation.
54 : 516371 : int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
55 : 516371 : std::vector<unsigned char> b256(size);
56 : : // Process the characters.
57 : : static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
58 [ + + + + ]: 49337356 : while (*psz && !IsSpace(*psz)) {
59 : : // Decode base58 character
60 : 48868032 : int carry = mapBase58[(uint8_t)*psz];
61 [ + + ]: 48868032 : if (carry == -1) // Invalid b58 character
62 : : return false;
63 : 48864018 : int i = 0;
64 [ + + - + ]: 1952271563 : for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
65 : 1903407545 : carry += 58 * (*it);
66 : 1903407545 : *it = carry % 256;
67 : 1903407545 : carry /= 256;
68 : : }
69 [ - + ]: 48864018 : assert(carry == 0);
70 : 48864018 : length = i;
71 [ + + ]: 48864018 : if (length + zeroes > max_ret_len) return false;
72 : 48820985 : psz++;
73 : : }
74 : : // Skip trailing spaces.
75 [ + + ]: 2198645 : while (IsSpace(*psz))
76 : 1729321 : psz++;
77 [ + + ]: 469324 : if (*psz != 0)
78 : : return false;
79 : : // Skip leading zeroes in b256.
80 [ + - ]: 469077 : std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
81 : : // Copy result into output vector.
82 [ + - ]: 469077 : vch.reserve(zeroes + (b256.end() - it));
83 [ + - ]: 469077 : vch.assign(zeroes, 0x00);
84 [ + + ]: 34797989 : while (it != b256.end())
85 [ + - ]: 34328912 : vch.push_back(*(it++));
86 : : return true;
87 : 516371 : }
88 : :
89 : 1506618 : std::string EncodeBase58(Span<const unsigned char> input)
90 : : {
91 : : // Skip & count leading zeroes.
92 : 1506618 : int zeroes = 0;
93 : 1506618 : int length = 0;
94 [ + + + + ]: 1533171 : while (input.size() > 0 && input[0] == 0) {
95 : 26553 : input = input.subspan(1);
96 : 26553 : zeroes++;
97 : : }
98 : : // Allocate enough space in big-endian base58 representation.
99 : 1506618 : int size = input.size() * 138 / 100 + 1; // log(256) / log(58), rounded up.
100 : 1506618 : std::vector<unsigned char> b58(size);
101 : : // Process the bytes.
102 [ + + ]: 100167869 : while (input.size() > 0) {
103 : 98661251 : int carry = input[0];
104 : 98661251 : int i = 0;
105 : : // Apply "b58 = b58 * 256 + ch".
106 [ + + - + ]: 5224322830 : for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
107 : 5125661579 : carry += 256 * (*it);
108 : 5125661579 : *it = carry % 58;
109 : 5125661579 : carry /= 58;
110 : : }
111 : :
112 [ - + ]: 98661251 : assert(carry == 0);
113 : 98661251 : length = i;
114 : 98661251 : input = input.subspan(1);
115 : : }
116 : : // Skip leading zeroes in base58 result.
117 : 1506618 : std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
118 [ + + + - ]: 1506618 : while (it != b58.end() && *it == 0)
119 : 0 : it++;
120 : : // Translate the result into a string.
121 [ + - ]: 1506618 : std::string str;
122 [ + - ]: 1506618 : str.reserve(zeroes + (b58.end() - it));
123 [ + - ]: 1506618 : str.assign(zeroes, '1');
124 : 135471391 : while (it != b58.end())
125 [ + - + + ]: 135471391 : str += pszBase58[*(it++)];
126 : 1506618 : return str;
127 : 1506618 : }
128 : :
129 : 9194 : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
130 : : {
131 [ + + ]: 18388 : if (!ContainsNoNUL(str)) {
132 : : return false;
133 : : }
134 : 8533 : return DecodeBase58(str.c_str(), vchRet, max_ret_len);
135 : : }
136 : :
137 : 1494135 : std::string EncodeBase58Check(Span<const unsigned char> input)
138 : : {
139 : : // add 4-byte hash check to the end
140 : 1494135 : std::vector<unsigned char> vch(input.begin(), input.end());
141 [ + - ]: 1494135 : uint256 hash = Hash(vch);
142 [ + - ]: 1494135 : vch.insert(vch.end(), hash.data(), hash.data() + 4);
143 [ + - ]: 1494135 : return EncodeBase58(vch);
144 : 1494135 : }
145 : :
146 : 507967 : [[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
147 : : {
148 [ + + ]: 507967 : if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
149 [ + + ]: 462820 : (vchRet.size() < 4)) {
150 [ + + ]: 51292 : vchRet.clear();
151 : 51292 : return false;
152 : : }
153 : : // re-calculate the checksum, ensure it matches the included 4-byte checksum
154 : 456675 : uint256 hash = Hash(Span{vchRet}.first(vchRet.size() - 4));
155 [ + + ]: 456675 : if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
156 [ + - ]: 1389 : vchRet.clear();
157 : 1389 : return false;
158 : : }
159 : 455286 : vchRet.resize(vchRet.size() - 4);
160 : 455286 : return true;
161 : : }
162 : :
163 : 508640 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
164 : : {
165 [ + + ]: 1017280 : if (!ContainsNoNUL(str)) {
166 : : return false;
167 : : }
168 : 507967 : return DecodeBase58Check(str.c_str(), vchRet, max_ret);
169 : : }
|