Browse Source

bitcoin: 3x speedup for DecodeBase58Check

(compared to HEAD~2)

rewrite base_{decode,encode} based on 2fae7065e3/base58/__init__.py
master
SomberNight 3 years ago
parent
commit
0037053d73
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 81
      electrum/bitcoin.py

81
electrum/bitcoin.py

@ -559,33 +559,26 @@ def base_encode(v: bytes, *, base: int) -> str:
chars = __b58chars
if base == 43:
chars = __b43chars
long_value = 0
power_of_base = 1
for c in v[::-1]:
# naive but slow variant: long_value += (256**i) * c
long_value += power_of_base * c
power_of_base <<= 8
result = bytearray()
while long_value >= base:
div, mod = divmod(long_value, base)
result.append(chars[mod])
long_value = div
result.append(chars[long_value])
# Bitcoin does a little leading-zero-compression:
# leading 0-bytes in the input become leading-1s
nPad = 0
for c in v:
if c == 0x00:
nPad += 1
else:
break
result.extend([chars[0]] * nPad)
result.reverse()
origlen = len(v)
v = v.lstrip(b'\x00')
newlen = len(v)
num = int.from_bytes(v, byteorder='big')
string = b""
while num:
num, idx = divmod(num, base)
string = chars[idx:idx + 1] + string
result = chars[0:1] * (origlen - newlen) + string
return result.decode('ascii')
def base_decode(v: Union[bytes, str], *, base: int, length: int = None) -> Optional[bytes]:
""" decode v into a string of len bytes."""
def base_decode(v: Union[bytes, str], *, base: int) -> Optional[bytes]:
""" decode v into a string of len bytes.
based on the work of David Keijser in https://github.com/keis/base58
"""
# assert_bytes(v)
v = to_bytes(v, 'ascii')
if base not in (58, 43):
@ -595,33 +588,19 @@ def base_decode(v: Union[bytes, str], *, base: int, length: int = None) -> Optio
if base == 43:
chars = __b43chars
chars_inv = __b43chars_inv
long_value = 0
power_of_base = 1
for c in v[::-1]:
try:
digit = chars_inv[c]
except KeyError:
raise BaseDecodeError('Forbidden character {} for base {}'.format(c, base))
# naive but slow variant: long_value += digit * (base**i)
long_value += digit * power_of_base
power_of_base *= base
result = bytearray()
while long_value >= 256:
div, mod = divmod(long_value, 256)
result.append(mod)
long_value = div
result.append(long_value)
nPad = 0
for c in v:
if c == chars[0]:
nPad += 1
else:
break
result.extend(b'\x00' * nPad)
if length is not None and len(result) != length:
return None
result.reverse()
return bytes(result)
origlen = len(v)
v = v.lstrip(chars[0:1])
newlen = len(v)
num = 0
try:
for char in v:
num = num * base + chars_inv[char]
except KeyError:
raise BaseDecodeError('Forbidden character {} for base {}'.format(char, base))
return num.to_bytes(origlen - newlen + (num.bit_length() + 7) // 8, 'big')
class InvalidChecksum(BaseDecodeError):

Loading…
Cancel
Save