@@ -2047,3 +2047,329 @@ fn fails_paying_after_rejected_by_payee() {
20472047 expect_pending_htlcs_forwardable_and_htlc_handling_failed ! ( nodes[ 1 ] , [ HTLCDestination :: FailedPayment { payment_hash } ] ) ;
20482048 pass_failed_payment_back ( & nodes[ 0 ] , & [ & [ & nodes[ 1 ] ] ] , false , payment_hash) ;
20492049}
2050+
2051+ #[ test]
2052+ fn retry_multi_path_single_failed_payment ( ) {
2053+ // Tests that we can/will retry after a single path of an MPP payment failed immediately
2054+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
2055+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
2056+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None , None ] ) ;
2057+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2058+
2059+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
2060+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
2061+ let chans = nodes[ 0 ] . node . list_usable_channels ( ) ;
2062+ let mut route = Route {
2063+ paths : vec ! [
2064+ vec![ RouteHop {
2065+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2066+ node_features: channelmanager:: provided_node_features( ) ,
2067+ short_channel_id: chans[ 0 ] . short_channel_id. unwrap( ) ,
2068+ channel_features: channelmanager:: provided_channel_features( ) ,
2069+ fee_msat: 10_000 ,
2070+ cltv_expiry_delta: 100 ,
2071+ } ] ,
2072+ vec![ RouteHop {
2073+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2074+ node_features: channelmanager:: provided_node_features( ) ,
2075+ short_channel_id: chans[ 1 ] . short_channel_id. unwrap( ) ,
2076+ channel_features: channelmanager:: provided_channel_features( ) ,
2077+ fee_msat: 100_000_001 , // Our default max-HTLC-value is 10% of the channel value, which this is one more than
2078+ cltv_expiry_delta: 100 ,
2079+ } ] ,
2080+ ] ,
2081+ payment_params : Some ( PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) ) ) ,
2082+ } ;
2083+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2084+ // On retry, split the payment across both channels.
2085+ route. paths [ 0 ] [ 0 ] . fee_msat = 50_000_001 ;
2086+ route. paths [ 1 ] [ 0 ] . fee_msat = 50_000_000 ;
2087+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2088+
2089+ let amt_msat = 100_010_000 ;
2090+ let ( _, payment_hash, _, payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , nodes[ 1 ] , amt_msat) ;
2091+ #[ cfg( feature = "std" ) ]
2092+ let payment_expiry_secs = SystemTime :: UNIX_EPOCH . elapsed ( ) . unwrap ( ) . as_secs ( ) + 60 * 60 ;
2093+ #[ cfg( not( feature = "std" ) ) ]
2094+ let payment_expiry_secs = 60 * 60 ;
2095+ let mut invoice_features = InvoiceFeatures :: empty ( ) ;
2096+ invoice_features. set_variable_length_onion_required ( ) ;
2097+ invoice_features. set_payment_secret_required ( ) ;
2098+ invoice_features. set_basic_mpp_optional ( ) ;
2099+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) )
2100+ . with_expiry_time ( payment_expiry_secs as u64 )
2101+ . with_features ( invoice_features) ;
2102+ let route_params = RouteParameters {
2103+ payment_params,
2104+ final_value_msat : amt_msat,
2105+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
2106+ } ;
2107+
2108+ nodes[ 0 ] . node . send_payment_with_retry ( payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
2109+ let htlc_msgs = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2110+ assert_eq ! ( htlc_msgs. len( ) , 2 ) ;
2111+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
2112+ }
2113+
2114+ #[ test]
2115+ fn immediate_retry_on_failure ( ) {
2116+ // Tests that we can/will retry immediately after a failure
2117+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
2118+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
2119+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None , None ] ) ;
2120+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
2121+
2122+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
2123+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) ;
2124+ let chans = nodes[ 0 ] . node . list_usable_channels ( ) ;
2125+ let mut route = Route {
2126+ paths : vec ! [
2127+ vec![ RouteHop {
2128+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2129+ node_features: channelmanager:: provided_node_features( ) ,
2130+ short_channel_id: chans[ 0 ] . short_channel_id. unwrap( ) ,
2131+ channel_features: channelmanager:: provided_channel_features( ) ,
2132+ fee_msat: 100_000_001 , // Our default max-HTLC-value is 10% of the channel value, which this is one more than
2133+ cltv_expiry_delta: 100 ,
2134+ } ] ,
2135+ ] ,
2136+ payment_params : Some ( PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) ) ) ,
2137+ } ;
2138+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2139+ // On retry, split the payment across both channels.
2140+ route. paths . push ( route. paths [ 0 ] . clone ( ) ) ;
2141+ route. paths [ 0 ] [ 0 ] . short_channel_id = chans[ 1 ] . short_channel_id . unwrap ( ) ;
2142+ route. paths [ 0 ] [ 0 ] . fee_msat = 50_000_000 ;
2143+ route. paths [ 1 ] [ 0 ] . fee_msat = 50_000_001 ;
2144+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2145+
2146+ let amt_msat = 100_010_000 ;
2147+ let ( _, payment_hash, _, payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , nodes[ 1 ] , amt_msat) ;
2148+ #[ cfg( feature = "std" ) ]
2149+ let payment_expiry_secs = SystemTime :: UNIX_EPOCH . elapsed ( ) . unwrap ( ) . as_secs ( ) + 60 * 60 ;
2150+ #[ cfg( not( feature = "std" ) ) ]
2151+ let payment_expiry_secs = 60 * 60 ;
2152+ let mut invoice_features = InvoiceFeatures :: empty ( ) ;
2153+ invoice_features. set_variable_length_onion_required ( ) ;
2154+ invoice_features. set_payment_secret_required ( ) ;
2155+ invoice_features. set_basic_mpp_optional ( ) ;
2156+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) )
2157+ . with_expiry_time ( payment_expiry_secs as u64 )
2158+ . with_features ( invoice_features) ;
2159+ let route_params = RouteParameters {
2160+ payment_params,
2161+ final_value_msat : amt_msat,
2162+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
2163+ } ;
2164+
2165+ nodes[ 0 ] . node . send_payment_with_retry ( payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
2166+ let htlc_msgs = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
2167+ assert_eq ! ( htlc_msgs. len( ) , 2 ) ;
2168+ check_added_monitors ! ( nodes[ 0 ] , 2 ) ;
2169+ }
2170+
2171+ #[ test]
2172+ fn no_extra_retries_on_back_to_back_fail ( ) {
2173+ // In a previous release, we had a race where we may exceed the payment retry count if we
2174+ // get two failures in a row with the second having `all_paths_failed` set.
2175+ // Generally, when we give up trying to retry a payment, we don't know for sure what the
2176+ // current state of the ChannelManager event queue is. Specifically, we cannot be sure that
2177+ // there are not multiple additional `PaymentPathFailed` or even `PaymentSent` events
2178+ // pending which we will see later. Thus, when we previously removed the retry tracking map
2179+ // entry after a `all_paths_failed` `PaymentPathFailed` event, we may have dropped the
2180+ // retry entry even though more events for the same payment were still pending. This led to
2181+ // us retrying a payment again even though we'd already given up on it.
2182+ //
2183+ // We now have a separate event - `PaymentFailed` which indicates no HTLCs remain and which
2184+ // is used to remove the payment retry counter entries instead. This tests for the specific
2185+ // excess-retry case while also testing `PaymentFailed` generation.
2186+
2187+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
2188+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
2189+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
2190+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
2191+
2192+ let chan_1_scid = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 0 . contents . short_channel_id ;
2193+ let chan_2_scid = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 0 , channelmanager:: provided_init_features ( ) , channelmanager:: provided_init_features ( ) ) . 0 . contents . short_channel_id ;
2194+
2195+ let mut route = Route {
2196+ paths : vec ! [
2197+ vec![ RouteHop {
2198+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2199+ node_features: channelmanager:: provided_node_features( ) ,
2200+ short_channel_id: chan_1_scid,
2201+ channel_features: channelmanager:: provided_channel_features( ) ,
2202+ fee_msat: 0 ,
2203+ cltv_expiry_delta: 100 ,
2204+ } , RouteHop {
2205+ pubkey: nodes[ 2 ] . node. get_our_node_id( ) ,
2206+ node_features: channelmanager:: provided_node_features( ) ,
2207+ short_channel_id: chan_2_scid,
2208+ channel_features: channelmanager:: provided_channel_features( ) ,
2209+ fee_msat: 100_000_000 ,
2210+ cltv_expiry_delta: 100 ,
2211+ } ] ,
2212+ vec![ RouteHop {
2213+ pubkey: nodes[ 1 ] . node. get_our_node_id( ) ,
2214+ node_features: channelmanager:: provided_node_features( ) ,
2215+ short_channel_id: chan_1_scid,
2216+ channel_features: channelmanager:: provided_channel_features( ) ,
2217+ fee_msat: 0 ,
2218+ cltv_expiry_delta: 100 ,
2219+ } , RouteHop {
2220+ pubkey: nodes[ 2 ] . node. get_our_node_id( ) ,
2221+ node_features: channelmanager:: provided_node_features( ) ,
2222+ short_channel_id: chan_2_scid,
2223+ channel_features: channelmanager:: provided_channel_features( ) ,
2224+ fee_msat: 100_000_000 ,
2225+ cltv_expiry_delta: 100 ,
2226+ } ]
2227+ ] ,
2228+ payment_params : Some ( PaymentParameters :: from_node_id ( nodes[ 2 ] . node . get_our_node_id ( ) ) ) ,
2229+ } ;
2230+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2231+ // On retry, we'll only be asked for one path
2232+ route. paths . remove ( 1 ) ;
2233+ nodes[ 0 ] . router . expect_find_route ( Ok ( route. clone ( ) ) ) ;
2234+
2235+ let amt_msat = 100_010_000 ;
2236+ let ( _, payment_hash, _, payment_secret) = get_route_and_payment_hash ! ( & nodes[ 0 ] , nodes[ 1 ] , amt_msat) ;
2237+ #[ cfg( feature = "std" ) ]
2238+ let payment_expiry_secs = SystemTime :: UNIX_EPOCH . elapsed ( ) . unwrap ( ) . as_secs ( ) + 60 * 60 ;
2239+ #[ cfg( not( feature = "std" ) ) ]
2240+ let payment_expiry_secs = 60 * 60 ;
2241+ let mut invoice_features = InvoiceFeatures :: empty ( ) ;
2242+ invoice_features. set_variable_length_onion_required ( ) ;
2243+ invoice_features. set_payment_secret_required ( ) ;
2244+ invoice_features. set_basic_mpp_optional ( ) ;
2245+ let payment_params = PaymentParameters :: from_node_id ( nodes[ 1 ] . node . get_our_node_id ( ) )
2246+ . with_expiry_time ( payment_expiry_secs as u64 )
2247+ . with_features ( invoice_features) ;
2248+ let route_params = RouteParameters {
2249+ payment_params,
2250+ final_value_msat : amt_msat,
2251+ final_cltv_expiry_delta : TEST_FINAL_CLTV ,
2252+ } ;
2253+
2254+ nodes[ 0 ] . node . send_payment_with_retry ( payment_hash, & Some ( payment_secret) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 1 ) ) . unwrap ( ) ;
2255+ let htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2256+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2257+ assert_eq ! ( htlc_updates. msgs. len( ) , 1 ) ;
2258+
2259+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & htlc_updates. msgs [ 0 ] ) ;
2260+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & htlc_updates. commitment_msg ) ;
2261+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2262+ let ( bs_first_raa, bs_first_cs) = get_revoke_commit_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2263+
2264+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_first_raa) ;
2265+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2266+ let second_htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2267+
2268+ nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_first_cs) ;
2269+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2270+ let as_first_raa = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2271+
2272+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & second_htlc_updates. msgs [ 0 ] ) ;
2273+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & second_htlc_updates. commitment_msg ) ;
2274+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2275+ let bs_second_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2276+
2277+ nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_first_raa) ;
2278+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2279+ let bs_fail_update = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2280+
2281+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_second_raa) ;
2282+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2283+
2284+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fail_update. update_fail_htlcs [ 0 ] ) ;
2285+ nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fail_update. commitment_signed ) ;
2286+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2287+ let ( as_second_raa, as_third_cs) = get_revoke_commit_msgs ! ( nodes[ 0 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2288+
2289+ nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_second_raa) ;
2290+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2291+ let bs_second_fail_update = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2292+
2293+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_third_cs) ;
2294+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2295+ let bs_third_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2296+
2297+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_second_fail_update. update_fail_htlcs [ 0 ] ) ;
2298+ nodes[ 0 ] . node . handle_commitment_signed ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_second_fail_update. commitment_signed ) ;
2299+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2300+
2301+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_third_raa) ;
2302+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2303+ let ( as_third_raa, as_fourth_cs) = get_revoke_commit_msgs ! ( nodes[ 0 ] , nodes[ 1 ] . node. get_our_node_id( ) ) ;
2304+
2305+ nodes[ 1 ] . node . handle_revoke_and_ack ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_third_raa) ;
2306+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2307+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_fourth_cs) ;
2308+ check_added_monitors ! ( nodes[ 1 ] , 1 ) ;
2309+ let bs_fourth_raa = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendRevokeAndACK , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2310+
2311+ nodes[ 0 ] . node . handle_revoke_and_ack ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fourth_raa) ;
2312+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2313+
2314+ // At this point A has sent two HTLCs which both failed due to lack of fee. It now has two
2315+ // pending `PaymentPathFailed` events, one with `all_paths_failed` unset, and the second
2316+ // with it set. The first event will use up the only retry we are allowed, with the second
2317+ // `PaymentPathFailed` being passed up to the user (us, in this case). Previously, we'd
2318+ // treated this as "HTLC complete" and dropped the retry counter, causing us to retry again
2319+ // if the final HTLC failed.
2320+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
2321+ println ! ( "VMW: events: {:?}" , events) ;
2322+ assert_eq ! ( events. len( ) , 4 ) ;
2323+ match events[ 0 ] {
2324+ Event :: PaymentPathFailed { payment_hash : ev_payment_hash, payment_failed_permanently, .. } => {
2325+ assert_eq ! ( payment_hash, ev_payment_hash) ;
2326+ assert_eq ! ( payment_failed_permanently, false ) ;
2327+ } ,
2328+ _ => panic ! ( "Unexpected event" ) ,
2329+ }
2330+ match events[ 1 ] {
2331+ Event :: PendingHTLCsForwardable { .. } => { } ,
2332+ _ => panic ! ( "Unexpected event" ) ,
2333+ }
2334+ match events[ 2 ] {
2335+ Event :: PaymentPathFailed { payment_hash : ev_payment_hash, payment_failed_permanently, .. } => {
2336+ assert_eq ! ( payment_hash, ev_payment_hash) ;
2337+ assert_eq ! ( payment_failed_permanently, false ) ;
2338+ } ,
2339+ _ => panic ! ( "Unexpected event" ) ,
2340+ }
2341+ match events[ 3 ] {
2342+ Event :: PendingHTLCsForwardable { .. } => { } ,
2343+ _ => panic ! ( "Unexpected event" ) ,
2344+ }
2345+
2346+ nodes[ 0 ] . node . process_pending_htlc_forwards ( ) ;
2347+ let retry_htlc_updates = SendEvent :: from_node ( & nodes[ 0 ] ) ;
2348+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
2349+
2350+ nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & retry_htlc_updates. msgs [ 0 ] ) ;
2351+ commitment_signed_dance ! ( nodes[ 1 ] , nodes[ 0 ] , & retry_htlc_updates. commitment_msg, false , true ) ;
2352+ let bs_fail_update = get_htlc_update_msgs ! ( nodes[ 1 ] , nodes[ 0 ] . node. get_our_node_id( ) ) ;
2353+ nodes[ 0 ] . node . handle_update_fail_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_fail_update. update_fail_htlcs [ 0 ] ) ;
2354+ commitment_signed_dance ! ( nodes[ 0 ] , nodes[ 1 ] , & bs_fail_update. commitment_signed, false , true ) ;
2355+
2356+ let mut events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
2357+ assert_eq ! ( events. len( ) , 1 ) ;
2358+ match events[ 0 ] {
2359+ Event :: PaymentPathFailed { payment_hash : ev_payment_hash, payment_failed_permanently, .. } => {
2360+ assert_eq ! ( payment_hash, ev_payment_hash) ;
2361+ assert_eq ! ( payment_failed_permanently, false ) ;
2362+ } ,
2363+ _ => panic ! ( "Unexpected event" ) ,
2364+ }
2365+ nodes[ 0 ] . node . abandon_payment ( PaymentId ( payment_hash. 0 ) ) ;
2366+ events = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
2367+ assert_eq ! ( events. len( ) , 1 ) ;
2368+ match events[ 0 ] {
2369+ Event :: PaymentFailed { payment_hash : ref ev_payment_hash, payment_id : ref ev_payment_id } => {
2370+ assert_eq ! ( payment_hash, * ev_payment_hash) ;
2371+ assert_eq ! ( PaymentId ( payment_hash. 0 ) , * ev_payment_id) ;
2372+ } ,
2373+ _ => panic ! ( "Unexpected event" ) ,
2374+ }
2375+ }
0 commit comments