Created
October 24, 2018 16:16
-
-
Save tianchaijz/01ae6db83113f392199510aebd94607d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2014-2018 The Bitcoin Core developers | |
// Distributed under the MIT software license, see the accompanying | |
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
#include <vector> | |
#include <string> | |
#include <cctype> | |
#include <iostream> | |
#include <assert.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
/** All alphanumeric characters except for "0", "I", "O", and "l" */ | |
static const char *pszBase58 = | |
"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<unsigned char> &vch) { | |
// Skip leading spaces. | |
while (*psz && isspace(*psz)) | |
psz++; | |
// Skip and count leading '1's. | |
int zeroes = 0; | |
int length = 0; | |
while (*psz == '1') { | |
zeroes++; | |
psz++; | |
} | |
// Allocate enough space in big-endian base256 representation. | |
int size = strlen(psz) * 733 / 1000 + 1; // log(58) / log(256), rounded up. | |
std::vector<unsigned char> b256(size); | |
// Process the characters. | |
static_assert( | |
sizeof(mapBase58) / sizeof(mapBase58[0]) == 256, | |
"mapBase58.size() should be 256"); // guarantee not out of range | |
while (*psz && !isspace(*psz)) { | |
// Decode base58 character | |
int carry = mapBase58[(uint8_t)*psz]; | |
if (carry == -1) // Invalid b58 character | |
return false; | |
int i = 0; | |
for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); | |
(carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { | |
carry += 58 * (*it); | |
*it = carry % 256; | |
carry /= 256; | |
} | |
assert(carry == 0); | |
length = i; | |
psz++; | |
} | |
// Skip trailing spaces. | |
while (isspace(*psz)) | |
psz++; | |
if (*psz != 0) | |
return false; | |
// Skip leading zeroes in b256. | |
std::vector<unsigned char>::iterator it = b256.begin() + (size - length); | |
while (it != b256.end() && *it == 0) | |
it++; | |
// Copy result into output vector. | |
vch.reserve(zeroes + (b256.end() - it)); | |
vch.assign(zeroes, 0x00); | |
while (it != b256.end()) { | |
vch.push_back(*(it++)); | |
} | |
return true; | |
} | |
std::string EncodeBase58(const unsigned char *pbegin, | |
const unsigned char *pend) { | |
// Skip & count leading zeroes. | |
int zeroes = 0; | |
int length = 0; | |
while (pbegin != pend && *pbegin == 0) { | |
pbegin++; | |
zeroes++; | |
} | |
// Allocate enough space in big-endian base58 representation. | |
int size = | |
(pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. | |
std::vector<unsigned char> b58(size); | |
// Process the bytes. | |
while (pbegin != pend) { | |
int carry = *pbegin; | |
int i = 0; | |
// Apply "b58 = b58 * 256 + ch". | |
int m = size - 1; | |
for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); | |
(carry != 0 || i < length) && (it != b58.rend()); it++, i++) { | |
carry += 256 * (*it); | |
*it = carry % 58; | |
carry /= 58; | |
} | |
assert(carry == 0); | |
length = i; | |
pbegin++; | |
} | |
// Skip leading zeroes in base58 result. | |
std::vector<unsigned char>::iterator it = b58.begin() + (size - length); | |
while (it != b58.end() && *it == 0) | |
it++; | |
// Translate the result into a string. | |
std::string str; | |
str.reserve(zeroes + (b58.end() - it)); | |
str.assign(zeroes, '1'); | |
while (it != b58.end()) { | |
str += pszBase58[*(it++)]; | |
} | |
return str; | |
} | |
std::string EncodeBase58(const std::vector<unsigned char> &vch) { | |
return EncodeBase58(vch.data(), vch.data() + vch.size()); | |
} | |
bool DecodeBase58(const std::string &str, std::vector<unsigned char> &vchRet) { | |
return DecodeBase58(str.c_str(), vchRet); | |
} | |
int main() { | |
std::string hash = "2noDGfzjJERhDvQ3kifCdX6QiL5XBMX6y3A44D5cH8twybYN9g"; | |
std::vector<unsigned char> res; | |
std::string bin; | |
DecodeBase58(hash.c_str(), res); | |
for (auto c : res) { | |
bin += c; | |
} | |
std::cout << std::endl; | |
std::cout << res.size() << std::endl; | |
std::cout << bin << std::endl; | |
auto b58 = EncodeBase58(&*res.cbegin(), &*res.cend()); | |
std::cout << b58 << ", " << b58.size() << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment