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 : : /** 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 : 316668 : [[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
39 : : {
40 : : // Skip leading spaces.
41 [ + + + + ]: 449349 : while (*psz && IsSpace(*psz))
42 : 132681 : psz++;
43 : : // Skip and count leading '1's.
44 : 316668 : int zeroes = 0;
45 : 316668 : int length = 0;
46 [ + + ]: 335090 : while (*psz == '1') {
47 : 18538 : zeroes++;
48 [ + + ]: 18538 : if (zeroes > max_ret_len) return false;
49 : 18422 : psz++;
50 : : }
51 : : // Allocate enough space in big-endian base256 representation.
52 : 316552 : int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
53 [ + - ]: 316552 : std::vector<unsigned char> b256(size);
54 : : // Process the characters.
55 : : static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range
56 [ + + + + ]: 29819367 : while (*psz && !IsSpace(*psz)) {
57 : : // Decode base58 character
58 : 29538776 : int carry = mapBase58[(uint8_t)*psz];
59 [ + + ]: 29538776 : if (carry == -1) // Invalid b58 character
60 : 3064 : return false;
61 : 29535712 : int i = 0;
62 [ + + + + : 1165283972 : for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
+ + + - ]
63 : 1135748260 : carry += 58 * (*it);
64 : 1135748260 : *it = carry % 256;
65 : 1135748260 : carry /= 256;
66 : 1135748260 : }
67 [ + - ]: 29535712 : assert(carry == 0);
68 : 29535712 : length = i;
69 [ + + ]: 29535712 : if (length + zeroes > max_ret_len) return false;
70 : 29502815 : psz++;
71 [ + + ]: 29538776 : }
72 : : // Skip trailing spaces.
73 [ + + ]: 1663908 : while (IsSpace(*psz))
74 : 1383317 : psz++;
75 [ + + ]: 280591 : if (*psz != 0)
76 : 264 : return false;
77 : : // Skip leading zeroes in b256.
78 : 280327 : std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
79 : : // Copy result into output vector.
80 [ + - ]: 280327 : vch.reserve(zeroes + (b256.end() - it));
81 [ - + ]: 280327 : vch.assign(zeroes, 0x00);
82 [ + + ]: 20717724 : while (it != b256.end())
83 [ + - ]: 20437397 : vch.push_back(*(it++));
84 : 280327 : return true;
85 : 316668 : }
86 : :
87 : 2377959 : std::string EncodeBase58(Span<const unsigned char> input)
88 : : {
89 : : // Skip & count leading zeroes.
90 : 2377959 : int zeroes = 0;
91 : 2377959 : int length = 0;
92 [ + + + + ]: 2418289 : while (input.size() > 0 && input[0] == 0) {
93 : 40330 : input = input.subspan(1);
94 : 40330 : zeroes++;
95 : : }
96 : : // Allocate enough space in big-endian base58 representation.
97 : 2377959 : int size = input.size() * 138 / 100 + 1; // log(256) / log(58), rounded up.
98 [ + - ]: 2377959 : std::vector<unsigned char> b58(size);
99 : : // Process the bytes.
100 [ + + ]: 166880404 : while (input.size() > 0) {
101 : 164502445 : int carry = input[0];
102 : 164502445 : int i = 0;
103 : : // Apply "b58 = b58 * 256 + ch".
104 [ + + + + : 8908497850 : for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
+ - + + +
- ]
105 [ + - ]: 8743995405 : carry += 256 * (*it);
106 [ + - ]: 8743995405 : *it = carry % 58;
107 : 8743995405 : carry /= 58;
108 : 8743995405 : }
109 : :
110 [ + - ]: 164502445 : assert(carry == 0);
111 : 164502445 : length = i;
112 : 164502445 : input = input.subspan(1);
113 : 164502445 : }
114 : : // Skip leading zeroes in base58 result.
115 : 2377959 : std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
116 [ + + - + ]: 2377959 : while (it != b58.end() && *it == 0)
117 : 0 : it++;
118 : : // Translate the result into a string.
119 : 2377959 : std::string str;
120 [ + - ]: 2377959 : str.reserve(zeroes + (b58.end() - it));
121 [ + - ]: 2377959 : str.assign(zeroes, '1');
122 [ + + ]: 225547476 : while (it != b58.end())
123 [ + - ]: 223169517 : str += pszBase58[*(it++)];
124 : 2377959 : return str;
125 [ + - ]: 2377959 : }
126 : :
127 : 4409 : bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
128 : : {
129 [ + + ]: 4409 : if (!ContainsNoNUL(str)) {
130 : 62 : return false;
131 : : }
132 : 4347 : return DecodeBase58(str.c_str(), vchRet, max_ret_len);
133 : 4409 : }
134 : :
135 : 2363675 : std::string EncodeBase58Check(Span<const unsigned char> input)
136 : : {
137 : : // add 4-byte hash check to the end
138 [ + - ]: 2363675 : std::vector<unsigned char> vch(input.begin(), input.end());
139 [ + - ]: 2363675 : uint256 hash = Hash(vch);
140 [ + - ]: 2363675 : vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
141 [ + - + - ]: 2363675 : return EncodeBase58(vch);
142 : 2363675 : }
143 : :
144 : 312321 : [[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
145 : : {
146 [ - + + + : 312321 : if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
+ + ]
147 : 277813 : (vchRet.size() < 4)) {
148 : 37249 : vchRet.clear();
149 : 37249 : return false;
150 : : }
151 : : // re-calculate the checksum, ensure it matches the included 4-byte checksum
152 : 275072 : uint256 hash = Hash(Span{vchRet}.first(vchRet.size() - 4));
153 [ + + ]: 275072 : if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
154 : 539 : vchRet.clear();
155 : 539 : return false;
156 : : }
157 : 274533 : vchRet.resize(vchRet.size() - 4);
158 : 274533 : return true;
159 : 312321 : }
160 : :
161 : 312395 : bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret)
162 : : {
163 [ + + ]: 312395 : if (!ContainsNoNUL(str)) {
164 : 74 : return false;
165 : : }
166 : 312321 : return DecodeBase58Check(str.c_str(), vchRet, max_ret);
167 : 312395 : }
|