def test_reconnect(bitcoind, node_factory, impls): node1 = node_factory.get_node(implementation=impls[0]) node2 = node_factory.get_node(implementation=impls[1]) capacity = 10**7 node1.connect('localhost', node2.daemon.port, node2.id()) wait_for(lambda: node1.peers(), interval=1) wait_for(lambda: node2.peers(), interval=1) node1.addfunds(bitcoind, 2*capacity) time.sleep(5) addr = bitcoind.rpc.getnewaddress() bitcoind.rpc.generatetoaddress(10, addr) time.sleep(5) node1.openchannel(node2.id(), 'localhost', node2.daemon.port, capacity) addr = bitcoind.rpc.getnewaddress() for i in range(30): node1.bitcoin.rpc.generatetoaddress(1, addr) time.sleep(1) wait_for(lambda: node1.check_channel(node2)) wait_for(lambda: node2.check_channel(node1)) sync_blockheight(bitcoind, [node1, node2]) amount = int(capacity / 10) req = node2.invoice(amount) payment_key = node1.send(req) dec = lndecode(req) assert(sha256(unhexlify(payment_key)).digest() == dec.paymenthash) print("Sleep before restart") time.sleep(5) print("Restarting") node2.restart() time.sleep(15) wait_for(lambda: node1.check_channel(node2)) wait_for(lambda: node2.check_channel(node1)) sync_blockheight(bitcoind, [node1, node2]) time.sleep(15) req = node2.invoice(amount) payment_key = node1.send(req) dec = lndecode(req) assert(sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def test_forwarded_payment(bitcoind, node_factory, impls): num_nodes = len(impls) nodes = [node_factory.get_node(implementation=impls[i]) for i in range(3)] capacity = 10**7 for i in range(num_nodes-1): nodes[i].connect('localhost', nodes[i+1].daemon.port, nodes[i+1].id()) nodes[i].addfunds(bitcoind, 4 * capacity) for i in range(num_nodes-1): nodes[i].openchannel(nodes[i+1].id(), 'localhost', nodes[i+1].daemon.port, capacity) assert confirm_channel(bitcoind, nodes[i], nodes[i+1]) addr = bitcoind.rpc.getnewaddress() bitcoind.rpc.generatetoaddress(6, addr) sync_blockheight(bitcoind, nodes) # Make sure we have a path ids = [n.info()['id'] for n in nodes] route = [(ids[i-1], ids[i]) for i in range(1, len(ids))] wait_for(lambda: node_has_route(nodes[0], route), timeout=120) sync_blockheight(bitcoind, nodes) src = nodes[0] dst = nodes[len(nodes)-1] amount = int(capacity / 10) req = dst.invoice(amount) print("Waiting for a route to be found") wait_for(lambda: src.check_route(dst.id(), amount), timeout=120) payment_key = src.send(req) dec = lndecode(req) assert(sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def test_direct_payment(bitcoind, node_factory, impls): node1 = node_factory.get_node(implementation=impls[0]) node2 = node_factory.get_node(implementation=impls[1]) capacity = 10**7 node1.connect('localhost', node2.daemon.port, node2.id()) wait_for(lambda: node1.peers(), interval=1) wait_for(lambda: node2.peers(), interval=1) node1.addfunds(bitcoind, 2 * capacity) time.sleep(5) bitcoind.rpc.generate(10) time.sleep(5) node1.openchannel(node2.id(), 'localhost', node2.daemon.port, capacity) generate_until(bitcoind, lambda: gossip_is_synced([node1, node2], 2), blocks=60, interval=1) sync_blockheight(bitcoind, [node1, node2]) amount = int(capacity / 10) req = node2.invoice(amount) payment_key = node1.send(req) dec = lndecode(req) assert (sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def test_direct_payment(bitcoind, node_factory, impls): node1 = node_factory.get_node(implementation=impls[0]) node2 = node_factory.get_node(implementation=impls[1]) capacity = 10**7 node1.connect('localhost', node2.daemon.port, node2.id()) wait_for(lambda: node1.peers(), interval=1) wait_for(lambda: node2.peers(), interval=1) node1.addfunds(bitcoind, 2*capacity) time.sleep(5) addr = bitcoind.rpc.getnewaddress() bitcoind.rpc.generatetoaddress(10, addr) time.sleep(5) node1.openchannel(node2.id(), 'localhost', node2.daemon.port, capacity) assert confirm_channel(bitcoind, node1, node2) sync_blockheight(bitcoind, [node1, node2]) amount = int(capacity / 10) req = node2.invoice(amount) dec = lndecode(req) print("Decoded payment request", req, dec) payment_key = node1.send(req) assert(sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def test_roundtrip(): longdescription = ( 'One piece of chocolate cake, one icecream cone, one' ' pickle, one slice of swiss cheese, one slice of salami,' ' one lollypop, one piece of cherry pie, one sausage, one' ' cupcake, and one slice of watermelon') tests = [ LnAddr(RHASH, tags=[('d', '')]), LnAddr(RHASH, amount=Decimal('0.001'), tags=[('d', '1 cup coffee'), ('x', 60)]), LnAddr(RHASH, amount=Decimal('1'), tags=[('h', longdescription)]), LnAddr(RHASH, currency='tb', tags=[('f', 'mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP'), ('h', longdescription)]), LnAddr( RHASH, amount=24, tags= [('r', [(unhexlify( '029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255' ), unhexlify('0102030405060708'), 1, 20, 3), (unhexlify( '039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255' ), unhexlify('030405060708090a'), 2, 30, 4)]), ('f', '1RustyRX2oai4EYYDpQGWvEL62BBGqN9T'), ('h', longdescription)]), LnAddr(RHASH, amount=24, tags=[('f', '3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX'), ('h', longdescription)]), LnAddr(RHASH, amount=24, tags=[('f', 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'), ('h', longdescription)]), LnAddr( RHASH, amount=24, tags=[( 'f', 'bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3' ), ('h', longdescription)]), LnAddr(RHASH, amount=24, tags=[('n', unhexlify(PUBKEY)), ('h', longdescription)]), ] # Roundtrip for t in tests: o = lndecode(lnencode(t, PRIVKEY)) compare(t, o)
def test_direct_payment(bitcoind, node_factory, impls): _csv_delay, capacity, node1, node2 = open_channel_get_invoice( bitcoind, node_factory, impls) amount = capacity // 10 * 1000 req = node2.invoice(amount) dec = lndecode(req) print("Decoded payment request", req, dec) payment_key = node1.send(req) assert (sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def test_n_decoding(): # We flip the signature recovery bit, which would normally give a different # pubkey. hrp, data = bech32_decode( lnencode(LnAddr(RHASH, amount=24, tags=[('d', '')]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) != PUBKEY # But not if we supply expliciy `n` specifier! hrp, data = bech32_decode( lnencode( LnAddr(RHASH, amount=24, tags=[('d', ''), ('n', unhexlify(PUBKEY))]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) == PUBKEY
def decode_func(options): try: a = lndecode(options.lnaddress, options.verbose) except AttributeError: a = lndecode(options) all_tags = { 'r': "Routes", 'd': "Description", 'f': "Fallback", 'h': "Description hash", 'x': "Expiry (seconds)", 'p': "Payment hash", 'n': "Payee node", 'c': "Minimum final CLTV expiry", } def tags_by_name(name, tags): return [t[1] for t in tags if t[0] == name] # Build decoded_request dict decoded_request = { "Signed with public key": hexlify(a.pubkey.serialize()), "Currency": a.currency, "Payment hash": hexlify(a.paymenthash), "Amount": a.amount, "Timestamp": a.date, } for k, v in all_tags.items(): if tags_by_name(k, a.tags): if k not in 'hpn': # list all tags here to be hexlified decoded_request[v] = tags_by_name(k, a.tags)[0] else: decoded_request[v] = hexlify(tags_by_name(k, a.tags)[0]) for t in [t for t in a.tags if t[0] not in all_tags.keys()]: decoded_request[f"UNKNOWN TAG {t[0]}"] = hexlify(t[1]) return decoded_request
def SignInvoice(self, request, context): """BOLT #11 - Invoice Protocol https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md """ node_id = request.node_id.data node = self.nodes.get(node_id) logger.debug("SignInvoice node:%s" % node_id.hex()) data = request.data_part hrp = request.human_readable_part import lnaddr lnaddr.lndecode(hrp, data, verbose=True) node_key = coincurve.PrivateKey(secret=node.node_privkey) logger.debug("SignInvoice node pubkey:%s" % node_key.public_key.format().hex()) signature = node_key.sign_recoverable( message=lnaddr.data_cov(hrp, data)) reply = remotesigner_pb2.RecoverableNodeSignatureReply() reply.signature.data = signature return reply
def test_forwarded_payment(bitcoind, node_factory, impls): num_nodes = len(impls) nodes = [node_factory.get_node(implementation=impls[i]) for i in range(3)] capacity = 10**7 for i in range(num_nodes - 1): nodes[i].connect('localhost', nodes[i + 1].daemon.port, nodes[i + 1].id()) nodes[i].addfunds(bitcoind, 4 * capacity) time.sleep(5) bitcoind.rpc.generate(6) time.sleep(5) for i in range(num_nodes - 1): nodes[i].openchannel(nodes[i + 1].id(), 'localhost', nodes[i + 1].daemon.port, capacity) time.sleep(5) bitcoind.rpc.generate(6) time.sleep(5) sync_blockheight(bitcoind, nodes) # Make sure that everybody knows about its own channel and it's confirmed generate_until(bitcoind, lambda: check_channels([(nodes[0], nodes[1]), (nodes[1], nodes[2])]), interval=1) # Each node should know 2 channels, 4 directions: generate_until(bitcoind, lambda: gossip_is_synced(nodes, 4), blocks=60, interval=3) sync_blockheight(bitcoind, nodes) #import pdb; pdb.set_trace() src = nodes[0] dst = nodes[len(nodes) - 1] amount = int(capacity / 10) req = dst.invoice(amount) payment_key = src.send(req) dec = lndecode(req) assert (sha256(unhexlify(payment_key)).digest() == dec.paymenthash)
def decode(options): a = lndecode(options.lnaddress, options.verbose) def tags_by_name(name, tags): return [t[1] for t in tags if t[0] == name] print("Signed with public key:", hexlify(a.pubkey.serialize())) print("Currency:", a.currency) print("Payment hash:", hexlify(a.paymenthash)) if a.amount: print("Amount:", a.amount) print("Timestamp: {} ({})".format(a.date, time.ctime(a.date))) for r in tags_by_name('r', a.tags): print("Route: ", end='') for step in r: print("{}/{}/{}/{}/{} ".format(hexlify(step[0]), hexlify(step[1]), step[2], step[3], step[4]), end='') print('') fallback = tags_by_name('f', a.tags) if fallback: print("Fallback:", fallback[0]) description = tags_by_name('d', a.tags) if description: print("Description:", description[0]) dhash = tags_by_name('h', a.tags) if dhash: print("Description hash:", hexlify(dhash[0])) expiry = tags_by_name('x', a.tags) if expiry: print("Expiry (seconds):", expiry[0]) for t in [t for t in a.tags if t[0] not in 'rdfhx']: print("UNKNOWN TAG {}: {}".format(t[0], hexlify(t[1])))