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