/ref/python/segwit_addr.py

https://github.com/sipa/bech32 · Python · 137 lines · 88 code · 19 blank · 30 comment · 46 complexity · d6c96f4a3074828bff4a3a2bdd63766a MD5 · raw file

  1. # Copyright (c) 2017, 2020 Pieter Wuille
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. # THE SOFTWARE.
  20. """Reference implementation for Bech32/Bech32m and segwit addresses."""
  21. from enum import Enum
  22. class Encoding(Enum):
  23. """Enumeration type to list the various supported encodings."""
  24. BECH32 = 1
  25. BECH32M = 2
  26. CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
  27. BECH32M_CONST = 0x2bc830a3
  28. def bech32_polymod(values):
  29. """Internal function that computes the Bech32 checksum."""
  30. generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
  31. chk = 1
  32. for value in values:
  33. top = chk >> 25
  34. chk = (chk & 0x1ffffff) << 5 ^ value
  35. for i in range(5):
  36. chk ^= generator[i] if ((top >> i) & 1) else 0
  37. return chk
  38. def bech32_hrp_expand(hrp):
  39. """Expand the HRP into values for checksum computation."""
  40. return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
  41. def bech32_verify_checksum(hrp, data):
  42. """Verify a checksum given HRP and converted data characters."""
  43. const = bech32_polymod(bech32_hrp_expand(hrp) + data)
  44. if const == 1:
  45. return Encoding.BECH32
  46. if const == BECH32M_CONST:
  47. return Encoding.BECH32M
  48. return None
  49. def bech32_create_checksum(hrp, data, spec):
  50. """Compute the checksum values given HRP and data."""
  51. values = bech32_hrp_expand(hrp) + data
  52. const = BECH32M_CONST if spec == Encoding.BECH32M else 1
  53. polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
  54. return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
  55. def bech32_encode(hrp, data, spec):
  56. """Compute a Bech32 string given HRP and data values."""
  57. combined = data + bech32_create_checksum(hrp, data, spec)
  58. return hrp + '1' + ''.join([CHARSET[d] for d in combined])
  59. def bech32_decode(bech):
  60. """Validate a Bech32/Bech32m string, and determine HRP and data."""
  61. if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
  62. (bech.lower() != bech and bech.upper() != bech)):
  63. return (None, None, None)
  64. bech = bech.lower()
  65. pos = bech.rfind('1')
  66. if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
  67. return (None, None, None)
  68. if not all(x in CHARSET for x in bech[pos+1:]):
  69. return (None, None, None)
  70. hrp = bech[:pos]
  71. data = [CHARSET.find(x) for x in bech[pos+1:]]
  72. spec = bech32_verify_checksum(hrp, data)
  73. if spec is None:
  74. return (None, None, None)
  75. return (hrp, data[:-6], spec)
  76. def convertbits(data, frombits, tobits, pad=True):
  77. """General power-of-2 base conversion."""
  78. acc = 0
  79. bits = 0
  80. ret = []
  81. maxv = (1 << tobits) - 1
  82. max_acc = (1 << (frombits + tobits - 1)) - 1
  83. for value in data:
  84. if value < 0 or (value >> frombits):
  85. return None
  86. acc = ((acc << frombits) | value) & max_acc
  87. bits += frombits
  88. while bits >= tobits:
  89. bits -= tobits
  90. ret.append((acc >> bits) & maxv)
  91. if pad:
  92. if bits:
  93. ret.append((acc << (tobits - bits)) & maxv)
  94. elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
  95. return None
  96. return ret
  97. def decode(hrp, addr):
  98. """Decode a segwit address."""
  99. hrpgot, data, spec = bech32_decode(addr)
  100. if hrpgot != hrp:
  101. return (None, None)
  102. decoded = convertbits(data[1:], 5, 8, False)
  103. if decoded is None or len(decoded) < 2 or len(decoded) > 40:
  104. return (None, None)
  105. if data[0] > 16:
  106. return (None, None)
  107. if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
  108. return (None, None)
  109. if data[0] == 0 and spec != Encoding.BECH32 or data[0] != 0 and spec != Encoding.BECH32M:
  110. return (None, None)
  111. return (data[0], decoded)
  112. def encode(hrp, witver, witprog):
  113. """Encode a segwit address."""
  114. spec = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
  115. ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), spec)
  116. if decode(hrp, ret) == (None, None):
  117. return None
  118. return ret