mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 10:46:58 +01:00
pytest: Test that we record forwardings correctly
Adapts the `test_forward_stats` test to include checks for the `forwarded_payments` table. Will add checks for the `listforwardings` RPC call next. Signed-off-by: Christian Decker <@cdecker>
This commit is contained in:
parent
4b4c549c9d
commit
6efdd5275c
2 changed files with 67 additions and 20 deletions
|
@ -976,30 +976,73 @@ def test_forward_pad_fees_and_cltv(node_factory, bitcoind):
|
|||
assert only_one(l3.rpc.listinvoices('test_forward_pad_fees_and_cltv')['invoices'])['status'] == 'paid'
|
||||
|
||||
|
||||
def test_forward_stats(node_factory):
|
||||
l1, l2, l3 = node_factory.line_graph(3, announce=True)
|
||||
def test_forward_stats(node_factory, bitcoind):
|
||||
"""Check that we track forwarded payments correctly.
|
||||
|
||||
inv = l3.rpc.invoice(100000, "first", "desc")['bolt11']
|
||||
l1.rpc.pay(inv)
|
||||
We wire up the network to have l1 as payment initiator, l2 as
|
||||
forwarded (the one we check) and l3-l5 as payment recipients. l3
|
||||
accepts correctly, l4 refects (because it doesn't know the payment
|
||||
hash) and l5 will keep the HTLC dangling by disconnecting.
|
||||
|
||||
"""
|
||||
amount = 10**4
|
||||
l1, l2, l3 = node_factory.line_graph(3, announce=False)
|
||||
l4 = node_factory.get_node()
|
||||
l5 = node_factory.get_node(may_fail=True)
|
||||
l2.openchannel(l4, 10**6, announce=False)
|
||||
l2.openchannel(l5, 10**6, announce=True)
|
||||
|
||||
bitcoind.generate_block(5)
|
||||
|
||||
wait_for(lambda: len(l1.rpc.listchannels()['channels']) == 8)
|
||||
|
||||
payment_hash = l3.rpc.invoice(amount, "first", "desc")['payment_hash']
|
||||
route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
|
||||
|
||||
l1.rpc.sendpay(route, payment_hash)
|
||||
l1.rpc.waitsendpay(payment_hash)
|
||||
|
||||
# l4 rejects since it doesn't know the payment_hash
|
||||
route = l1.rpc.getroute(l4.info['id'], amount, 1)['route']
|
||||
payment_hash = "F" * 64
|
||||
with pytest.raises(RpcError):
|
||||
l1.rpc.sendpay(route, payment_hash)
|
||||
l1.rpc.waitsendpay(payment_hash)
|
||||
|
||||
# l5 will hold the HTLC hostage and walk away
|
||||
route = l1.rpc.getroute(l5.info['id'], amount, 1)['route']
|
||||
payment_hash = l5.rpc.invoice(amount, "first", "desc")['payment_hash']
|
||||
l1.rpc.sendpay(route, payment_hash)
|
||||
|
||||
# Wait for the HTLC to be added, then try to kill it to keep the
|
||||
# HTLC pending. This is racy but there seems to be no good
|
||||
# alternative
|
||||
l5.daemon.wait_for_log(r'RCVD_ADD_HTLC/SENT_ADD_HTLC')
|
||||
l5.daemon.wait_for_log(r'peer_out WIRE_COMMITMENT_SIGNED')
|
||||
l5.daemon.kill()
|
||||
print("Killed!")
|
||||
|
||||
# Select all forwardings, ordered by htlc_id to ensure the order
|
||||
# matches below
|
||||
forwardings = l2.db_query("SELECT *, in_msatoshi - out_msatoshi as fee "
|
||||
"FROM forwarded_payments "
|
||||
"ORDER BY in_htlc_id;")
|
||||
assert(len(forwardings) == 3)
|
||||
states = [f['state'] for f in forwardings]
|
||||
assert(states == [1, 2, 0]) # settled, failed, offered
|
||||
|
||||
inchan = l2.rpc.listpeers(l1.info['id'])['peers'][0]['channels'][0]
|
||||
outchan = l2.rpc.listpeers(l3.info['id'])['peers'][0]['channels'][0]
|
||||
|
||||
def extract_stats(c):
|
||||
return {k: v for k, v in c.items() if 'in_' in k or 'out_' in k}
|
||||
|
||||
instats = extract_stats(inchan)
|
||||
outstats = extract_stats(outchan)
|
||||
|
||||
# Check that we correctly account channel changes
|
||||
assert instats['in_payments_offered'] == 1
|
||||
assert instats['in_payments_fulfilled'] == 1
|
||||
assert instats['in_msatoshi_offered'] >= 100000
|
||||
assert instats['in_msatoshi_offered'] == instats['in_msatoshi_fulfilled']
|
||||
assert inchan['in_payments_offered'] == 3
|
||||
assert inchan['in_payments_fulfilled'] == 1
|
||||
assert inchan['in_msatoshi_offered'] >= 3 * amount
|
||||
assert inchan['in_msatoshi_fulfilled'] >= amount
|
||||
|
||||
assert outstats['out_payments_offered'] == 1
|
||||
assert outstats['out_payments_fulfilled'] == 1
|
||||
assert outstats['out_msatoshi_offered'] >= 100000
|
||||
assert outstats['out_msatoshi_offered'] == outstats['out_msatoshi_fulfilled']
|
||||
assert outchan['out_payments_offered'] == 1
|
||||
assert outchan['out_payments_fulfilled'] == 1
|
||||
assert outchan['out_msatoshi_offered'] >= amount
|
||||
assert outchan['out_msatoshi_offered'] == outchan['out_msatoshi_fulfilled']
|
||||
|
||||
assert outstats['out_msatoshi_fulfilled'] < instats['in_msatoshi_fulfilled']
|
||||
assert outchan['out_msatoshi_fulfilled'] < inchan['in_msatoshi_fulfilled']
|
||||
|
|
|
@ -380,8 +380,12 @@ class LightningNode(object):
|
|||
self.may_fail = may_fail
|
||||
self.may_reconnect = may_reconnect
|
||||
|
||||
def openchannel(self, remote_node, capacity, addrtype="p2sh-segwit", confirm=True, announce=True):
|
||||
def openchannel(self, remote_node, capacity, addrtype="p2sh-segwit", confirm=True, announce=True, connect=True):
|
||||
addr, wallettxid = self.fundwallet(10 * capacity, addrtype)
|
||||
|
||||
if connect and remote_node.info['id'] not in [p['id'] for p in self.rpc.listpeers()['peers']]:
|
||||
self.rpc.connect(remote_node.info['id'], '127.0.0.1', remote_node.daemon.port)
|
||||
|
||||
fundingtx = self.rpc.fundchannel(remote_node.info['id'], capacity)
|
||||
|
||||
# Wait for the funding transaction to be in bitcoind's mempool
|
||||
|
|
Loading…
Add table
Reference in a new issue