@@ -33,8 +33,8 @@ use crate::ln::channel::{
3333 MIN_CHAN_DUST_LIMIT_SATOSHIS, UNFUNDED_CHANNEL_AGE_LIMIT_TICKS,
3434};
3535use crate::ln::channelmanager::{
36- PaymentId, RAACommitmentOrder, RecipientOnionFields, BREAKDOWN_TIMEOUT, DISABLE_GOSSIP_TICKS ,
37- ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA,
36+ PaymentId, RAACommitmentOrder, RecipientOnionFields, Retry, BREAKDOWN_TIMEOUT ,
37+ DISABLE_GOSSIP_TICKS, ENABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA,
3838};
3939use crate::ln::msgs;
4040use crate::ln::msgs::{
@@ -9703,3 +9703,147 @@ pub fn test_multi_post_event_actions() {
97039703 do_test_multi_post_event_actions(true);
97049704 do_test_multi_post_event_actions(false);
97059705}
9706+
9707+ #[xtest(feature = "_externalize_tests")]
9708+ fn test_stale_force_close_with_identical_htlcs() {
9709+ // Test that when two identical HTLCs are relayed and force-closes
9710+ // with a stale state, that we fail both HTLCs back immediately.
9711+ let chanmon_cfgs = create_chanmon_cfgs(4);
9712+ let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
9713+ let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
9714+ let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
9715+
9716+ let chan_a_b = create_announced_chan_between_nodes(&nodes, 0, 1);
9717+ let _chan_b_c = create_announced_chan_between_nodes(&nodes, 1, 2);
9718+ let _chan_d_b = create_announced_chan_between_nodes(&nodes, 3, 1);
9719+
9720+ let (_payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
9721+
9722+ let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 100);
9723+ let scorer = test_utils::TestScorer::new();
9724+ let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
9725+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1_000_000);
9726+
9727+ let route = get_route(
9728+ &nodes[0].node.get_our_node_id(),
9729+ &route_params,
9730+ &nodes[0].network_graph.read_only(),
9731+ None,
9732+ nodes[0].logger,
9733+ &scorer,
9734+ &Default::default(),
9735+ &random_seed_bytes,
9736+ )
9737+ .unwrap();
9738+
9739+ nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
9740+ nodes[0]
9741+ .node
9742+ .send_payment(
9743+ payment_hash,
9744+ RecipientOnionFields::secret_only(payment_secret),
9745+ PaymentId([1; 32]),
9746+ route_params.clone(),
9747+ Retry::Attempts(0),
9748+ )
9749+ .unwrap();
9750+
9751+ let ev1 = remove_first_msg_event_to_node(
9752+ &nodes[1].node.get_our_node_id(),
9753+ &mut nodes[0].node.get_and_clear_pending_msg_events(),
9754+ );
9755+ let mut send_ev1 = SendEvent::from_event(ev1);
9756+
9757+ nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_ev1.msgs[0]);
9758+ nodes[1].node.handle_commitment_signed_batch_test(
9759+ nodes[0].node.get_our_node_id(),
9760+ &send_ev1.commitment_msg,
9761+ );
9762+
9763+ let mut b_events = nodes[1].node.get_and_clear_pending_msg_events();
9764+ for ev in b_events.drain(..) {
9765+ match ev {
9766+ MessageSendEvent::SendRevokeAndACK { node_id, msg } => {
9767+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
9768+ nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &msg);
9769+ },
9770+ MessageSendEvent::UpdateHTLCs { node_id, updates, .. } => {
9771+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
9772+ nodes[0].node.handle_commitment_signed_batch_test(
9773+ nodes[1].node.get_our_node_id(),
9774+ &updates.commitment_signed,
9775+ );
9776+ let mut a_events = nodes[0].node.get_and_clear_pending_msg_events();
9777+ for a_ev in a_events.drain(..) {
9778+ if let MessageSendEvent::SendRevokeAndACK { node_id, msg } = a_ev {
9779+ assert_eq!(node_id, nodes[1].node.get_our_node_id());
9780+ nodes[1].node.handle_revoke_and_ack(nodes[0].node.get_our_node_id(), &msg);
9781+ }
9782+ }
9783+ },
9784+ _ => {},
9785+ }
9786+ }
9787+
9788+ nodes[1].node.process_pending_htlc_forwards();
9789+ let _ = nodes[1].node.get_and_clear_pending_msg_events();
9790+
9791+ let stale_commitment_tx = get_local_commitment_txn!(nodes[0], chan_a_b.2)[0].clone();
9792+
9793+ *nodes[0].network_payment_count.borrow_mut() -= 1;
9794+ nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
9795+ nodes[0]
9796+ .node
9797+ .send_payment(
9798+ payment_hash,
9799+ RecipientOnionFields::secret_only(payment_secret),
9800+ PaymentId([2; 32]),
9801+ route_params.clone(),
9802+ Retry::Attempts(0),
9803+ )
9804+ .unwrap();
9805+
9806+ let ev2 = remove_first_msg_event_to_node(
9807+ &nodes[1].node.get_our_node_id(),
9808+ &mut nodes[0].node.get_and_clear_pending_msg_events(),
9809+ );
9810+ let mut send_ev2 = SendEvent::from_event(ev2);
9811+
9812+ nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &send_ev2.msgs[0]);
9813+ nodes[1].node.handle_commitment_signed_batch_test(
9814+ nodes[0].node.get_our_node_id(),
9815+ &send_ev2.commitment_msg,
9816+ );
9817+
9818+ let mut b2_events = nodes[1].node.get_and_clear_pending_msg_events();
9819+ for ev in b2_events.drain(..) {
9820+ match ev {
9821+ MessageSendEvent::SendRevokeAndACK { node_id, msg } => {
9822+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
9823+ nodes[0].node.handle_revoke_and_ack(nodes[1].node.get_our_node_id(), &msg);
9824+ },
9825+ MessageSendEvent::UpdateHTLCs { node_id, updates, .. } => {
9826+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
9827+ nodes[0].node.handle_commitment_signed_batch_test(
9828+ nodes[1].node.get_our_node_id(),
9829+ &updates.commitment_signed,
9830+ );
9831+ },
9832+ _ => {},
9833+ }
9834+ }
9835+
9836+ nodes[1].node.process_pending_htlc_forwards();
9837+ let _ = nodes[1].node.get_and_clear_pending_msg_events();
9838+
9839+ mine_transaction(&nodes[1], &stale_commitment_tx);
9840+ connect_blocks(&nodes[1], ANTI_REORG_DELAY);
9841+
9842+ let events = nodes[1].node.get_and_clear_pending_events();
9843+ let failed_count =
9844+ events.iter().filter(|e| matches!(e, Event::HTLCHandlingFailed { .. })).count();
9845+ assert_eq!(failed_count, 2);
9846+
9847+ check_added_monitors!(&nodes[1], 1);
9848+ nodes[1].node.get_and_clear_pending_msg_events();
9849+ }
0 commit comments