@@ -2259,13 +2259,13 @@ fn fails_paying_invoice_with_unknown_required_features() {
2259
2259
fn no_double_pay_with_stale_channelmanager ( ) {
2260
2260
// This tests the following bug:
2261
2261
// - An outbound payment is AwaitingInvoice
2262
- // - We receive an invoice and lock the HTLCs into the relevant ChannelMonitor
2263
- // - The monitor is successfully persisted, but the ChannelManager fails to persist, so the
2262
+ // - We receive an invoice and lock the HTLCs into the relevant ChannelMonitors
2263
+ // - The monitors are successfully persisted, but the ChannelManager fails to persist, so the
2264
2264
// payment remains AwaitingInvoice
2265
- // - We restart, causing the channel to close due to a stale ChannelManager
2265
+ // - We restart, causing the channels to close due to a stale ChannelManager
2266
2266
// - We receive a duplicate invoice, and attempt to pay it again due to the payment still being
2267
2267
// AwaitingInvoice in the stale ChannelManager
2268
- // After the fix for this, we will notice that the payment is already locked into the monitor on
2268
+ // After the fix for this, we will notice that the payment is already locked into the monitors on
2269
2269
// startup and transition the incorrectly-AwaitingInvoice payment to Retryable, which prevents
2270
2270
// double-paying on duplicate invoice receipt.
2271
2271
let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
@@ -2275,15 +2275,17 @@ fn no_double_pay_with_stale_channelmanager() {
2275
2275
let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
2276
2276
let alice_deserialized;
2277
2277
let mut nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2278
- let chan_id = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) . 2 ;
2278
+ let chan_id_0 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) . 2 ;
2279
+ let chan_id_1 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) . 2 ;
2279
2280
2280
2281
let alice_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
2281
2282
let bob_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
2282
2283
2284
+ let amt_msat = nodes[ 0 ] . node . list_usable_channels ( ) [ 0 ] . next_outbound_htlc_limit_msat + 1 ; // Force MPP
2283
2285
let offer = nodes[ 1 ] . node
2284
2286
. create_offer_builder ( None ) . unwrap ( )
2285
2287
. clear_paths ( )
2286
- . amount_msats ( 10_000_000 )
2288
+ . amount_msats ( amt_msat )
2287
2289
. build ( ) . unwrap ( ) ;
2288
2290
assert_eq ! ( offer. signing_pubkey( ) , Some ( bob_id) ) ;
2289
2291
assert ! ( offer. paths( ) . is_empty( ) ) ;
@@ -2300,9 +2302,23 @@ fn no_double_pay_with_stale_channelmanager() {
2300
2302
2301
2303
let invoice_om = nodes[ 1 ] . onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
2302
2304
nodes[ 0 ] . onion_messenger . handle_onion_message ( bob_id, & invoice_om) ;
2305
+ let payment_hash = extract_invoice ( & nodes[ 0 ] , & invoice_om) . 0 . payment_hash ( ) ;
2306
+
2307
+ let expected_route: & [ & [ & Node ] ] = & [ & [ & nodes[ 1 ] ] , & [ & nodes[ 1 ] ] ] ;
2308
+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2309
+ assert_eq ! ( events. len( ) , 2 ) ;
2310
+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
2311
+
2312
+ let ev = remove_first_msg_event_to_node ( & bob_id, & mut events) ;
2313
+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , expected_route[ 0 ] , amt_msat, payment_hash, ev)
2314
+ . without_clearing_recipient_events ( ) ;
2315
+ do_pass_along_path ( args) ;
2316
+
2317
+ let ev = remove_first_msg_event_to_node ( & bob_id, & mut events) ;
2318
+ let args = PassAlongPathArgs :: new ( & nodes[ 0 ] , expected_route[ 0 ] , amt_msat, payment_hash, ev)
2319
+ . without_clearing_recipient_events ( ) ;
2320
+ do_pass_along_path ( args) ;
2303
2321
2304
- let ( invoice, _) = extract_invoice ( & nodes[ 0 ] , & invoice_om) ;
2305
- route_bolt12_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , & invoice) ;
2306
2322
expect_recent_payment ! ( nodes[ 0 ] , RecentPaymentDetails :: Pending , payment_id) ;
2307
2323
match get_event ! ( nodes[ 1 ] , Event :: PaymentClaimable ) {
2308
2324
Event :: PaymentClaimable { .. } => { } ,
@@ -2311,16 +2327,17 @@ fn no_double_pay_with_stale_channelmanager() {
2311
2327
2312
2328
// Reload with the stale manager and check that receiving the invoice again won't result in a
2313
2329
// duplicate payment attempt.
2314
- let monitor = get_monitor ! ( nodes[ 0 ] , chan_id) . encode ( ) ;
2315
- reload_node ! ( nodes[ 0 ] , & alice_chan_manager_serialized, & [ & monitor] , persister, chain_monitor, alice_deserialized) ;
2316
- // The stale manager results in closing the channel.
2317
- check_closed_event ! ( nodes[ 0 ] , 1 , ClosureReason :: OutdatedChannelManager , [ bob_id] , 10_000_000 ) ;
2318
- check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2330
+ let monitor_0 = get_monitor ! ( nodes[ 0 ] , chan_id_0) . encode ( ) ;
2331
+ let monitor_1 = get_monitor ! ( nodes[ 0 ] , chan_id_1) . encode ( ) ;
2332
+ reload_node ! ( nodes[ 0 ] , & alice_chan_manager_serialized, & [ & monitor_0, & monitor_1] , persister, chain_monitor, alice_deserialized) ;
2333
+ // The stale manager results in closing the channels.
2334
+ check_closed_event ! ( nodes[ 0 ] , 2 , ClosureReason :: OutdatedChannelManager , [ bob_id, bob_id] , 10_000_000 ) ;
2335
+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
2319
2336
2320
2337
// Alice receives a duplicate invoice, but the payment should be transitioned to Retryable by now.
2321
2338
nodes[ 0 ] . onion_messenger . handle_onion_message ( bob_id, & invoice_om) ;
2322
2339
// Previously, Alice would've attempted to pay the invoice a 2nd time. In this test case, this 2nd
2323
- // attempt would have resulted in a PaymentFailed event here, since the only channnel between
2340
+ // attempt would have resulted in a PaymentFailed event here, since the only channnels between
2324
2341
// Alice and Bob is closed. Since no 2nd attempt should be made, check that no events are
2325
2342
// generated in response to the duplicate invoice.
2326
2343
assert ! ( nodes[ 0 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ;
0 commit comments