1
0
Fork 0
mirror of https://github.com/eosswedenorg/libantelope synced 2026-06-16 03:34:56 +02:00

include/libeosio/base58.hpp: adding base58_decode functions.

This commit is contained in:
Henrik Hautakoski 2023-03-09 18:18:10 +01:00
parent a43b913277
commit ed59959b5b
4 changed files with 136 additions and 0 deletions

View file

@ -36,6 +36,13 @@ std::string base58_encode(const std::string& str);
std::string base58_encode(const std::vector<unsigned char>& vch);
std::string base58_encode(const unsigned char* pbegin, const unsigned char* pend);
/**
* Base58 Decoding functions.
*/
bool base58_decode(const char* psz, std::string& out);
bool base58_decode(const std::string& str, std::string& out);
/**
* Returns true if `ch` is a base58 character, false otherwise.
*/

View file

@ -27,11 +27,35 @@
#include <algorithm>
#include <cstddef>
#include <cassert>
#include <cstring>
#include <libeosio/base58.hpp>
namespace libeosio {
static const char charmap[59] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const int8_t table[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 is_space(char c) {
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
}
std::string base58_encode(const unsigned char* pbegin, const unsigned char* pend) {
@ -84,6 +108,62 @@ std::string base58_encode(const std::vector<unsigned char>& vch) {
return base58_encode(vch.data(), vch.data() + vch.size());
}
bool base58_decode(const char* psz, std::string& out) {
// Skip leading spaces.
while (*psz && is_space(*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.
while (*psz && !is_space(*psz)) {
// Decode base58 character
int carry = table[(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 (is_space(*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.
out.reserve(zeroes + (b256.end() - it));
out.assign(zeroes, 0);
while (it != b256.end())
out.push_back(*(it++));
return true;
}
bool base58_decode(const std::string& str, std::string& out) {
return base58_decode(str.c_str(), out);
}
bool is_base58(char ch) {
for(unsigned int i=0; i < sizeof(charmap); i++) {
if (ch == charmap[i]) {

View file

@ -4,6 +4,7 @@ set(TEST_SRC
# Base58
base58/encode.cpp
base58/decode.cpp
base58/is_base58.cpp
# WIF

48
tests/base58/decode.cpp Normal file
View file

@ -0,0 +1,48 @@
#include <libeosio/base58.hpp>
#include <iostream>
#include <vector>
#include <doctest.h>
typedef struct {
std::string name;
std::string in;
std::string expectedOut;
bool expectedReturn;
} test_t;
typedef std::vector<test_t> tests;
TEST_CASE("base58_decode") {
tests input = {
test_t{"empty", "","", true},
test_t{"invalid","OI","",false},
test_t{
"valid #1",
"2nPTv2DT874jRaYBN4uhM9mT2iRiwdJuCXuX5buUHyyvWUSu6cX62i8HYo8PsWqgs9DHbwhpSpV5SVUnCqyLcpxcuGanH68eXgzZTGq",
"Quisque ut ipsum lorem. Nullam ac justo elit. Sed gravida convallis mattis.",
true
},
test_t{
"valid #2",
"5yAgp6rBagDHQZ3GacZSeaEPF2jfuwVHM21aNfXETJgn3EkArxc5UWSq1RM",
"Cras fringilla, eros et imperdiet tincidunt",
true
},
test_t{
"valid #3",
"9P7SxYWTWMq5hHkri53b1CGvWKRXxq3uXWPs5RiVtYagFrsnTXDxvKnk1twkPmV7BuxcRhBHWSwFLXpXbmdfHwZrnDaTB3wrBhsjm2Dd7F95ixh5vQLxajmT8hd22yUbvXuAZci8vTgFWMUyQi5YzWwntQiK5KFDkx3oA7kxvdU5t1yJZur84a9aKTCihEWtvCJ6LoBCpxvyB16YaCKeBQWLbUqoaXvFoDM78BpKD8biYyWQhnzHonjdwAS4KNXs5ByBdBvvPK1Q2Knr8zuFZxKHEFmgZGFTt8SMSsTDjkanUjojbfpJt5gcrHh6UFrt45n7kT9sj9Xsf1UyXZG3E2H85jXSbVnKowz2VPq1TkLLUKG8CSfdH3fVRp2E3yL5cpbbFWngbMzsbBZDgr4kPPcazebvSZ8qm8taBcBmt1ry25ey9TfFbMzP4FR1q9yjvkqGusMtrrBFm8YEeRmoMugMQoXvUgpExh29j",
"Praesent massa nibh, feugiat ac aliquet sed, varius quis metus. Fusce auctor imperdiet purus. Vivamus elementum risus vel imperdiet condimentum. Nunc iaculis, sem eu sollicitudin tempus, nibh felis scelerisque orci, a tincidunt felis lectus in nulla. Vestibulum egestas eu elit id luctus. Vivamus eget ipsum neque. Fusce eleifend mauris a tempus vehicula.",
true
},
};
for(tests::const_iterator it = input.begin(); it != input.end(); it++) {
SUBCASE(it->name.c_str()) {
std::string result;
CHECK( libeosio::base58_decode(it->in, result) == it->expectedReturn );
CHECK( result == it->expectedOut );
}
}
}