Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions bech32.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,33 @@ def bech32_hrp_expand(hrp):
return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]


def bech32_verify_checksum(hrp, data):
def bech32_verify_checksum(hrp, data, segwit_version=0):
"""Verify a checksum given HRP and converted data characters."""
return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
if segwit_version == 0:
const = 1 # Bech32
else:
const = 0x2bc830a3 # Bech32m
return bech32_polymod(bech32_hrp_expand(hrp) + data) == const


def bech32_create_checksum(hrp, data):
def bech32_create_checksum(hrp, data, segwit_version=0):
"""Compute the checksum values given HRP and data."""
values = bech32_hrp_expand(hrp) + data
polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
if segwit_version == 0:
const = 1 # Bech32
else:
const = 0x2bc830a3 # Bech32m
polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]


def bech32_encode(hrp, data):
def bech32_encode(hrp, data, segwit_version=0):
"""Compute a Bech32 string given HRP and data values."""
combined = data + bech32_create_checksum(hrp, data)
combined = data + bech32_create_checksum(hrp, data, segwit_version)
return hrp + '1' + ''.join([CHARSET[d] for d in combined])


def bech32_decode(bech):
def bech32_decode(bech, segwit_version_verify=False):
"""Validate a Bech32 string, and determine HRP and data."""
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
(bech.lower() != bech and bech.upper() != bech)):
Expand All @@ -72,7 +80,7 @@ def bech32_decode(bech):
return (None, None)
hrp = bech[:pos]
data = [CHARSET.find(x) for x in bech[pos+1:]]
if not bech32_verify_checksum(hrp, data):
if not bech32_verify_checksum(hrp, data, data[0] if segwit_version_verify else 0):
return (None, None)
return (hrp, data[:-6])

Expand Down
2 changes: 2 additions & 0 deletions examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ echo
echo '### On mainnet, with fallback (p2wsh) address bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3'
./lightning-address.py encode $TIMESTAMP --description-hashed="$LONG_DESCRIPTION" --fallback=bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3 $(to_btc 24) $RHASH $PRIVKEY

echo '### On mainnet, with fallback (p2tr) address bc1pptdvg0d2nj99568qn6ssdy4cygnwuxgw2ukmnwgwz7jpqjz2kszse2s3lm'
./lightning-address.py encode $TIMESTAMP --description-hashed="$LONG_DESCRIPTION" --fallback=bc1pptdvg0d2nj99568qn6ssdy4cygnwuxgw2ukmnwgwz7jpqjz2kszse2s3lm $(to_btc 24) $RHASH $PRIVKEY
4 changes: 2 additions & 2 deletions lnaddr.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def encode_fallback(fallback, currency):
""" Encode all supported fallback addresses.
"""
if currency == 'bc' or currency == 'tb':
fbhrp, witness = bech32_decode(fallback)
fbhrp, witness = bech32_decode(fallback, segwit_version_verify=True)
if fbhrp:
if fbhrp != currency:
raise ValueError("Not a bech32 address for this currency")
Expand Down Expand Up @@ -109,7 +109,7 @@ def parse_fallback(fallback, currency):
addr=base58.b58encode_check(bytes([base58_prefix_map[currency][1]])
+ fallback[5:].tobytes())
elif wver <= 16:
addr=bech32_encode(currency, bitarray_to_u5(fallback))
addr=bech32_encode(currency, bitarray_to_u5(fallback), wver)
else:
return None
else:
Expand Down