segwit_addr.py
1 #!/usr/bin/env python3 2 # Copyright (c) 2017 Pieter Wuille 3 # Distributed under the MIT software license, see the accompanying 4 # file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 """Reference implementation for Bech32/Bech32m and segwit addresses.""" 6 import unittest 7 from enum import Enum 8 9 CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" 10 BECH32_CONST = 1 11 BECH32M_CONST = 0x2bc830a3 12 13 class Encoding(Enum): 14 """Enumeration type to list the various supported encodings.""" 15 BECH32 = 1 16 BECH32M = 2 17 18 19 def bech32_polymod(values): 20 """Internal function that computes the Bech32 checksum.""" 21 generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] 22 chk = 1 23 for value in values: 24 top = chk >> 25 25 chk = (chk & 0x1ffffff) << 5 ^ value 26 for i in range(5): 27 chk ^= generator[i] if ((top >> i) & 1) else 0 28 return chk 29 30 31 def bech32_hrp_expand(hrp): 32 """Expand the HRP into values for checksum computation.""" 33 return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] 34 35 36 def bech32_verify_checksum(hrp, data): 37 """Verify a checksum given HRP and converted data characters.""" 38 check = bech32_polymod(bech32_hrp_expand(hrp) + data) 39 if check == BECH32_CONST: 40 return Encoding.BECH32 41 elif check == BECH32M_CONST: 42 return Encoding.BECH32M 43 else: 44 return None 45 46 def bech32_create_checksum(encoding, hrp, data): 47 """Compute the checksum values given HRP and data.""" 48 values = bech32_hrp_expand(hrp) + data 49 const = BECH32M_CONST if encoding == Encoding.BECH32M else BECH32_CONST 50 polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const 51 return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] 52 53 54 def bech32_encode(encoding, hrp, data): 55 """Compute a Bech32 or Bech32m string given HRP and data values.""" 56 combined = data + bech32_create_checksum(encoding, hrp, data) 57 return hrp + '1' + ''.join([CHARSET[d] for d in combined]) 58 59 60 def bech32_decode(bech): 61 """Validate a Bech32/Bech32m string, and determine HRP and data.""" 62 if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or 63 (bech.lower() != bech and bech.upper() != bech)): 64 return (None, None, None) 65 bech = bech.lower() 66 pos = bech.rfind('1') 67 if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: 68 return (None, None, None) 69 if not all(x in CHARSET for x in bech[pos+1:]): 70 return (None, None, None) 71 hrp = bech[:pos] 72 data = [CHARSET.find(x) for x in bech[pos+1:]] 73 encoding = bech32_verify_checksum(hrp, data) 74 if encoding is None: 75 return (None, None, None) 76 return (encoding, hrp, data[:-6]) 77 78 79 def convertbits(data, frombits, tobits, pad=True): 80 """General power-of-2 base conversion.""" 81 acc = 0 82 bits = 0 83 ret = [] 84 maxv = (1 << tobits) - 1 85 max_acc = (1 << (frombits + tobits - 1)) - 1 86 for value in data: 87 if value < 0 or (value >> frombits): 88 return None 89 acc = ((acc << frombits) | value) & max_acc 90 bits += frombits 91 while bits >= tobits: 92 bits -= tobits 93 ret.append((acc >> bits) & maxv) 94 if pad: 95 if bits: 96 ret.append((acc << (tobits - bits)) & maxv) 97 elif bits >= frombits or ((acc << (tobits - bits)) & maxv): 98 return None 99 return ret 100 101 102 def decode_segwit_address(hrp, addr): 103 """Decode a segwit address.""" 104 encoding, hrpgot, data = bech32_decode(addr) 105 if hrpgot != hrp: 106 return (None, None) 107 decoded = convertbits(data[1:], 5, 8, False) 108 if decoded is None or len(decoded) < 2 or len(decoded) > 40: 109 return (None, None) 110 if data[0] > 16: 111 return (None, None) 112 if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32: 113 return (None, None) 114 if (data[0] == 0 and encoding != Encoding.BECH32) or (data[0] != 0 and encoding != Encoding.BECH32M): 115 return (None, None) 116 return (data[0], decoded) 117 118 119 def encode_segwit_address(hrp, witver, witprog): 120 """Encode a segwit address.""" 121 encoding = Encoding.BECH32 if witver == 0 else Encoding.BECH32M 122 ret = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5)) 123 if decode_segwit_address(hrp, ret) == (None, None): 124 return None 125 return ret 126 127 class TestFrameworkScript(unittest.TestCase): 128 def test_segwit_encode_decode(self): 129 def test_python_bech32(addr): 130 hrp = addr[:4] 131 self.assertEqual(hrp, "bcrt") 132 (witver, witprog) = decode_segwit_address(hrp, addr) 133 self.assertEqual(encode_segwit_address(hrp, witver, witprog), addr) 134 135 # P2WPKH 136 test_python_bech32('bcrt1qthmht0k2qnh3wy7336z05lu2km7emzfpm3wg46') 137 # P2WSH 138 test_python_bech32('bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj') 139 test_python_bech32('bcrt1qft5p2uhsdcdc3l2ua4ap5qqfg4pjaqlp250x7us7a8qqhrxrxfsqseac85') 140 # P2TR 141 test_python_bech32('bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6')