Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
base58.cpp
Go to the documentation of this file.
1// Copyright (c) 2014-2016 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 <cassert>
13#include <cstdint>
14#include <cstring>
15#include <limits>
16
18static const char *pszBase58 =
19 "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
20static const int8_t mapBase58[256] = {
21 -1, -1, -1, -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, -1, -1, -1,
23 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
24 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18,
25 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1,
26 -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48,
27 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
28 -1, -1, -1, -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, -1, -1, -1,
30 -1, -1, -1, -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, -1, -1, -1,
32 -1, -1, -1, -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, -1, -1, -1,
34 -1, -1, -1, -1, -1, -1, -1, -1, -1,
35};
36
37[[nodiscard]] static bool
38DecodeBase58(const char *psz, std::vector<uint8_t> &vch, int max_ret_len) {
39 // Skip leading spaces.
40 while (*psz && IsSpace(*psz)) {
41 psz++;
42 }
43 // Skip and count leading '1's.
44 int zeroes = 0;
45 int length = 0;
46 while (*psz == '1') {
47 zeroes++;
48 if (zeroes > max_ret_len) {
49 return false;
50 }
51 psz++;
52 }
53 // Allocate enough space in big-endian base256 representation.
54 // log(58) / log(256), rounded up.
55 int size = strlen(psz) * 733 / 1000 + 1;
56 std::vector<uint8_t> b256(size);
57 // Process the characters.
58 // guarantee not out of range
59 static_assert(std::size(mapBase58) == 256,
60 "mapBase58.size() should be 256");
61 while (*psz && !IsSpace(*psz)) {
62 // Decode base58 character
63 int carry = mapBase58[(uint8_t)*psz];
64 // Invalid b58 character
65 if (carry == -1) {
66 return false;
67 }
68 int i = 0;
69 for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin();
70 (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
71 carry += 58 * (*it);
72 *it = carry % 256;
73 carry /= 256;
74 }
75 assert(carry == 0);
76 length = i;
77 if (length + zeroes > max_ret_len) {
78 return false;
79 }
80 psz++;
81 }
82 // Skip trailing spaces.
83 while (IsSpace(*psz)) {
84 psz++;
85 }
86 if (*psz != 0) {
87 return false;
88 }
89 // Skip leading zeroes in b256.
90 std::vector<uint8_t>::iterator it = b256.begin() + (size - length);
91
92 // Copy result into output vector.
93 vch.reserve(zeroes + (b256.end() - it));
94 vch.assign(zeroes, 0x00);
95 while (it != b256.end()) {
96 vch.push_back(*(it++));
97 }
98 return true;
99}
100
102 // Skip & count leading zeroes.
103 int zeroes = 0;
104 int length = 0;
105 while (input.size() > 0 && input[0] == 0) {
106 input = input.subspan(1);
107 zeroes++;
108 }
109 // Allocate enough space in big-endian base58 representation.
110 // log(256) / log(58), rounded up.
111 int size = input.size() * 138 / 100 + 1;
112 std::vector<uint8_t> b58(size);
113 // Process the bytes.
114 while (input.size() > 0) {
115 int carry = input[0];
116 int i = 0;
117 // Apply "b58 = b58 * 256 + ch".
118 for (std::vector<uint8_t>::reverse_iterator it = b58.rbegin();
119 (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
120 carry += 256 * (*it);
121 *it = carry % 58;
122 carry /= 58;
123 }
124
125 assert(carry == 0);
126 length = i;
127 input = input.subspan(1);
128 }
129 // Skip leading zeroes in base58 result.
130 std::vector<uint8_t>::iterator it = b58.begin() + (size - length);
131 while (it != b58.end() && *it == 0) {
132 it++;
133 }
134 // Translate the result into a string.
135 std::string str;
136 str.reserve(zeroes + (b58.end() - it));
137 str.assign(zeroes, '1');
138 while (it != b58.end()) {
139 str += pszBase58[*(it++)];
140 }
141 return str;
142}
143
144bool DecodeBase58(const std::string &str, std::vector<uint8_t> &vchRet,
145 int max_ret_len) {
146 if (!ContainsNoNUL(str)) {
147 return false;
148 }
149 return DecodeBase58(str.c_str(), vchRet, max_ret_len);
150}
151
153 // add 4-byte hash check to the end
154 std::vector<uint8_t> vch(input.begin(), input.end());
155 uint256 hash = Hash(vch);
156 vch.insert(vch.end(), (uint8_t *)&hash, (uint8_t *)&hash + 4);
157 return EncodeBase58(vch);
158}
159
160[[nodiscard]] static bool DecodeBase58Check(const char *psz,
161 std::vector<uint8_t> &vchRet,
162 int max_ret_len) {
163 if (!DecodeBase58(psz, vchRet,
164 max_ret_len > std::numeric_limits<int>::max() - 4
165 ? std::numeric_limits<int>::max()
166 : max_ret_len + 4) ||
167 (vchRet.size() < 4)) {
168 vchRet.clear();
169 return false;
170 }
171 // re-calculate the checksum, ensure it matches the included 4-byte checksum
172 uint256 hash = Hash(Span{vchRet}.first(vchRet.size() - 4));
173 if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
174 vchRet.clear();
175 return false;
176 }
177 vchRet.resize(vchRet.size() - 4);
178 return true;
179}
180
181bool DecodeBase58Check(const std::string &str, std::vector<uint8_t> &vchRet,
182 int max_ret) {
183 if (!ContainsNoNUL(str)) {
184 return false;
185 }
186 return DecodeBase58Check(str.c_str(), vchRet, max_ret);
187}
std::string EncodeBase58(Span< const uint8_t > input)
Why base-58 instead of standard base-64 encoding?
Definition base58.cpp:101
std::string EncodeBase58Check(Span< const uint8_t > input)
Encode a byte span into a base58-encoded string, including checksum.
Definition base58.cpp:152
static bool DecodeBase58(const char *psz, std::vector< uint8_t > &vch, int max_ret_len)
Definition base58.cpp:38
static bool DecodeBase58Check(const char *psz, std::vector< uint8_t > &vchRet, int max_ret_len)
Definition base58.cpp:160
static const char * pszBase58
All alphanumeric characters except for "0", "I", "O", and "l".
Definition base58.cpp:18
static const int8_t mapBase58[256]
Definition base58.cpp:20
A Span is an object that can refer to a contiguous sequence of objects.
Definition span.h:93
constexpr std::size_t size() const noexcept
Definition span.h:209
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
Definition span.h:218
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition span.h:227
constexpr C * begin() const noexcept
Definition span.h:199
constexpr C * end() const noexcept
Definition span.h:200
256-bit opaque blob.
Definition uint256.h:129
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition hash.h:74
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition string.h:90
assert(!tx.IsCoinBase())