(node_factory, executor)
| 447 | @pytest.mark.openchannel('v1') |
| 448 | @pytest.mark.openchannel('v2') |
| 449 | def test_payment_failed_persistence(node_factory, executor): |
| 450 | # Start two nodes and open a channel.. die during payment. |
| 451 | # Feerates identical so we don't get gratuitous commit to update them |
| 452 | disconnect = ['+WIRE_COMMITMENT_SIGNED'] |
| 453 | if EXPERIMENTAL_DUAL_FUND: |
| 454 | # We have to add an extra 'wire-commitment-signed' because |
| 455 | # dual funding uses this for channel establishment also |
| 456 | disconnect = ['=WIRE_COMMITMENT_SIGNED'] + disconnect |
| 457 | l1 = node_factory.get_node(disconnect=disconnect, |
| 458 | options={'dev-no-reconnect': None}, |
| 459 | may_reconnect=True, |
| 460 | feerates=(7500, 7500, 7500, 7500)) |
| 461 | l2 = node_factory.get_node(may_reconnect=True) |
| 462 | l1.rpc.connect(l2.info['id'], 'localhost', l2.port) |
| 463 | |
| 464 | l1.fundchannel(l2, 100000) |
| 465 | |
| 466 | # Expires almost immediately, so it will fail. |
| 467 | inv1 = l2.rpc.invoice(1000, 'inv1', 'inv1', 5) |
| 468 | |
| 469 | # Fire off a pay request, it'll get interrupted by a restart |
| 470 | executor.submit(l1.rpc.pay, inv1['bolt11']) |
| 471 | |
| 472 | l1.daemon.wait_for_log(r'dev_disconnect: \+WIRE_COMMITMENT_SIGNED') |
| 473 | |
| 474 | print("Killing l1 in mid HTLC") |
| 475 | l1.daemon.kill() |
| 476 | |
| 477 | # Restart l1, without disconnect stuff. |
| 478 | del l1.daemon.opts['dev-no-reconnect'] |
| 479 | del l1.daemon.opts['dev-disconnect'] |
| 480 | |
| 481 | # Make sure invoice has expired. |
| 482 | time.sleep(5 + 1) |
| 483 | |
| 484 | # Should reconnect, and fail the payment |
| 485 | l1.start() |
| 486 | |
| 487 | wait_for(lambda: l1.rpc.listsendpays()['payments'][0]['status'] != 'pending') |
| 488 | |
| 489 | payments = l1.rpc.listsendpays()['payments'] |
| 490 | invoices = l2.rpc.listinvoices('inv1')['invoices'] |
| 491 | assert len(invoices) == 1 and invoices[0]['status'] == 'expired' |
| 492 | assert len(payments) == 1 and payments[0]['status'] == 'failed' |
| 493 | |
| 494 | # Another attempt should also fail. |
| 495 | with pytest.raises(RpcError): |
| 496 | l1.rpc.pay(inv1['bolt11']) |
| 497 | |
| 498 | |
| 499 | @pytest.mark.developer("needs DEVELOPER=1") |
nothing calls this directly
no test coverage detected