Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
changes from 2.2
----------------

* Fix Base58 decoding of a Bitcoin address made only of the digit 1. That digit is a zero byte, so a string of them was one byte too long.


changes from 2.1 to 2.2
-----------------------

Expand Down
5 changes: 3 additions & 2 deletions stdnum/bitcoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ def b58decode(s: str) -> bytes:
"""Decode a Base58 encoded string to a bytestring."""
value = reduce(lambda a, c: a * 58 + _base58_alphabet.index(c), s, 0)
result = b''
while value >= 256:
# A zero value has no payload bytes. Each leading 1 is already a zero
# byte, so packing the leftover 0 here would add one extra.
while value:
value, mod = divmod(value, 256)
result = struct.pack('B', mod) + result
result = struct.pack('B', value) + result
return struct.pack('B', 0) * (len(s) - len(s.lstrip('1'))) + result


Expand Down
13 changes: 13 additions & 0 deletions tests/test_bitcoin.doctest
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ useful as module documentation.
>>> from stdnum import bitcoin


The digit 1 is zero. A string of them is that many zero bytes, and an empty
string is empty. A leftover zero must not add another byte.

>>> bitcoin.b58decode('1')
b'\x00'
>>> bitcoin.b58decode('11')
b'\x00\x00'
>>> bitcoin.b58decode('2')
b'\x01'
>>> bitcoin.b58decode('')
b''


These are found and constructed P2PKH addresses (P2SH addresses are basically
the same because they follow the same validation, except that the first digit
is a 3).
Expand Down
Loading