electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 5f6f7da2a1be473a34a125509413d95475011e6a
parent 8cf3587aeb0b1fb767aee84792e15f75f90e8f23
Author: SomberNight <somber.night@protonmail.com>
Date:   Sun,  8 Dec 2019 06:56:19 +0100

bitcoin.py: base58 address: make sure all public methods test checksum

Note: the checksum was already being checked in practically all cases, by the caller.
Moved the check here, to the lower level (but still public) method for sanity.

Diffstat:
Melectrum/bitcoin.py | 7+++++--
Melectrum/tests/test_bitcoin.py | 10++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/electrum/bitcoin.py b/electrum/bitcoin.py @@ -328,7 +328,9 @@ def hash160_to_b58_address(h160: bytes, addrtype: int) -> str: def b58_address_to_hash160(addr: str) -> Tuple[int, bytes]: addr = to_bytes(addr, 'ascii') - _bytes = base_decode(addr, base=58, length=25) + _bytes = DecodeBase58Check(addr) + if len(_bytes) != 21: + raise Exception(f'expected 21 payload bytes in base58 address. got: {len(_bytes)}') return _bytes[0], _bytes[1:21] @@ -638,12 +640,13 @@ def is_segwit_address(addr: str, *, net=None) -> bool: def is_b58_address(addr: str, *, net=None) -> bool: if net is None: net = constants.net try: + # test length, checksum, encoding: addrtype, h = b58_address_to_hash160(addr) except Exception as e: return False if addrtype not in [net.ADDRTYPE_P2PKH, net.ADDRTYPE_P2SH]: return False - return addr == hash160_to_b58_address(h, addrtype) + return True def is_address(addr: str, *, net=None) -> bool: if net is None: net = constants.net diff --git a/electrum/tests/test_bitcoin.py b/electrum/tests/test_bitcoin.py @@ -711,6 +711,16 @@ class Test_keyImport(ElectrumTestCase): self.assertFalse(is_address("not an address")) + def test_is_address_bad_checksums(self): + self.assertTrue(is_address('1819s5TxxbBtuRPr3qYskMVC8sb1pqapWx')) + self.assertFalse(is_address('1819s5TxxbBtuRPr3qYskMVC8sb1pqapWw')) + + self.assertTrue(is_address('3LrjLVnngqnaJeo3BQwMBg34iqYsjZjQUe')) + self.assertFalse(is_address('3LrjLVnngqnaJeo3BQwMBg34iqYsjZjQUd')) + + self.assertTrue(is_address('bc1qxq64lrwt02hm7tu25lr3hm9tgzh58snfe67yt6')) + self.assertFalse(is_address('bc1qxq64lrwt02hm7tu25lr3hm9tgzh58snfe67yt5')) + @needs_test_with_all_ecc_implementations def test_is_private_key(self): for priv_details in self.priv_pub_addr: