diff --git a/electrum/segwit_addr.py b/electrum/segwit_addr.py index 3f3992a5a..05ee1d419 100644 --- a/electrum/segwit_addr.py +++ b/electrum/segwit_addr.py @@ -59,14 +59,14 @@ def bech32_encode(hrp, data): return hrp + '1' + ''.join([CHARSET[d] for d in combined]) -def bech32_decode(bech): +def bech32_decode(bech, ignore_long_length=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)): return (None, None) bech = bech.lower() pos = bech.rfind('1') - if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: + if pos < 1 or pos + 7 > len(bech) or (not ignore_long_length and len(bech) > 90): return (None, None) if not all(x in CHARSET for x in bech[pos+1:]): return (None, None) diff --git a/lib/lightning_payencode/bech32.py b/lib/lightning_payencode/bech32.py deleted file mode 100644 index 9b0817634..000000000 --- a/lib/lightning_payencode/bech32.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (c) 2017 Pieter Wuille -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -"""Reference implementation for Bech32 and segwit addresses.""" - - -CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" - - -def bech32_polymod(values): - """Internal function that computes the Bech32 checksum.""" - generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] - chk = 1 - for value in values: - top = chk >> 25 - chk = (chk & 0x1ffffff) << 5 ^ value - for i in range(5): - chk ^= generator[i] if ((top >> i) & 1) else 0 - return chk - - -def bech32_hrp_expand(hrp): - """Expand the HRP into values for checksum computation.""" - return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] - - -def bech32_verify_checksum(hrp, data): - """Verify a checksum given HRP and converted data characters.""" - return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1 - - -def bech32_create_checksum(hrp, data): - """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 - return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] - - -def bech32_encode(hrp, data): - """Compute a Bech32 string given HRP and data values.""" - combined = data + bech32_create_checksum(hrp, data) - return hrp + '1' + ''.join([CHARSET[d] for d in combined]) - - -def bech32_decode(bech): - """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)): - return (None, None) - bech = bech.lower() - pos = bech.rfind('1') - if pos < 1 or pos + 7 > len(bech): #or len(bech) > 90: - return (None, None) - if not all(x in CHARSET for x in bech[pos+1:]): - return (None, None) - hrp = bech[:pos] - data = [CHARSET.find(x) for x in bech[pos+1:]] - if not bech32_verify_checksum(hrp, data): - return (None, None) - return (hrp, data[:-6]) - - -def convertbits(data, frombits, tobits, pad=True): - """General power-of-2 base conversion.""" - acc = 0 - bits = 0 - ret = [] - maxv = (1 << tobits) - 1 - max_acc = (1 << (frombits + tobits - 1)) - 1 - for value in data: - if value < 0 or (value >> frombits): - return None - acc = ((acc << frombits) | value) & max_acc - bits += frombits - while bits >= tobits: - bits -= tobits - ret.append((acc >> bits) & maxv) - if pad: - if bits: - ret.append((acc << (tobits - bits)) & maxv) - elif bits >= frombits or ((acc << (tobits - bits)) & maxv): - return None - return ret - - -def decode(hrp, addr): - """Decode a segwit address.""" - hrpgot, data = bech32_decode(addr) - if hrpgot != hrp: - return (None, None) - decoded = convertbits(data[1:], 5, 8, False) - if decoded is None or len(decoded) < 2 or len(decoded) > 40: - return (None, None) - if data[0] > 16: - return (None, None) - if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32: - return (None, None) - return (data[0], decoded) - - -def encode(hrp, witver, witprog): - """Encode a segwit address.""" - ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) - assert decode(hrp, ret) is not (None, None) - return ret - diff --git a/lib/lightning_payencode/lnaddr.py b/lib/lightning_payencode/lnaddr.py index 911989267..ca9809b59 100755 --- a/lib/lightning_payencode/lnaddr.py +++ b/lib/lightning_payencode/lnaddr.py @@ -2,7 +2,7 @@ import traceback import ecdsa.curves from ..bitcoin import MyVerifyingKey, GetPubKey -from .bech32 import bech32_encode, bech32_decode, CHARSET +from ..segwit_addr import bech32_encode, bech32_decode, CHARSET from binascii import hexlify, unhexlify from bitstring import BitArray from decimal import Decimal @@ -79,7 +79,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, ignore_long_length=True) if fbhrp: if fbhrp != currency: raise ValueError("Not a bech32 address for this currency") @@ -251,7 +251,7 @@ class LnAddr(object): ) def lndecode(a, verbose=False): - hrp, data = bech32_decode(a) + hrp, data = bech32_decode(a, ignore_long_length=True) if not hrp: raise ValueError("Bad bech32 checksum")