3

I've been trying to create a function in TypeScript for converting to and from base58. I'm pretty familiar with base conversion generally: divide a number by a target base, and take each remainder as a digit of the conversion from right to left, until it equals 0.

But this took me into Bitcoin's source code, which does the base 58 conversion in a way I've never seen before, working from a stream of bytes from left-to-right instead of the way I'm used to.

Here's their function for encoding to base 58:

https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp#L87

Essentially, for each byte in the input buffer, it sets a variable carry to the value of that byte. Then working from the end of the zero-filled output buffer, it multiplies that byte by 256 and adds it to carry. It sets the output byte to carry %58 and sets carry to carry / 58 (integer division). It then moves back one byte and repeats until carry is 0.

Here's the loop as I have it written in TypeScript:

    let base58Bytes = Buffer.alloc(size);
    let length = 0;
while (input.length > 0) {
  let carry: number = input[0];
  let i = 0;

  for (
    let pos = base58Bytes.length - 1;
    (carry !== 0 || i < length) && pos >= 0;
    i++, pos--
  ) {
    carry += base58Bytes[pos] * 256;
    base58Bytes[pos] = carry % 58;
    carry = Math.floor(carry / 58);
  }

  length = i;
  input = input.subarray(1);
}

My problem:

I see that it works, but not why it works. Any time I google base conversion, I find the first method I discussed, but nothing about this method.

In particular, I don't understand why the output byte is multiplied by the source base (256 in this case) before being added to carry.

I can see it works from any base to any base, and have worked it out by hand multiple times. I just don't understand why it works yet nor can I find any resources that explain it.

devbanana
  • 131
  • 2

0 Answers0