github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/base58.cpp (about) 1 // Copyright (c) 2014-2017 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 "common/base58.h" 6 7 #include <assert.h> 8 #include <string.h> 9 10 namespace neb { 11 /** All alphanumeric characters except for "0", "I", "O", and "l" */ 12 static const char *psz_base58 = 13 "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 14 static const int8_t map_base58[256] = { 15 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 18 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, 20 -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, 21 49, 50, 51, 52, 53, 54, 55, 56, 57, -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, -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, -1, -1, -1, -1, -1, -1, -1, -1, 26 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28 -1, -1, -1, -1, -1, -1, -1, -1, -1, 29 }; 30 31 bool decode_base58(const char *psz, std::vector<unsigned char> &vch) { 32 // Skip leading spaces. 33 while (*psz && isspace(*psz)) 34 psz++; 35 // Skip and count leading '1's. 36 int zeroes = 0; 37 int length = 0; 38 while (*psz == '1') { 39 zeroes++; 40 psz++; 41 } 42 // Allocate enough space in big-endian base256 representation. 43 int size = strlen(psz) * 733 / 1000 + 1; // log(58) / log(256), rounded up. 44 std::vector<unsigned char> b256(size); 45 // Process the characters. 46 static_assert( 47 sizeof(map_base58) / sizeof(map_base58[0]) == 256, 48 "map_base58.size() should be 256"); // guarantee not out of range 49 while (*psz && !isspace(*psz)) { 50 // Decode base58 character 51 int carry = map_base58[(uint8_t)*psz]; 52 if (carry == -1) // Invalid b58 character 53 return false; 54 int i = 0; 55 for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); 56 (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { 57 carry += 58 * (*it); 58 *it = carry % 256; 59 carry /= 256; 60 } 61 assert(carry == 0); 62 length = i; 63 psz++; 64 } 65 // Skip trailing spaces. 66 while (isspace(*psz)) 67 psz++; 68 if (*psz != 0) 69 return false; 70 // Skip leading zeroes in b256. 71 std::vector<unsigned char>::iterator it = b256.begin() + (size - length); 72 while (it != b256.end() && *it == 0) 73 it++; 74 // Copy result into output vector. 75 vch.reserve(zeroes + (b256.end() - it)); 76 vch.assign(zeroes, 0x00); 77 while (it != b256.end()) 78 vch.push_back(*(it++)); 79 return true; 80 } 81 82 std::string encode_base58(const unsigned char *pbegin, 83 const unsigned char *pend) { 84 // Skip & count leading zeroes. 85 int zeroes = 0; 86 int length = 0; 87 while (pbegin != pend && *pbegin == 0) { 88 pbegin++; 89 zeroes++; 90 } 91 // Allocate enough space in big-endian base58 representation. 92 int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up. 93 std::vector<unsigned char> b58(size); 94 // Process the bytes. 95 while (pbegin != pend) { 96 int carry = *pbegin; 97 int i = 0; 98 // Apply "b58 = b58 * 256 + ch". 99 for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); 100 (carry != 0 || i < length) && (it != b58.rend()); it++, i++) { 101 carry += 256 * (*it); 102 *it = carry % 58; 103 carry /= 58; 104 } 105 106 assert(carry == 0); 107 length = i; 108 pbegin++; 109 } 110 // Skip leading zeroes in base58 result. 111 std::vector<unsigned char>::iterator it = b58.begin() + (size - length); 112 while (it != b58.end() && *it == 0) 113 it++; 114 // Translate the result into a string. 115 std::string str; 116 str.reserve(zeroes + (b58.end() - it)); 117 str.assign(zeroes, '1'); 118 while (it != b58.end()) 119 str += psz_base58[*(it++)]; 120 return str; 121 } 122 123 std::string encode_base58(const std::vector<unsigned char> &vch) { 124 return encode_base58(vch.data(), vch.data() + vch.size()); 125 } 126 127 bool decode_base58(const std::string &str, std::vector<unsigned char> &vchRet) { 128 return decode_base58(str.c_str(), vchRet); 129 } 130 } // namespace neb