0

I am trying to make a base58 decoder in c following this tutorial https://learnmeabitcoin.com/technical/base58

To convert a base58 value in to base10,
you take each character index and multiply it with how many 58s that position in the number represents.

Then you just add all these values together.

base58 = BukQL

L = 19 * pow(58, 0) //= 19
Q = 23 * pow(58, 1) //= 1334
k = 43 * pow(58, 2) //= 144652
u = 52 * pow(58, 3) //= 10145824
B = 10 * pow(58, 4) //= 113164960

base10 = 19 + 1334 + 144652 + 10145824 + 113164960
base10 = 123456789

as you see the number can bee quite big fast only with 5 characters BukQL = 113164960

what if the string is BukQLKksdjkL7asSld = 11398419278238782..more there is no type in c who can store such very large numbers.

what is the best solution for this problem?

  • Don't convert them to numbers. Use plain strings to store and display the result. Btw, 113164960 isn't that big. `UINT64_MAX` is 18446744073709551615 for example. – Ted Lyngmo Jan 19 '22 at 21:30
  • if int64 is not big enough, you might want to find an existing extended-precision math library. Also, you can add without exponentials if you go high to low and do value = (old value * 58) + new digit. – Dave S Jan 19 '22 at 21:31
  • 2
    @Ted Lyngmo the result could be even larger than UINT64_MAX –  Jan 19 '22 at 21:34
  • The comment `// ^ in c == pow()` is wrong. – user3386109 Jan 19 '22 at 21:36
  • @ Dave S are you talking about storing piece by piece in an `uint64_t * bignum[33]` kind of array? –  Jan 19 '22 at 21:39
  • @ user3386109 really? i have tried using ^ rise of power with no result? could you be more specific –  Jan 19 '22 at 21:41
  • @dinolin `^` is XOR, not `pow` - why do you need them as numbers? Wouldn't using strings be fine? Do you need arithmetic operators? If so, use a BigNum library. – Ted Lyngmo Jan 19 '22 at 21:42
  • You can use `^` for exponents, and people will understand what you mean, but the `^` operator in C is the exclusive-OR operator. – user3386109 Jan 19 '22 at 21:43
  • @ user3386109 Re"You can use ^ for expon.." aah ok.. i will edit it adding pow –  Jan 19 '22 at 21:45
  • 2
    Don't use `pow` for integers though. You also do not need exponents here. – Ted Lyngmo Jan 19 '22 at 21:45
  • 2
    You may be interested in the [GNU multiple precision library](https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library) . – user3386109 Jan 19 '22 at 22:09
  • @user3386109 gona look at it now, thanks –  Jan 19 '22 at 22:19
  • Why base 58, though? Digits + letters would give you base 36, while digits + lowercase letters + uppercase letters would give you base 62. I wonder which 4 characters are missing in this representation? (But I don't wonder enough to, like, chase that link. :-) ) – Steve Summit Jan 19 '22 at 23:28
  • @ Steve Summit in Base 58 0,o and l <-- you probably thought that i said` (and i "but it's an L")`those characters are removed to skip bad reading from the user as they can MissInterpreting some characters with others .. as for example 0 looks like o or l loks like 1 or I and so on... :) –  Jan 20 '22 at 00:00

1 Answers1

1

what is the best solution for this problem?

Check for input validity

what if the string is BukQLKksdjkL7asSld = 11398419278238782..more

OP's assertion is in error as l is invalid.

The valid characters are 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz


Avoid floating power functions for an integer problem

Rather than pow(), simply scale by 58 on each iteration.

For up to 10 Base58 digits, code can use various 64-bit types.

const char base58[] =
    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

uintmax_t base58_decode(const char *s) {
  printf("<%s>", s);
  uintmax_t val = 0;
  while (*s) {
    const char *pos = strchr(base58, *s);
    if (pos == NULL) {
      printf("\nInvalid <%c>\n", *s);
      exit -1;
    }
    val = val * 58 + (pos - base58);
    s++;
  }
  printf(" %ju\n", val);
  return val;
}

// Call examples
base58_decode("BukQL");
base58_decode("BukQLKksdjkL7asSld");  // Error out on 'l'

Big numbers

To handle more that 10 digits, code needs to employ some extended math like this that uses a string to determine fibonacci(100).

Alternative

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • i was trying writing a solution for this also but yours where very effective and short well done – dn70a Jan 20 '22 at 00:13
  • you are right i didn't se the "l" `good that you noticed it`, there i was typing some random characters as an example `BukQLKksdjkL7asSld` i will be more careful when putting invalid examples or at least commenting on them –  Jan 20 '22 at 00:38
  • @dinolin The key is that _I_ did not notice it either. Instead I write code to find such as robust code does that. – chux - Reinstate Monica Jan 20 '22 at 01:24