| 36 | }; |
| 37 | |
| 38 | [[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len) |
| 39 | { |
| 40 | // Skip leading spaces. |
| 41 | while (*psz && IsSpace(*psz)) |
| 42 | psz++; |
| 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) return false; |
| 49 | psz++; |
| 50 | } |
| 51 | // Allocate enough space in big-endian base256 representation. |
| 52 | int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up. |
| 53 | std::vector<unsigned char> b256(size); |
| 54 | // Process the characters. |
| 55 | static_assert(std::size(mapBase58) == 256, "mapBase58.size() should be 256"); // guarantee not out of range |
| 56 | while (*psz && !IsSpace(*psz)) { |
| 57 | // Decode base58 character |
| 58 | int carry = mapBase58[(uint8_t)*psz]; |
| 59 | if (carry == -1) // Invalid b58 character |
| 60 | return false; |
| 61 | int i = 0; |
| 62 | for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) { |
| 63 | carry += 58 * (*it); |
| 64 | *it = carry % 256; |
| 65 | carry /= 256; |
| 66 | } |
| 67 | assert(carry == 0); |
| 68 | length = i; |
| 69 | if (length + zeroes > max_ret_len) return false; |
| 70 | psz++; |
| 71 | } |
| 72 | // Skip trailing spaces. |
| 73 | while (IsSpace(*psz)) |
| 74 | psz++; |
| 75 | if (*psz != 0) |
| 76 | return false; |
| 77 | // Skip leading zeroes in b256. |
| 78 | std::vector<unsigned char>::iterator it = b256.begin() + (size - length); |
| 79 | // Copy result into output vector. |
| 80 | vch.reserve(zeroes + (b256.end() - it)); |
| 81 | vch.assign(zeroes, 0x00); |
| 82 | while (it != b256.end()) |
| 83 | vch.push_back(*(it++)); |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | std::string EncodeBase58(Span<const unsigned char> input) |
| 88 | { |