(node_factory, executor)
| 386 | @pytest.mark.openchannel('v1') |
| 387 | @pytest.mark.openchannel('v2') |
| 388 | def test_payment_failed_persistence(node_factory, executor): |
| 389 | # Start two nodes and open a channel.. die during payment. |
| 390 | # Feerates identical so we don't get gratuitous commit to update them |
| 391 | disconnect = ['+WIRE_COMMITMENT_SIGNED'] |
| 392 | if EXPERIMENTAL_DUAL_FUND: |
| 393 | # We have to add an extra 'wire-commitment-signed' because |
| 394 | # dual funding uses this for channel establishment also |
| 395 | disconnect = ['=WIRE_COMMITMENT_SIGNED'] + disconnect |
| 396 | l1 = node_factory.get_node(disconnect=disconnect, |
| 397 | options={'dev-no-reconnect': None}, |
| 398 | may_reconnect=True, |
| 399 | feerates=(7500, 7500, 7500, 7500)) |
| 400 | l2 = node_factory.get_node(may_reconnect=True) |
| 401 | l1.rpc.connect(l2.info['id'], 'localhost', l2.port) |
| 402 | |
| 403 | l1.fundchannel(l2, 100000) |
| 404 | |
| 405 | # Expires almost immediately, so it will fail. |
| 406 | inv1 = l2.rpc.invoice(1000, 'inv1', 'inv1', 5) |
| 407 | |
| 408 | # Fire off a pay request, it'll get interrupted by a restart |
| 409 | executor.submit(l1.rpc.pay, inv1['bolt11']) |
| 410 | |
| 411 | l1.daemon.wait_for_log(r'dev_disconnect: \+WIRE_COMMITMENT_SIGNED') |
| 412 | |
| 413 | print("Killing l1 in mid HTLC") |
| 414 | l1.daemon.kill() |
| 415 | |
| 416 | # Restart l1, without disconnect stuff. |
| 417 | del l1.daemon.opts['dev-no-reconnect'] |
| 418 | l1.daemon.disconnect = None |
| 419 | |
| 420 | # Make sure invoice has expired. |
| 421 | time.sleep(5 + 1) |
| 422 | |
| 423 | # Should reconnect, and fail the payment |
| 424 | l1.start() |
| 425 | |
| 426 | wait_for(lambda: l1.rpc.listsendpays()['payments'][0]['status'] != 'pending') |
| 427 | |
| 428 | payments = l1.rpc.listsendpays()['payments'] |
| 429 | invoices = l2.rpc.listinvoices('inv1')['invoices'] |
| 430 | assert len(invoices) == 1 and invoices[0]['status'] == 'expired' |
| 431 | assert len(payments) == 1 and payments[0]['status'] == 'failed' |
| 432 | |
| 433 | # Another attempt should also fail. |
| 434 | with pytest.raises(RpcError, match='Invoice expired'): |
| 435 | l1.rpc.pay(inv1['bolt11']) |
| 436 | |
| 437 | |
| 438 | def test_payment_duplicate_uncommitted(node_factory, executor): |
nothing calls this directly
no test coverage detected