Changeset View
Changeset View
Standalone View
Standalone View
src/base58.cpp
Show All 9 Lines | |||||
#include <cassert> | #include <cassert> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <cstring> | #include <cstring> | ||||
/** All alphanumeric characters except for "0", "I", "O", and "l" */ | /** All alphanumeric characters except for "0", "I", "O", and "l" */ | ||||
static const char *pszBase58 = | static const char *pszBase58 = | ||||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | ||||
static const int8_t mapBase58[256] = { | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, | |||||
8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, | |||||
19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, | |||||
-1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, | |||||
49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, | |||||
}; | |||||
bool DecodeBase58(const char *psz, std::vector<uint8_t> &vch) { | bool DecodeBase58(const char *psz, std::vector<uint8_t> &vch) { | ||||
// Skip leading spaces. | // Skip leading spaces. | ||||
while (*psz && IsSpace(*psz)) { | while (*psz && IsSpace(*psz)) { | ||||
psz++; | psz++; | ||||
} | } | ||||
// Skip and count leading '1's. | // Skip and count leading '1's. | ||||
int zeroes = 0; | int zeroes = 0; | ||||
int length = 0; | int length = 0; | ||||
while (*psz == '1') { | while (*psz == '1') { | ||||
zeroes++; | zeroes++; | ||||
psz++; | psz++; | ||||
} | } | ||||
// Allocate enough space in big-endian base256 representation. | // Allocate enough space in big-endian base256 representation. | ||||
// log(58) / log(256), rounded up. | // log(58) / log(256), rounded up. | ||||
int size = strlen(psz) * 733 / 1000 + 1; | int size = strlen(psz) * 733 / 1000 + 1; | ||||
std::vector<uint8_t> b256(size); | std::vector<uint8_t> b256(size); | ||||
// Process the characters. | // Process the characters. | ||||
// guarantee not out of range | |||||
static_assert(sizeof(mapBase58) / sizeof(mapBase58[0]) == 256, | |||||
"mapBase58.size() should be 256"); | |||||
while (*psz && !IsSpace(*psz)) { | while (*psz && !IsSpace(*psz)) { | ||||
// Decode base58 character | // Decode base58 character | ||||
const char *ch = strchr(pszBase58, *psz); | int carry = mapBase58[(uint8_t)*psz]; | ||||
if (ch == nullptr) { | // Invalid b58 character | ||||
if (carry == -1) { | |||||
return false; | return false; | ||||
} | } | ||||
// Apply "b256 = b256 * 58 + ch". | |||||
int carry = ch - pszBase58; | |||||
int i = 0; | int i = 0; | ||||
for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin(); | for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin(); | ||||
(carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { | (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { | ||||
carry += 58 * (*it); | carry += 58 * (*it); | ||||
*it = carry % 256; | *it = carry % 256; | ||||
carry /= 256; | carry /= 256; | ||||
} | } | ||||
assert(carry == 0); | assert(carry == 0); | ||||
▲ Show 20 Lines • Show All 100 Lines • Show Last 20 Lines |