Skip to content

Commit f57221b

Browse files
committed
Make claimable_payments map value a struct, rather than a tuple
This makes the `claimable_payments` code more upgradable allowing us to add new fields in the coming commit(s).
1 parent ee9afd3 commit f57221b

File tree

1 file changed

+61
-40
lines changed

1 file changed

+61
-40
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ impl_writeable_tlv_based!(ClaimingPayment, {
470470
(4, receiver_node_id, required),
471471
});
472472

473+
struct ClaimablePayment {
474+
purpose: events::PaymentPurpose,
475+
htlcs: Vec<ClaimableHTLC>,
476+
}
477+
473478
/// Information about claimable or being-claimed payments
474479
struct ClaimablePayments {
475480
/// Map from payment hash to the payment data and any HTLCs which are to us and can be
@@ -480,7 +485,7 @@ struct ClaimablePayments {
480485
///
481486
/// When adding to the map, [`Self::pending_claiming_payments`] must also be checked to ensure
482487
/// we don't get a duplicate payment.
483-
claimable_htlcs: HashMap<PaymentHash, (events::PaymentPurpose, Vec<ClaimableHTLC>)>,
488+
claimable_payments: HashMap<PaymentHash, ClaimablePayment>,
484489

485490
/// Map from payment hash to the payment data for HTLCs which we have begun claiming, but which
486491
/// are waiting on a [`ChannelMonitorUpdate`] to complete in order to be surfaced to the user
@@ -1668,7 +1673,7 @@ where
16681673
pending_inbound_payments: Mutex::new(HashMap::new()),
16691674
pending_outbound_payments: OutboundPayments::new(),
16701675
forward_htlcs: Mutex::new(HashMap::new()),
1671-
claimable_payments: Mutex::new(ClaimablePayments { claimable_htlcs: HashMap::new(), pending_claiming_payments: HashMap::new() }),
1676+
claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: HashMap::new(), pending_claiming_payments: HashMap::new() }),
16721677
pending_intercepted_htlcs: Mutex::new(HashMap::new()),
16731678
id_to_peer: Mutex::new(HashMap::new()),
16741679
short_to_chan_info: FairRwLock::new(HashMap::new()),
@@ -3349,8 +3354,13 @@ where
33493354
fail_htlc!(claimable_htlc, payment_hash);
33503355
continue
33513356
}
3352-
let (_, ref mut htlcs) = claimable_payments.claimable_htlcs.entry(payment_hash)
3353-
.or_insert_with(|| (purpose(), Vec::new()));
3357+
let ref mut claimable_payment = claimable_payments.claimable_payments
3358+
.entry(payment_hash)
3359+
// Note that if we insert here we MUST NOT fail_htlc!()
3360+
.or_insert_with(|| ClaimablePayment {
3361+
purpose: purpose(), htlcs: Vec::new()
3362+
});
3363+
let ref mut htlcs = &mut claimable_payment.htlcs;
33543364
if htlcs.len() == 1 {
33553365
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
33563366
log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash", log_bytes!(payment_hash.0));
@@ -3445,13 +3455,16 @@ where
34453455
fail_htlc!(claimable_htlc, payment_hash);
34463456
continue
34473457
}
3448-
match claimable_payments.claimable_htlcs.entry(payment_hash) {
3458+
match claimable_payments.claimable_payments.entry(payment_hash) {
34493459
hash_map::Entry::Vacant(e) => {
34503460
let amount_msat = claimable_htlc.value;
34513461
claimable_htlc.total_value_received = Some(amount_msat);
34523462
let claim_deadline = Some(claimable_htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER);
34533463
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
3454-
e.insert((purpose.clone(), vec![claimable_htlc]));
3464+
e.insert(ClaimablePayment {
3465+
purpose: purpose.clone(),
3466+
htlcs: vec![claimable_htlc],
3467+
});
34553468
let prev_channel_id = prev_funding_outpoint.to_channel_id();
34563469
new_events.push(events::Event::PaymentClaimable {
34573470
receiver_node_id: Some(receiver_node_id),
@@ -3708,24 +3721,27 @@ where
37083721
}
37093722
}
37103723

3711-
self.claimable_payments.lock().unwrap().claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
3712-
if htlcs.is_empty() {
3724+
self.claimable_payments.lock().unwrap().claimable_payments.retain(|payment_hash, payment| {
3725+
if payment.htlcs.is_empty() {
37133726
// This should be unreachable
37143727
debug_assert!(false);
37153728
return false;
37163729
}
3717-
if let OnionPayload::Invoice { .. } = htlcs[0].onion_payload {
3730+
if let OnionPayload::Invoice { .. } = payment.htlcs[0].onion_payload {
37183731
// Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat).
37193732
// In this case we're not going to handle any timeouts of the parts here.
37203733
// This condition determining whether the MPP is complete here must match
37213734
// exactly the condition used in `process_pending_htlc_forwards`.
3722-
if htlcs[0].total_msat <= htlcs.iter().fold(0, |total, htlc| total + htlc.sender_intended_value) {
3735+
if payment.htlcs[0].total_msat <= payment.htlcs.iter()
3736+
.fold(0, |total, htlc| total + htlc.sender_intended_value)
3737+
{
37233738
return true;
3724-
} else if htlcs.into_iter().any(|htlc| {
3739+
} else if payment.htlcs.iter_mut().any(|htlc| {
37253740
htlc.timer_ticks += 1;
37263741
return htlc.timer_ticks >= MPP_TIMEOUT_TICKS
37273742
}) {
3728-
timed_out_mpp_htlcs.extend(htlcs.drain(..).map(|htlc: ClaimableHTLC| (htlc.prev_hop, *payment_hash)));
3743+
timed_out_mpp_htlcs.extend(payment.htlcs.drain(..)
3744+
.map(|htlc: ClaimableHTLC| (htlc.prev_hop, *payment_hash)));
37293745
return false;
37303746
}
37313747
}
@@ -3780,9 +3796,9 @@ where
37803796
pub fn fail_htlc_backwards_with_reason(&self, payment_hash: &PaymentHash, failure_code: FailureCode) {
37813797
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
37823798

3783-
let removed_source = self.claimable_payments.lock().unwrap().claimable_htlcs.remove(payment_hash);
3784-
if let Some((_, mut sources)) = removed_source {
3785-
for htlc in sources.drain(..) {
3799+
let removed_source = self.claimable_payments.lock().unwrap().claimable_payments.remove(payment_hash);
3800+
if let Some(payment) = removed_source {
3801+
for htlc in payment.htlcs {
37863802
let reason = self.get_htlc_fail_reason_from_failure_code(failure_code, &htlc);
37873803
let source = HTLCSource::PreviousHopData(htlc.prev_hop);
37883804
let receiver = HTLCDestination::FailedPayment { payment_hash: *payment_hash };
@@ -3959,9 +3975,9 @@ where
39593975

39603976
let mut sources = {
39613977
let mut claimable_payments = self.claimable_payments.lock().unwrap();
3962-
if let Some((payment_purpose, sources)) = claimable_payments.claimable_htlcs.remove(&payment_hash) {
3978+
if let Some(payment) = claimable_payments.claimable_payments.remove(&payment_hash) {
39633979
let mut receiver_node_id = self.our_network_pubkey;
3964-
for htlc in sources.iter() {
3980+
for htlc in payment.htlcs.iter() {
39653981
if htlc.prev_hop.phantom_shared_secret.is_some() {
39663982
let phantom_pubkey = self.node_signer.get_node_id(Recipient::PhantomNode)
39673983
.expect("Failed to get node_id for phantom node recipient");
@@ -3971,15 +3987,15 @@ where
39713987
}
39723988

39733989
let dup_purpose = claimable_payments.pending_claiming_payments.insert(payment_hash,
3974-
ClaimingPayment { amount_msat: sources.iter().map(|source| source.value).sum(),
3975-
payment_purpose, receiver_node_id,
3990+
ClaimingPayment { amount_msat: payment.htlcs.iter().map(|source| source.value).sum(),
3991+
payment_purpose: payment.purpose, receiver_node_id,
39763992
});
39773993
if dup_purpose.is_some() {
39783994
debug_assert!(false, "Shouldn't get a duplicate pending claim event ever");
39793995
log_error!(self.logger, "Got a duplicate pending claimable event on payment hash {}! Please report this bug",
39803996
log_bytes!(payment_hash.0));
39813997
}
3982-
sources
3998+
payment.htlcs
39833999
} else { return; }
39844000
};
39854001
debug_assert!(!sources.is_empty());
@@ -6091,8 +6107,8 @@ where
60916107
}
60926108

60936109
if let Some(height) = height_opt {
6094-
self.claimable_payments.lock().unwrap().claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
6095-
htlcs.retain(|htlc| {
6110+
self.claimable_payments.lock().unwrap().claimable_payments.retain(|payment_hash, payment| {
6111+
payment.htlcs.retain(|htlc| {
60966112
// If height is approaching the number of blocks we think it takes us to get
60976113
// our commitment transaction confirmed before the HTLC expires, plus the
60986114
// number of blocks we generally consider it to take to do a commitment update,
@@ -6107,7 +6123,7 @@ where
61076123
false
61086124
} else { true }
61096125
});
6110-
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
6126+
!payment.htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
61116127
});
61126128

61136129
let mut intercepted_htlcs = self.pending_intercepted_htlcs.lock().unwrap();
@@ -7028,14 +7044,14 @@ where
70287044
let pending_outbound_payments = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap();
70297045

70307046
let mut htlc_purposes: Vec<&events::PaymentPurpose> = Vec::new();
7031-
(claimable_payments.claimable_htlcs.len() as u64).write(writer)?;
7032-
for (payment_hash, (purpose, previous_hops)) in claimable_payments.claimable_htlcs.iter() {
7047+
(claimable_payments.claimable_payments.len() as u64).write(writer)?;
7048+
for (payment_hash, payment) in claimable_payments.claimable_payments.iter() {
70337049
payment_hash.write(writer)?;
7034-
(previous_hops.len() as u64).write(writer)?;
7035-
for htlc in previous_hops.iter() {
7050+
(payment.htlcs.len() as u64).write(writer)?;
7051+
for htlc in payment.htlcs.iter() {
70367052
htlc.write(writer)?;
70377053
}
7038-
htlc_purposes.push(purpose);
7054+
htlc_purposes.push(&payment.purpose);
70397055
}
70407056

70417057
let mut monitor_update_blocked_actions_per_peer = None;
@@ -7688,22 +7704,25 @@ where
76887704
let inbound_pmt_key_material = args.node_signer.get_inbound_payment_key_material();
76897705
let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
76907706

7691-
let mut claimable_htlcs = HashMap::with_capacity(claimable_htlcs_list.len());
7707+
let mut claimable_payments = HashMap::with_capacity(claimable_htlcs_list.len());
76927708
if let Some(mut purposes) = claimable_htlc_purposes {
76937709
if purposes.len() != claimable_htlcs_list.len() {
76947710
return Err(DecodeError::InvalidValue);
76957711
}
7696-
for (purpose, (payment_hash, previous_hops)) in purposes.drain(..).zip(claimable_htlcs_list.drain(..)) {
7697-
claimable_htlcs.insert(payment_hash, (purpose, previous_hops));
7712+
for (purpose, (payment_hash, htlcs)) in purposes.drain(..).zip(claimable_htlcs_list.drain(..)) {
7713+
let existing_payment = claimable_payments.insert(payment_hash, ClaimablePayment {
7714+
purpose, htlcs,
7715+
});
7716+
if existing_payment.is_some() { return Err(DecodeError::InvalidValue); }
76987717
}
76997718
} else {
77007719
// LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do
77017720
// include a `_legacy_hop_data` in the `OnionPayload`.
7702-
for (payment_hash, previous_hops) in claimable_htlcs_list.drain(..) {
7703-
if previous_hops.is_empty() {
7721+
for (payment_hash, htlcs) in claimable_htlcs_list.drain(..) {
7722+
if htlcs.is_empty() {
77047723
return Err(DecodeError::InvalidValue);
77057724
}
7706-
let purpose = match &previous_hops[0].onion_payload {
7725+
let purpose = match &htlcs[0].onion_payload {
77077726
OnionPayload::Invoice { _legacy_hop_data } => {
77087727
if let Some(hop_data) = _legacy_hop_data {
77097728
events::PaymentPurpose::InvoicePayment {
@@ -7724,7 +7743,9 @@ where
77247743
OnionPayload::Spontaneous(payment_preimage) =>
77257744
events::PaymentPurpose::SpontaneousPayment(*payment_preimage),
77267745
};
7727-
claimable_htlcs.insert(payment_hash, (purpose, previous_hops));
7746+
claimable_payments.insert(payment_hash, ClaimablePayment {
7747+
purpose, htlcs,
7748+
});
77287749
}
77297750
}
77307751

@@ -7776,17 +7797,17 @@ where
77767797

77777798
for (_, monitor) in args.channel_monitors.iter() {
77787799
for (payment_hash, payment_preimage) in monitor.get_stored_preimages() {
7779-
if let Some((payment_purpose, claimable_htlcs)) = claimable_htlcs.remove(&payment_hash) {
7800+
if let Some(payment) = claimable_payments.remove(&payment_hash) {
77807801
log_info!(args.logger, "Re-claiming HTLCs with payment hash {} as we've released the preimage to a ChannelMonitor!", log_bytes!(payment_hash.0));
77817802
let mut claimable_amt_msat = 0;
77827803
let mut receiver_node_id = Some(our_network_pubkey);
7783-
let phantom_shared_secret = claimable_htlcs[0].prev_hop.phantom_shared_secret;
7804+
let phantom_shared_secret = payment.htlcs[0].prev_hop.phantom_shared_secret;
77847805
if phantom_shared_secret.is_some() {
77857806
let phantom_pubkey = args.node_signer.get_node_id(Recipient::PhantomNode)
77867807
.expect("Failed to get node_id for phantom node recipient");
77877808
receiver_node_id = Some(phantom_pubkey)
77887809
}
7789-
for claimable_htlc in claimable_htlcs {
7810+
for claimable_htlc in payment.htlcs {
77907811
claimable_amt_msat += claimable_htlc.value;
77917812

77927813
// Add a holding-cell claim of the payment to the Channel, which should be
@@ -7820,7 +7841,7 @@ where
78207841
pending_events_read.push(events::Event::PaymentClaimed {
78217842
receiver_node_id,
78227843
payment_hash,
7823-
purpose: payment_purpose,
7844+
purpose: payment.purpose,
78247845
amount_msat: claimable_amt_msat,
78257846
});
78267847
}
@@ -7851,7 +7872,7 @@ where
78517872
pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()),
78527873

78537874
forward_htlcs: Mutex::new(forward_htlcs),
7854-
claimable_payments: Mutex::new(ClaimablePayments { claimable_htlcs, pending_claiming_payments: pending_claiming_payments.unwrap() }),
7875+
claimable_payments: Mutex::new(ClaimablePayments { claimable_payments, pending_claiming_payments: pending_claiming_payments.unwrap() }),
78557876
outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
78567877
id_to_peer: Mutex::new(id_to_peer),
78577878
short_to_chan_info: FairRwLock::new(short_to_chan_info),

0 commit comments

Comments
 (0)