Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/validators/crypto_addresses/btc_address.py: 100%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

18 statements  

1"""BTC Address.""" 

2 

3# standard 

4from hashlib import sha256 

5import re 

6 

7# local 

8from validators.utils import validator 

9 

10 

11def _decode_base58(addr: str): 

12 """Decode base58.""" 

13 alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" 

14 return sum((58**enm) * alphabet.index(idx) for enm, idx in enumerate(addr[::-1])) 

15 

16 

17def _validate_old_btc_address(addr: str): 

18 """Validate P2PKH and P2SH type address.""" 

19 if len(addr) not in range(25, 35): 

20 return False 

21 decoded_bytes = _decode_base58(addr).to_bytes(25, "big") 

22 header, checksum = decoded_bytes[:-4], decoded_bytes[-4:] 

23 return checksum == sha256(sha256(header).digest()).digest()[:4] 

24 

25 

26@validator 

27def btc_address(value: str, /): 

28 """Return whether or not given value is a valid bitcoin address. 

29 

30 Full validation is implemented for P2PKH and P2SH addresses. 

31 For segwit addresses a regexp is used to provide a reasonable 

32 estimate on whether the address is valid. 

33 

34 Examples: 

35 >>> btc_address('3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69') 

36 True 

37 >>> btc_address('1BvBMsEYstWetqTFn5Au4m4GFg7xJaNVN2') 

38 ValidationError(func=btc_address, args={'value': '1BvBMsEYstWetqTFn5Au4m4GFg7xJaNVN2'}) 

39 

40 Args: 

41 value: 

42 Bitcoin address string to validate. 

43 

44 Returns: 

45 (Literal[True]): If `value` is a valid bitcoin address. 

46 (ValidationError): If `value` is an invalid bitcoin address. 

47 """ 

48 if not value: 

49 return False 

50 

51 return ( 

52 # segwit pattern 

53 re.compile(r"^(bc|tc)[0-3][02-9ac-hj-np-z]{14,74}$").match(value) 

54 if value[:2] in ("bc", "tb") 

55 else _validate_old_btc_address(value) 

56 )