Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/validators/btc_address.py: 100%
17 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:08 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:08 +0000
1"""BTC Address."""
2# -*- coding: utf-8 -*-
4# standard
5from hashlib import sha256
6import re
8# local
9from .utils import validator
12def _decode_base58(addr: str):
13 """Decode base58."""
14 alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
15 return sum((58**enm) * alphabet.index(idx) for enm, idx in enumerate(addr[::-1]))
18def _validate_old_btc_address(addr: str):
19 """Validate P2PKH and P2SH type address."""
20 if len(addr) not in range(25, 35):
21 return False
22 decoded_bytes = _decode_base58(addr).to_bytes(25, "big")
23 header, checksum = decoded_bytes[:-4], decoded_bytes[-4:]
24 return checksum == sha256(sha256(header).digest()).digest()[:4]
27@validator
28def btc_address(value: str, /):
29 """Return whether or not given value is a valid bitcoin address.
31 Full validation is implemented for P2PKH and P2SH addresses.
32 For segwit addresses a regexp is used to provide a reasonable
33 estimate on whether the address is valid.
35 Examples:
36 >>> btc_address('3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69')
37 # Output: True
38 >>> btc_address('1BvBMsEYstWetqTFn5Au4m4GFg7xJaNVN2')
39 # Output: ValidationFailure(func=btc_address, args=...)
41 Args:
42 value:
43 Bitcoin address string to validate.
45 Returns:
46 (Literal[True]):
47 If `value` is a valid bitcoin address.
48 (ValidationFailure):
49 If `value` is an invalid bitcoin address.
51 > *New in version 0.18.0*.
52 """
53 if not value:
54 return False
56 return (
57 # segwit pattern
58 re.compile(r"^(bc|tc)[0-3][02-9ac-hj-np-z]{14,74}$").match(value)
59 if value[:2] in ("bc", "tb")
60 else _validate_old_btc_address(value)
61 )