pytest: test to demonstrate BROKEN message on onchaind htlc close.

We assumed that if the outgoing htlc has failed, we should have always
failed the incoming one.  This is not true, as this testcase demonstrates:

```
lightningd-2: 2022-05-25T04:38:31.449Z DEBUG   035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-onchaind-chan#2: Sending 1 missing htlc messages
lightningd-2: 2022-05-25T04:38:31.449Z DEBUG   035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-chan#2: onchain_failed_our_htlc
lightningd-2: 2022-05-25T04:38:31.449Z DEBUG   035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-chan#2: HTLC id 0 failonion = 0x55cb8bc045d8, failmsg = (nil), preimage = (nil)
lightningd-2: 2022-05-25T04:38:31.449Z **BROKEN** 035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-chan#2: HTLC id 0 already complete, but ->in not resolved! failonion = 206816a391d3a7666ddd5213914cbb68f5da1fc4a0937e729de5a1990c94d26312caa5f2778e8da0c6bdefc68dd1a3bc28b5b5650fc0bdb3c2247ecca94ed0bbb224c8448c2c71eb1656a8740cadb301bd1ee1c1e774a8fef817352f502e4217b11e93aa6877b88b37afab0e4d4e49ed0385be9ab9a1ab1ac0e3460e41cfafb30ed896cea96e346041919a6c524ce56c3e5f27c7cd78a36b6df221e90a1c6e048c72b4146a5a51885fb70649037fe7ace77a016ae3ec8aee97960d0e5f0582713f671df79d8dee11b82708b6d882ee5adbb328db1938e824110f57ead1b27410bc6f775c7bb4ae40c1768d77a166c9bfda8f634ba0ac4f8a9fe199894dd3754c5ce41c9694544c805ffc177517661f11221dd8dffac60ce1c8c5bf54cda8e5ea44d8ec6b, failmsg = (null), preimage = (null)
lightningd-2: 2022-05-25T04:38:31.449Z **BROKEN** 035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-chan#2: MISSING incoming fail for 0: failing incoming now
lightningd-2: 2022-05-25T04:38:31.449Z **BROKEN** 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: MISSED incoming fail for 0: failing now
lightningd-2: 2022-05-25T04:38:31.449Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: HTLC in 0 RCVD_ADD_ACK_REVOCATION->SENT_REMOVE_HTLC
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-06-26 14:09:01 +09:30
parent 11de721ba9
commit 353361a05c

View File

@ -5265,3 +5265,48 @@ def test_pay_bolt11_metadata(node_factory, bitcoind):
l1.rpc.pay(inv)
l2.daemon.wait_for_log("Unexpected payment_metadata {}".format(b'this is metadata'.hex()))
@pytest.mark.xfail(strict=True)
@pytest.mark.developer("needs to dev-disconnect")
def test_pay_middle_fail(node_factory, bitcoind, executor):
"""Test the case where a HTLC is failed, but not on peer's side, then
we go onchain"""
# Set feerates the same so we don't have update_fee interfering.
# We want to disconnect on revoke-and-ack we send for failing htlc.
l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True,
opts=[{'feerates': (1500,) * 4},
{'feerates': (1500,) * 4},
{'feerates': (1500,) * 4,
'disconnect': ['-WIRE_REVOKE_AND_ACK*2']}])
chanid12 = only_one(l1.rpc.getpeer(l2.info['id'])['channels'])['short_channel_id']
chanid23 = only_one(l2.rpc.getpeer(l3.info['id'])['channels'])['short_channel_id']
# Make a failing payment.
route = [{'amount_msat': 1011,
'id': l2.info['id'],
'delay': 20,
'channel': chanid12},
{'amount_msat': 1000,
'id': l3.info['id'],
'delay': 10,
'channel': chanid23}]
# Start payment, it will fail.
l1.rpc.sendpay(route, payment_hash='00' * 32)
wait_for(lambda: only_one(l3.rpc.listpeers(l2.info['id'])['peers'])['connected'] is False)
# After this (cltv is actually +11, and we give it 1 block grace)
# l2 will go onchain since HTLC is not resolved.
bitcoind.generate_block(12)
sync_blockheight(bitcoind, [l1, l2, l3])
wait_for(lambda: only_one(only_one(l2.rpc.listpeers(l3.info['id'])['peers'])['channels'])['state'] == 'AWAITING_UNILATERAL')
# Three blocks and it will resolve the parent.
bitcoind.generate_block(3, wait_for_mempool=1)
# And that will fail upstream
with pytest.raises(RpcError, match=r'WIRE_PERMANENT_CHANNEL_FAILURE'):
l1.rpc.waitsendpay('00' * 32)