def gen_invalid_bech32_vector(template): '''Generate possibly invalid bech32 vector''' no_data = randbool(0.1) to_upper = randbool(0.1) hrp = template[0] witver = template[1] witprog = bytearray(os.urandom(template[2])) if no_data: rv = bech32_encode(hrp, []) else: data = [witver] + convertbits(witprog, 8, 5) if template[3] and not no_data: if template[2] % 5 in {2, 4}: data[-1] |= 1 else: data.append(0) rv = bech32_encode(hrp, data) if template[4]: i = len(rv) - random.randrange(1, 7) rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:] if template[5]: i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4) rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:] if to_upper: rv = rv.swapcase() return rv
def gen_valid_bech32_vector(template): '''Generate valid bech32 vector''' hrp = template[0] witver = template[1] witprog = bytearray(os.urandom(template[2])) dst_prefix = bytearray(template[4]) rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) return rv, dst_prefix + witprog
def P2WSHAddress(self): pk_bytes = self.PublicKey() assert len(pk_bytes) == 33 and (pk_bytes.startswith(b"\x02") or pk_bytes.startswith(b"\x03")) pk_added_code = bytes.fromhex('0014') + sha256(b"\x21" + pk_bytes + b"\xac").digest() hrp = "bc" if not self.testnet else "tb" l = list(bytearray(pk_added_code)) l0 = l[0] - 0x50 if l[0] else 0 address = bech32_encode(hrp, l0, l[2:]) return address
def P2WPKHAddress(self): "Return P2WPKH over P2SH segwit address" pk_bytes = self.PublicKey() assert len(pk_bytes) == 33 and (pk_bytes.startswith(b"\x02") or pk_bytes.startswith(b"\x03")) address_bytes = self.Identifier() push_20 = bytes.fromhex('0014') l = list(bytearray(push_20 + address_bytes)) l0 = l[0] - 0x50 if l[0] else 0 hrp = "bc" if not self.testnet else "tb" result = bech32_encode(hrp, l0, l[2:]) return result
def parse_fallback(fallback, currency): if currency in [ constants.BitcoinMainnet.SEGWIT_HRP, constants.BitcoinTestnet.SEGWIT_HRP ]: wver = fallback[0:5].uint if wver == 17: addr = hash160_to_b58_address(fallback[5:].tobytes(), base58_prefix_map[currency][0]) elif wver == 18: addr = hash160_to_b58_address(fallback[5:].tobytes(), base58_prefix_map[currency][1]) elif wver <= 16: addr = bech32_encode(currency, bitarray_to_u5(fallback)) else: return None else: addr = fallback.tobytes() return addr
def bech32Encode(hrp, data): ret = segwit_addr.bech32_encode(hrp, segwit_addr.convertbits(data, 8, 5)) if bech32Decode(hrp, ret) is None: return None return ret
def bech32Encode(hrp, data): ret = bech32_encode(hrp, convertbits(data, 8, 5)) if bech32Decode(hrp, ret) is None: return None return ret
# it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys import segwit_addr if len(sys.argv) not in [2, 3]: print("Usage: convertBechAddress.py ADDRESS [TO-HRP]") sys.exit(-1) addr = sys.argv[1] if len(sys.argv) >= 3: hrp = sys.argv[2] else: hrp = "chi" oldHrp, data = segwit_addr.bech32_decode(addr) print("Old HRP: %s" % oldHrp) newAddr = segwit_addr.bech32_encode(hrp, data) print(newAddr)
def lnencode(addr, privkey): if addr.amount: amount = Decimal(str(addr.amount)) # We can only send down to millisatoshi. if amount * 10**12 % 10: raise ValueError( "Cannot encode {}: too many decimal places".format( addr.amount)) amount = addr.currency + shorten_amount(amount) else: amount = addr.currency if addr.currency else '' hrp = 'ln' + amount # Start with the timestamp data = bitstring.pack('uint:35', addr.date) # Payment hash data += tagged_bytes('p', addr.paymenthash) tags_set = set() for k, v in addr.tags: # BOLT #11: # # A writer MUST NOT include more than one `d`, `h`, `n` or `x` fields, if k in ('d', 'h', 'n', 'x'): if k in tags_set: raise ValueError("Duplicate '{}' tag".format(k)) if k == 'r': route = bitstring.BitArray() for step in v: pubkey, channel, feebase, feerate, cltv = step route.append( bitstring.BitArray(pubkey) + bitstring.BitArray(channel) + bitstring.pack('intbe:32', feebase) + bitstring.pack('intbe:32', feerate) + bitstring.pack('intbe:16', cltv)) data += tagged('r', route) elif k == 'f': data += encode_fallback(v, addr.currency) elif k == 'd': data += tagged_bytes('d', v.encode()) elif k == 'x': # Get minimal length by trimming leading 5 bits at a time. expirybits = bitstring.pack('intbe:64', v)[4:64] while expirybits.startswith('0b00000'): expirybits = expirybits[5:] data += tagged('x', expirybits) elif k == 'h': data += tagged_bytes('h', sha256(v.encode('utf-8')).digest()) elif k == 'n': data += tagged_bytes('n', v) elif k == 'c': # Get minimal length by trimming leading 5 bits at a time. finalcltvbits = bitstring.pack('intbe:64', v)[4:64] while finalcltvbits.startswith('0b00000'): finalcltvbits = finalcltvbits[5:] data += tagged('c', finalcltvbits) else: # FIXME: Support unknown tags? raise ValueError("Unknown tag {}".format(k)) tags_set.add(k) # BOLT #11: # # A writer MUST include either a `d` or `h` field, and MUST NOT include # both. if 'd' in tags_set and 'h' in tags_set: raise ValueError("Cannot include both 'd' and 'h'") if not 'd' in tags_set and not 'h' in tags_set: raise ValueError("Must include either 'd' or 'h'") # We actually sign the hrp, then data (padded to 8 bits with zeroes). msg = hrp.encode("ascii") + data.tobytes() privkey = coincurve.PrivateKey(secret=privkey) sig = privkey.sign_recoverable(msg) #privkey = ecc.ECPrivkey(privkey) #sig = privkey.sign_message(msg, is_compressed=False, algo=lambda x:sha256(x).digest()) #recovery_flag = bytes([sig[0] - 27]) #sig = bytes(sig[1:]) + recovery_flag data += sig return bech32_encode(hrp, bitarray_to_u5(data))
def pk_encode(k): pk8 = hextobytes(k) pk5 = segwit_addr.convertbits(pk8, 8, 5) a = segwit_addr.bech32_encode('pk', pk5) return a
# it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys import segwit_addr if len (sys.argv) not in [2, 3]: print ("Usage: convertBechAddress.py ADDRESS [TO-HRP]") sys.exit (-1); addr = sys.argv[1] if len (sys.argv) >= 3: hrp = sys.argv[2] else: hrp = "nc" oldHrp, data = segwit_addr.bech32_decode (addr) print ("Old HRP: %s" % oldHrp) newAddr = segwit_addr.bech32_encode (hrp, data) print (newAddr)