19
19
# THE SOFTWARE.
20
20
21
21
"""Reference implementation for Bech32 and segwit addresses."""
22
+ from typing import Tuple
22
23
23
24
24
25
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
25
26
26
27
27
- def bech32_polymod (values ) :
28
+ def bech32_polymod (values : bytes ) -> int :
28
29
"""Internal function that computes the Bech32 checksum."""
29
30
generator = [0x3b6a57b2 , 0x26508e6d , 0x1ea119fa , 0x3d4233dd , 0x2a1462b3 ]
30
31
chk = 1
@@ -36,43 +37,47 @@ def bech32_polymod(values):
36
37
return chk
37
38
38
39
39
- def bech32_hrp_expand (hrp ) :
40
+ def bech32_hrp_expand (hrp : str ) -> bytes :
40
41
"""Expand the HRP into values for checksum computation."""
41
- return [ord (x ) >> 5 for x in hrp ] + [0 ] + [ord (x ) & 31 for x in hrp ]
42
+ return bytes ( [ord (x ) >> 5 for x in hrp ] + [0 ] + [ord (x ) & 31 for x in hrp ])
42
43
43
44
44
- def bech32_verify_checksum (hrp , data ) :
45
+ def bech32_verify_checksum (hrp : str , data : bytes ) -> bool :
45
46
"""Verify a checksum given HRP and converted data characters."""
46
47
return bech32_polymod (bech32_hrp_expand (hrp ) + data ) == 1
47
48
48
49
49
- def bech32_create_checksum (hrp , data ) :
50
+ def bech32_create_checksum (hrp : str , data : bytes ) -> bytes :
50
51
"""Compute the checksum values given HRP and data."""
51
52
values = bech32_hrp_expand (hrp ) + data
52
- polymod = bech32_polymod (values + [0 , 0 , 0 , 0 , 0 , 0 ]) ^ 1
53
- return [(polymod >> 5 * (5 - i )) & 31 for i in range (6 )]
53
+ polymod = bech32_polymod (values + bytes ( [0 , 0 , 0 , 0 , 0 , 0 ]) ) ^ 1
54
+ return bytes ( [(polymod >> 5 * (5 - i )) & 31 for i in range (6 )])
54
55
55
56
56
- def bech32_encode (hrp , data ) :
57
+ def bech32_encode (hrp : str , data : bytes ) -> str :
57
58
"""Compute a Bech32 string given HRP and data values."""
58
59
combined = data + bech32_create_checksum (hrp , data )
59
60
return hrp + '1' + '' .join ([CHARSET [d ] for d in combined ])
60
61
61
62
62
- def bech32_decode (bech ) :
63
+ def bech32_decode (bech : str ) -> Tuple [ str , bytes ] :
63
64
"""Validate a Bech32 string, and determine HRP and data."""
64
65
if ((any (ord (x ) < 33 or ord (x ) > 126 for x in bech )) or (bech .lower () != bech and bech .upper () != bech )):
65
- return (None , None )
66
+ raise ValueError ("Not a bech32-encoded string: {}" .format (bech ))
67
+
66
68
bech = bech .lower ()
67
69
pos = bech .rfind ('1' )
68
70
if pos < 1 or pos + 7 > len (bech ):
69
- return (None , None )
71
+ raise ValueError ("Could not locate hrp separator '1' in {}" .format (bech ))
72
+
70
73
if not all (x in CHARSET for x in bech [pos + 1 :]):
71
- return (None , None )
74
+ raise ValueError ("Non-bech32 character found in {}" .format (bech ))
75
+
72
76
hrp = bech [:pos ]
73
- data = [CHARSET .find (x ) for x in bech [pos + 1 :]]
77
+ data = bytes ( [CHARSET .find (x ) for x in bech [pos + 1 :]])
74
78
if not bech32_verify_checksum (hrp , data ):
75
- return (None , None )
79
+ raise ValueError ("Checksum verification failed for {}" .format (bech ))
80
+
76
81
return (hrp , data [:- 6 ])
77
82
78
83
0 commit comments