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

1"""BTC Address.""" 

2# -*- coding: utf-8 -*- 

3 

4# standard 

5from hashlib import sha256 

6import re 

7 

8# local 

9from .utils import validator 

10 

11 

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])) 

16 

17 

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] 

25 

26 

27@validator 

28def btc_address(value: str, /): 

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

30 

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. 

34 

35 Examples: 

36 >>> btc_address('3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69') 

37 # Output: True 

38 >>> btc_address('1BvBMsEYstWetqTFn5Au4m4GFg7xJaNVN2') 

39 # Output: ValidationFailure(func=btc_address, args=...) 

40 

41 Args: 

42 value: 

43 Bitcoin address string to validate. 

44 

45 Returns: 

46 (Literal[True]): 

47 If `value` is a valid bitcoin address. 

48 (ValidationFailure): 

49 If `value` is an invalid bitcoin address. 

50 

51 > *New in version 0.18.0*. 

52 """ 

53 if not value: 

54 return False 

55 

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 )