@@ -23,7 +23,7 @@ use bitcoin::constants::ChainHash;
2323use bitcoin::key::constants::SECRET_KEY_SIZE;
2424use bitcoin::network::Network;
2525
26- use bitcoin::hashes::Hash;
26+ use bitcoin::hashes::{ Hash, HashEngine, HmacEngine} ;
2727use bitcoin::hashes::hmac::Hmac;
2828use bitcoin::hashes::sha256::Hash as Sha256;
2929use bitcoin::hash_types::{BlockHash, Txid};
@@ -369,6 +369,7 @@ pub(crate) struct HTLCPreviousHopData {
369369 counterparty_node_id: Option<PublicKey>,
370370}
371371
372+ #[derive(PartialEq, Eq)]
372373enum OnionPayload {
373374 /// Indicates this incoming onion payload is for the purpose of paying an invoice.
374375 Invoice {
@@ -381,6 +382,7 @@ enum OnionPayload {
381382}
382383
383384/// HTLCs that are to us and can be failed/claimed by the user
385+ #[derive(PartialEq, Eq)]
384386struct ClaimableHTLC {
385387 prev_hop: HTLCPreviousHopData,
386388 cltv_expiry: u32,
@@ -412,6 +414,23 @@ impl From<&ClaimableHTLC> for events::ClaimedHTLC {
412414 }
413415}
414416
417+ impl PartialOrd for ClaimableHTLC {
418+ fn partial_cmp(&self, other: &ClaimableHTLC) -> Option<cmp::Ordering> {
419+ Some(self.cmp(other))
420+ }
421+ }
422+ impl Ord for ClaimableHTLC {
423+ fn cmp(&self, other: &ClaimableHTLC) -> cmp::Ordering {
424+ let res = (self.prev_hop.channel_id, self.prev_hop.htlc_id).cmp(
425+ &(other.prev_hop.channel_id, other.prev_hop.htlc_id)
426+ );
427+ if res.is_eq() {
428+ debug_assert!(self == other, "ClaimableHTLCs from the same source should be identical");
429+ }
430+ res
431+ }
432+ }
433+
415434/// A trait defining behavior for creating and verifing the HMAC for authenticating a given data.
416435pub trait Verification {
417436 /// Constructs an HMAC to include in [`OffersContext`] for the data along with the given
@@ -492,6 +511,22 @@ impl Verification for PaymentId {
492511 }
493512}
494513
514+ impl PaymentId {
515+ fn for_inbound_from_htlcs<I: Iterator<Item=(ChannelId, u64)>>(key: &[u8; 32], htlcs: I) -> PaymentId {
516+ let mut prev_pair = None;
517+ let mut hasher = HmacEngine::new(key);
518+ for (channel_id, htlc_id) in htlcs {
519+ hasher.input(&channel_id.0);
520+ hasher.input(&htlc_id.to_le_bytes());
521+ if let Some(prev) = prev_pair {
522+ debug_assert!(prev < (channel_id, htlc_id), "HTLCs should be sorted");
523+ }
524+ prev_pair = Some((channel_id, htlc_id));
525+ }
526+ PaymentId(Hmac::<Sha256>::from_engine(hasher).to_byte_array())
527+ }
528+ }
529+
495530impl Writeable for PaymentId {
496531 fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
497532 self.0.write(w)
@@ -765,6 +800,7 @@ struct ClaimingPayment {
765800 htlcs: Vec<events::ClaimedHTLC>,
766801 sender_intended_value: Option<u64>,
767802 onion_fields: Option<RecipientOnionFields>,
803+ payment_id: Option<PaymentId>,
768804}
769805impl_writeable_tlv_based!(ClaimingPayment, {
770806 (0, amount_msat, required),
@@ -773,6 +809,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
773809 (5, htlcs, optional_vec),
774810 (7, sender_intended_value, option),
775811 (9, onion_fields, option),
812+ (11, payment_id, option),
776813});
777814
778815struct ClaimablePayment {
@@ -781,6 +818,15 @@ struct ClaimablePayment {
781818 htlcs: Vec<ClaimableHTLC>,
782819}
783820
821+ impl ClaimablePayment {
822+ fn inbound_payment_id(&self, secret: &[u8; 32]) -> PaymentId {
823+ PaymentId::for_inbound_from_htlcs(
824+ secret,
825+ self.htlcs.iter().map(|htlc| (htlc.prev_hop.channel_id, htlc.prev_hop.htlc_id))
826+ )
827+ }
828+ }
829+
784830/// Represent the channel funding transaction type.
785831enum FundingType {
786832 /// This variant is useful when we want LDK to validate the funding transaction and
@@ -2283,6 +2329,9 @@ where
22832329 /// keeping additional state.
22842330 probing_cookie_secret: [u8; 32],
22852331
2332+ /// When generating [`PaymentId`]s for inbound payments, we HMAC the HTLCs with this secret.
2333+ inbound_payment_id_secret: [u8; 32],
2334+
22862335 /// The highest block timestamp we've seen, which is usually a good guess at the current time.
22872336 /// Assuming most miners are generating blocks with reasonable timestamps, this shouldn't be
22882337 /// very far in the past, and can only ever be up to two hours in the future.
@@ -3176,6 +3225,7 @@ where
31763225 fake_scid_rand_bytes: entropy_source.get_secure_random_bytes(),
31773226
31783227 probing_cookie_secret: entropy_source.get_secure_random_bytes(),
3228+ inbound_payment_id_secret: entropy_source.get_secure_random_bytes(),
31793229
31803230 highest_seen_timestamp: AtomicUsize::new(current_timestamp as usize),
31813231
@@ -5769,10 +5819,9 @@ where
57695819 } else {
57705820 claimable_payment.onion_fields = Some(onion_fields);
57715821 }
5772- let ref mut htlcs = &mut claimable_payment.htlcs;
57735822 let mut total_value = claimable_htlc.sender_intended_value;
57745823 let mut earliest_expiry = claimable_htlc.cltv_expiry;
5775- for htlc in htlcs.iter() {
5824+ for htlc in claimable_payment. htlcs.iter() {
57765825 total_value += htlc.sender_intended_value;
57775826 earliest_expiry = cmp::min(earliest_expiry, htlc.cltv_expiry);
57785827 if htlc.total_msat != claimable_htlc.total_msat {
@@ -5794,13 +5843,18 @@ where
57945843 #[allow(unused_assignments)] {
57955844 committed_to_claimable = true;
57965845 }
5797- htlcs.push(claimable_htlc);
5798- let amount_msat = htlcs.iter().map(|htlc| htlc.value).sum();
5799- htlcs.iter_mut().for_each(|htlc| htlc.total_value_received = Some(amount_msat));
5800- let counterparty_skimmed_fee_msat = htlcs.iter()
5846+ claimable_payment.htlcs.push(claimable_htlc);
5847+ let amount_msat =
5848+ claimable_payment.htlcs.iter().map(|htlc| htlc.value).sum();
5849+ claimable_payment.htlcs.iter_mut()
5850+ .for_each(|htlc| htlc.total_value_received = Some(amount_msat));
5851+ let counterparty_skimmed_fee_msat = claimable_payment.htlcs.iter()
58015852 .map(|htlc| htlc.counterparty_skimmed_fee_msat.unwrap_or(0)).sum();
58025853 debug_assert!(total_value.saturating_sub(amount_msat) <=
58035854 counterparty_skimmed_fee_msat);
5855+ claimable_payment.htlcs.sort();
5856+ let payment_id =
5857+ claimable_payment.inbound_payment_id(&self.inbound_payment_id_secret);
58045858 new_events.push_back((events::Event::PaymentClaimable {
58055859 receiver_node_id: Some(receiver_node_id),
58065860 payment_hash,
@@ -5811,13 +5865,14 @@ where
58115865 via_user_channel_id: Some(prev_user_channel_id),
58125866 claim_deadline: Some(earliest_expiry - HTLC_FAIL_BACK_BUFFER),
58135867 onion_fields: claimable_payment.onion_fields.clone(),
5868+ payment_id: Some(payment_id),
58145869 }, None));
58155870 payment_claimable_generated = true;
58165871 } else {
58175872 // Nothing to do - we haven't reached the total
58185873 // payment value yet, wait until we receive more
58195874 // MPP parts.
5820- htlcs.push(claimable_htlc);
5875+ claimable_payment. htlcs.push(claimable_htlc);
58215876 #[allow(unused_assignments)] {
58225877 committed_to_claimable = true;
58235878 }
@@ -6614,6 +6669,7 @@ where
66146669 }
66156670 }
66166671
6672+ let payment_id = payment.inbound_payment_id(&self.inbound_payment_id_secret);
66176673 let claiming_payment = claimable_payments.pending_claiming_payments
66186674 .entry(payment_hash)
66196675 .and_modify(|_| {
@@ -6631,6 +6687,7 @@ where
66316687 htlcs,
66326688 sender_intended_value,
66336689 onion_fields: payment.onion_fields,
6690+ payment_id: Some(payment_id),
66346691 }
66356692 });
66366693
@@ -7148,6 +7205,7 @@ where
71487205 htlcs,
71497206 sender_intended_value: sender_intended_total_msat,
71507207 onion_fields,
7208+ payment_id,
71517209 }) = payment {
71527210 self.pending_events.lock().unwrap().push_back((events::Event::PaymentClaimed {
71537211 payment_hash,
@@ -7157,6 +7215,7 @@ where
71577215 htlcs,
71587216 sender_intended_total_msat,
71597217 onion_fields,
7218+ payment_id,
71607219 }, None));
71617220 }
71627221 },
@@ -12428,6 +12487,7 @@ where
1242812487 let mut events_override = None;
1242912488 let mut in_flight_monitor_updates: Option<HashMap<(PublicKey, OutPoint), Vec<ChannelMonitorUpdate>>> = None;
1243012489 let mut decode_update_add_htlcs: Option<HashMap<u64, Vec<msgs::UpdateAddHTLC>>> = None;
12490+ let mut inbound_payment_id_secret = None;
1243112491 read_tlv_fields!(reader, {
1243212492 (1, pending_outbound_payments_no_retry, option),
1243312493 (2, pending_intercepted_htlcs, option),
@@ -12442,6 +12502,7 @@ where
1244212502 (11, probing_cookie_secret, option),
1244312503 (13, claimable_htlc_onion_fields, optional_vec),
1244412504 (14, decode_update_add_htlcs, option),
12505+ (15, inbound_payment_id_secret, option),
1244512506 });
1244612507 let mut decode_update_add_htlcs = decode_update_add_htlcs.unwrap_or_else(|| new_hash_map());
1244712508 if fake_scid_rand_bytes.is_none() {
@@ -12452,6 +12513,10 @@ where
1245212513 probing_cookie_secret = Some(args.entropy_source.get_secure_random_bytes());
1245312514 }
1245412515
12516+ if inbound_payment_id_secret.is_none() {
12517+ inbound_payment_id_secret = Some(args.entropy_source.get_secure_random_bytes());
12518+ }
12519+
1245512520 if let Some(events) = events_override {
1245612521 pending_events_read = events;
1245712522 }
@@ -12900,6 +12965,7 @@ where
1290012965 previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &bounded_fee_estimator, &args.logger);
1290112966 }
1290212967 }
12968+ let payment_id = payment.inbound_payment_id(&inbound_payment_id_secret.unwrap());
1290312969 pending_events_read.push_back((events::Event::PaymentClaimed {
1290412970 receiver_node_id,
1290512971 payment_hash,
@@ -12908,6 +12974,7 @@ where
1290812974 htlcs: payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(),
1290912975 sender_intended_total_msat: payment.htlcs.first().map(|htlc| htlc.total_msat),
1291012976 onion_fields: payment.onion_fields,
12977+ payment_id: Some(payment_id),
1291112978 }, None));
1291212979 }
1291312980 }
@@ -12978,6 +13045,7 @@ where
1297813045 fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(),
1297913046
1298013047 probing_cookie_secret: probing_cookie_secret.unwrap(),
13048+ inbound_payment_id_secret: inbound_payment_id_secret.unwrap(),
1298113049
1298213050 our_network_pubkey,
1298313051 secp_ctx,
0 commit comments