@@ -1883,7 +1883,22 @@ fn test_reload_node_with_preimage_in_monitor_claims_htlc() {
18831883 //
18841884 // Here we ensure that inbound HTLCs in case (b) above will not be failed backwards on manager
18851885 // reload.
1886+ do_test_reclaim_after_reload ( true ) ;
1887+ }
1888+
1889+ #[ test]
1890+ fn test_reclaim_after_reload_payment_forwarded_ev ( ) {
1891+ // Test that when a forwarding node reloads:
1892+ // - mid-HTLC-forward
1893+ // - with a preimage in the outbound edge monitor
1894+ // - and the outbound edge channel is still open
1895+ // - and we subsequently re-claim the inbound HTLC backwards
1896+ // the `PaymentForwarded` event contains `next_user_channel_id`. Previously,
1897+ // `next_user_channel_id` would always be None even if the outbound edge channel was still open.
1898+ do_test_reclaim_after_reload ( false ) ;
1899+ }
18861900
1901+ fn do_test_reclaim_after_reload ( outbound_htlc_fully_removed : bool ) {
18871902 let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
18881903 let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
18891904 let persister;
@@ -1924,29 +1939,22 @@ fn test_reload_node_with_preimage_in_monitor_claims_htlc() {
19241939 let updates_2_1 = get_htlc_update_msgs ( & nodes[ 2 ] , & node_1_id) ;
19251940 nodes[ 1 ] . node . handle_update_fulfill_htlc ( node_2_id, updates_2_1. update_fulfill_htlcs [ 0 ] . clone ( ) ) ;
19261941 check_added_monitors ( & nodes[ 1 ] , 1 ) ;
1927- do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & updates_2_1. commitment_signed , false , false ) ;
1928- expect_payment_forwarded ! ( nodes[ 1 ] , nodes[ 0 ] , nodes[ 2 ] , Some ( 1000 ) , false , false ) ;
19291942
1930- // Clear the holding cell's claim entry on chan_0_1 before serialization.
1931- // This simulates a crash where the HTLC was fully removed from the outbound edge but is still
1932- // present on the inbound edge without a resolution.
1933- nodes[ 1 ] . node . test_clear_channel_holding_cell ( node_0_id, chan_id_0_1) ;
1943+ if outbound_htlc_fully_removed {
1944+ // Complete the commitment dance so the HTLC is fully resolved on the outbound edge.
1945+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & updates_2_1. commitment_signed , false , false ) ;
1946+ expect_payment_forwarded ! ( nodes[ 1 ] , nodes[ 0 ] , nodes[ 2 ] , Some ( 1000 ) , false , false ) ;
1947+
1948+ // Clear the holding cell's claim entry on chan_0_1 before serialization.
1949+ // This simulates a crash where the HTLC was fully removed from the outbound edge but is still
1950+ // present on the inbound edge without a resolution.
1951+ nodes[ 1 ] . node . test_clear_channel_holding_cell ( node_0_id, chan_id_0_1) ;
1952+ }
19341953
1935- // At this point:
1936- // - The inbound HTLC on nodes[1] (from nodes[0]) is in ::Forwarded state
1937- // - The preimage IS in nodes[1]'s monitor for chan_1_2
1938- // - The outbound HTLC to nodes[2] is resolved
1939- //
1940- // Serialize nodes[1] state and monitors before reloading.
19411954 let node_1_serialized = nodes[ 1 ] . node . encode ( ) ;
19421955 let mon_0_1_serialized = get_monitor ! ( nodes[ 1 ] , chan_id_0_1) . encode ( ) ;
19431956 let mon_1_2_serialized = get_monitor ! ( nodes[ 1 ] , chan_id_1_2) . encode ( ) ;
19441957
1945- // Reload nodes[1].
1946- // During deserialization, we track inbound HTLCs that purport to already be forwarded on the
1947- // outbound edge. If any are entirely missing from the outbound edge with no preimage available,
1948- // they will be failed backwards. Otherwise, as in this case where a preimage is available, the
1949- // payment should be claimed backwards.
19501958 reload_node ! (
19511959 nodes[ 1 ] ,
19521960 node_1_serialized,
@@ -1958,9 +1966,11 @@ fn test_reload_node_with_preimage_in_monitor_claims_htlc() {
19581966 ) ;
19591967
19601968 // When the claim is reconstructed during reload, a PaymentForwarded event is generated.
1961- // Fetching events triggers the pending monitor update (adding preimage) to be applied.
19621969 expect_payment_forwarded ! ( nodes[ 1 ] , nodes[ 0 ] , nodes[ 2 ] , Some ( 1000 ) , false , false ) ;
1963- check_added_monitors ( & nodes[ 1 ] , 1 ) ;
1970+ if outbound_htlc_fully_removed {
1971+ // Fetching events triggers the pending monitor update (adding preimage) to be applied.
1972+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
1973+ }
19641974
19651975 // Reconnect nodes[1] to nodes[0]. The claim should be in nodes[1]'s holding cell.
19661976 let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 0 ] ) ;
0 commit comments