2022-05-23 00:16:32 +04:00

56 lines
1.5 KiB
Python

import re
from hashlib import sha256
from .utils import validator
segwit_pattern = re.compile(
r'^(bc|tc)[0-3][02-9ac-hj-np-z]{14,74}$')
def validate_segwit_address(addr):
return segwit_pattern.match(addr)
def decode_base58(addr):
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
return sum([
(58 ** e) * alphabet.index(i)
for e, i in enumerate(addr[::-1])
])
def validate_old_btc_address(addr):
"Validate P2PKH and P2SH type address"
if not len(addr) in range(25, 35):
return False
decoded_bytes = decode_base58(addr).to_bytes(25, "big")
header = decoded_bytes[:-4]
checksum = decoded_bytes[-4:]
return checksum == sha256(sha256(header).digest()).digest()[:4]
@validator
def btc_address(value):
"""
Return whether or not given value is a valid bitcoin address.
If the value is valid bitcoin address this function returns ``True``,
otherwise :class:`~validators.utils.ValidationFailure`.
Full validation is implemented for P2PKH and P2SH addresses.
For segwit addresses a regexp is used to provide a reasonable estimate
on whether the address is valid.
Examples::
>>> btc_address('3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69')
True
:param value: Bitcoin address string to validate
"""
if not value or not isinstance(value, str):
return False
if value[:2] in ("bc", "tb"):
return validate_segwit_address(value)
return validate_old_btc_address(value)