@@ -18468,17 +18468,24 @@ impl<
1846818468 // edge or (b) removed from the outbound edge via claim. If it's in neither of these states, we
1846918469 // infer that it was removed from the outbound edge via fail, and fail it backwards to ensure
1847018470 // that it is handled.
18471- let mut already_forwarded_htlcs = Vec::new();
18472- let prune_forwarded_htlc =
18473- |already_forwarded_htlcs: &mut Vec<(PaymentHash, HTLCPreviousHopData, u64)>,
18474- prev_hop: &HTLCPreviousHopData| {
18475- if let Some(idx) = already_forwarded_htlcs.iter().position(|(_, htlc, _)| {
18476- prev_hop.htlc_id == htlc.htlc_id
18477- && prev_hop.prev_outbound_scid_alias == htlc.prev_outbound_scid_alias
18478- }) {
18479- already_forwarded_htlcs.swap_remove(idx);
18471+ let mut already_forwarded_htlcs: HashMap<
18472+ ChannelId,
18473+ Vec<(PaymentHash, HTLCPreviousHopData, u64)>,
18474+ > = new_hash_map();
18475+ let prune_forwarded_htlc = |already_forwarded_htlcs: &mut HashMap<
18476+ ChannelId,
18477+ Vec<(PaymentHash, HTLCPreviousHopData, u64)>,
18478+ >,
18479+ prev_hop: &HTLCPreviousHopData| {
18480+ if let hash_map::Entry::Occupied(mut entry) =
18481+ already_forwarded_htlcs.entry(prev_hop.channel_id)
18482+ {
18483+ entry.get_mut().retain(|(_, htlc, _)| prev_hop.htlc_id != htlc.htlc_id);
18484+ if entry.get().is_empty() {
18485+ entry.remove();
1848018486 }
18481- };
18487+ }
18488+ };
1848218489 {
1848318490 // If we're tracking pending payments, ensure we haven't lost any by looking at the
1848418491 // ChannelMonitor data for any channels for which we do not have authorative state
@@ -18523,11 +18530,23 @@ impl<
1852318530 hop_data,
1852418531 outbound_amt_msat,
1852518532 } => {
18526- already_forwarded_htlcs.push((
18527- payment_hash,
18528- hop_data,
18529- outbound_amt_msat,
18530- ));
18533+ match already_forwarded_htlcs.entry(hop_data.channel_id)
18534+ {
18535+ hash_map::Entry::Occupied(mut entry) => {
18536+ entry.get_mut().push((
18537+ payment_hash,
18538+ hop_data,
18539+ outbound_amt_msat,
18540+ ));
18541+ },
18542+ hash_map::Entry::Vacant(entry) => {
18543+ entry.insert(vec![(
18544+ payment_hash,
18545+ hop_data,
18546+ outbound_amt_msat,
18547+ )]);
18548+ },
18549+ }
1853118550 },
1853218551 InboundUpdateAdd::Legacy => {
1853318552 return Err(DecodeError::InvalidValue)
@@ -19296,44 +19315,50 @@ impl<
1929619315
1929719316 let mut processed_claims: HashSet<Vec<MPPClaimHTLCSource>> = new_hash_set();
1929819317 for (channel_id, monitor) in args.channel_monitors.iter() {
19318+ let counterparty_node_id = monitor.get_counterparty_node_id();
1929919319 for (payment_hash, (payment_preimage, payment_claims)) in monitor.get_stored_preimages()
1930019320 {
1930119321 // If we have unresolved inbound committed HTLCs that were already forwarded to the
1930219322 // outbound edge and removed via claim, we need to make sure to claim them backwards via
1930319323 // adding them to `pending_claims_to_replay`.
19304- for (hash, hop_data, outbound_amt_msat) in
19305- mem::take(&mut already_forwarded_htlcs).drain(.. )
19324+ if let hash_map::Entry::Occupied(mut entry) =
19325+ already_forwarded_htlcs.entry(*channel_id )
1930619326 {
19307- if hash != payment_hash {
19308- already_forwarded_htlcs.push((hash, hop_data, outbound_amt_msat));
19309- continue;
19310- }
19311- let new_pending_claim = !pending_claims_to_replay.iter().any(|(src, _, _, _, _, _, _)| {
19312- matches!(src, HTLCSource::PreviousHopData(hop) if hop.htlc_id == hop_data.htlc_id && hop.prev_outbound_scid_alias == hop_data.prev_outbound_scid_alias)
19313- });
19314- if new_pending_claim {
19315- let counterparty_node_id = monitor.get_counterparty_node_id();
19316- let is_channel_closed = channel_manager
19317- .per_peer_state
19318- .read()
19319- .unwrap()
19320- .get(&counterparty_node_id)
19321- .map_or(true, |peer_state_mtx| {
19322- !peer_state_mtx
19323- .lock()
19324- .unwrap()
19325- .channel_by_id
19326- .contains_key(channel_id)
19327+ for (hash, hop_data, outbound_amt_msat) in mem::take(entry.get_mut()) {
19328+ if hash != payment_hash {
19329+ entry.get_mut().push((hash, hop_data, outbound_amt_msat));
19330+ continue;
19331+ }
19332+ let new_pending_claim =
19333+ !pending_claims_to_replay.iter().any(|(src, _, _, _, _, _, _)| {
19334+ matches!(src, HTLCSource::PreviousHopData(hop) if hop.htlc_id == hop_data.htlc_id && hop.channel_id == hop_data.channel_id)
1932719335 });
19328- pending_claims_to_replay.push((
19329- HTLCSource::PreviousHopData(hop_data),
19330- payment_preimage,
19331- outbound_amt_msat,
19332- is_channel_closed,
19333- counterparty_node_id,
19334- monitor.get_funding_txo(),
19335- *channel_id,
19336- ));
19336+ if new_pending_claim {
19337+ let is_channel_closed = channel_manager
19338+ .per_peer_state
19339+ .read()
19340+ .unwrap()
19341+ .get(&counterparty_node_id)
19342+ .map_or(true, |peer_state_mtx| {
19343+ !peer_state_mtx
19344+ .lock()
19345+ .unwrap()
19346+ .channel_by_id
19347+ .contains_key(channel_id)
19348+ });
19349+ pending_claims_to_replay.push((
19350+ HTLCSource::PreviousHopData(hop_data),
19351+ payment_preimage,
19352+ outbound_amt_msat,
19353+ is_channel_closed,
19354+ counterparty_node_id,
19355+ monitor.get_funding_txo(),
19356+ *channel_id,
19357+ ));
19358+ }
19359+ }
19360+ if entry.get().is_empty() {
19361+ entry.remove();
1933719362 }
1933819363 }
1933919364 if !payment_claims.is_empty() {
@@ -19577,7 +19602,7 @@ impl<
1957719602 channel_manager
1957819603 .fail_htlc_backwards_internal(&source, &hash, &reason, receiver, ev_action);
1957919604 }
19580- for (hash, htlc, _) in already_forwarded_htlcs {
19605+ for (hash, htlc, _) in already_forwarded_htlcs.into_values().flatten() {
1958119606 let channel_id = htlc.channel_id;
1958219607 let node_id = htlc.counterparty_node_id;
1958319608 let source = HTLCSource::PreviousHopData(htlc);
0 commit comments