@@ -23,7 +23,7 @@ use bitcoin::constants::ChainHash;
23
23
use bitcoin::key::constants::SECRET_KEY_SIZE;
24
24
use bitcoin::network::Network;
25
25
26
- use bitcoin::hashes::Hash;
26
+ use bitcoin::hashes::{ Hash, HashEngine, HmacEngine} ;
27
27
use bitcoin::hashes::hmac::Hmac;
28
28
use bitcoin::hashes::sha256::Hash as Sha256;
29
29
use bitcoin::hash_types::{BlockHash, Txid};
@@ -368,6 +368,7 @@ pub(crate) struct HTLCPreviousHopData {
368
368
counterparty_node_id: Option<PublicKey>,
369
369
}
370
370
371
+ #[derive(PartialEq, Eq)]
371
372
enum OnionPayload {
372
373
/// Indicates this incoming onion payload is for the purpose of paying an invoice.
373
374
Invoice {
@@ -380,6 +381,7 @@ enum OnionPayload {
380
381
}
381
382
382
383
/// HTLCs that are to us and can be failed/claimed by the user
384
+ #[derive(PartialEq, Eq)]
383
385
struct ClaimableHTLC {
384
386
prev_hop: HTLCPreviousHopData,
385
387
cltv_expiry: u32,
@@ -411,6 +413,23 @@ impl From<&ClaimableHTLC> for events::ClaimedHTLC {
411
413
}
412
414
}
413
415
416
+ impl PartialOrd for ClaimableHTLC {
417
+ fn partial_cmp(&self, other: &ClaimableHTLC) -> Option<cmp::Ordering> {
418
+ Some(self.cmp(other))
419
+ }
420
+ }
421
+ impl Ord for ClaimableHTLC {
422
+ fn cmp(&self, other: &ClaimableHTLC) -> cmp::Ordering {
423
+ let res = (self.prev_hop.channel_id, self.prev_hop.htlc_id).cmp(
424
+ &(other.prev_hop.channel_id, other.prev_hop.htlc_id)
425
+ );
426
+ if res.is_eq() {
427
+ debug_assert!(self == other, "ClaimableHTLCs from the same source should be identical");
428
+ }
429
+ res
430
+ }
431
+ }
432
+
414
433
/// A trait defining behavior for creating and verifing the HMAC for authenticating a given data.
415
434
pub trait Verification {
416
435
/// Constructs an HMAC to include in [`OffersContext`] for the data along with the given
@@ -491,6 +510,22 @@ impl Verification for PaymentId {
491
510
}
492
511
}
493
512
513
+ impl PaymentId {
514
+ fn for_inbound_from_htlcs<I: Iterator<Item=(ChannelId, u64)>>(key: &[u8; 32], htlcs: I) -> PaymentId {
515
+ let mut prev_pair = None;
516
+ let mut hasher = HmacEngine::new(key);
517
+ for (channel_id, htlc_id) in htlcs {
518
+ hasher.input(&channel_id.0);
519
+ hasher.input(&htlc_id.to_le_bytes());
520
+ if let Some(prev) = prev_pair {
521
+ debug_assert!(prev < (channel_id, htlc_id), "HTLCs should be sorted");
522
+ }
523
+ prev_pair = Some((channel_id, htlc_id));
524
+ }
525
+ PaymentId(Hmac::<Sha256>::from_engine(hasher).to_byte_array())
526
+ }
527
+ }
528
+
494
529
impl Writeable for PaymentId {
495
530
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
496
531
self.0.write(w)
@@ -764,6 +799,7 @@ struct ClaimingPayment {
764
799
htlcs: Vec<events::ClaimedHTLC>,
765
800
sender_intended_value: Option<u64>,
766
801
onion_fields: Option<RecipientOnionFields>,
802
+ payment_id: Option<PaymentId>,
767
803
}
768
804
impl_writeable_tlv_based!(ClaimingPayment, {
769
805
(0, amount_msat, required),
@@ -772,6 +808,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
772
808
(5, htlcs, optional_vec),
773
809
(7, sender_intended_value, option),
774
810
(9, onion_fields, option),
811
+ (11, payment_id, option),
775
812
});
776
813
777
814
struct ClaimablePayment {
@@ -780,6 +817,15 @@ struct ClaimablePayment {
780
817
htlcs: Vec<ClaimableHTLC>,
781
818
}
782
819
820
+ impl ClaimablePayment {
821
+ fn inbound_payment_id(&self, secret: &[u8; 32]) -> PaymentId {
822
+ PaymentId::for_inbound_from_htlcs(
823
+ secret,
824
+ self.htlcs.iter().map(|htlc| (htlc.prev_hop.channel_id, htlc.prev_hop.htlc_id))
825
+ )
826
+ }
827
+ }
828
+
783
829
/// Represent the channel funding transaction type.
784
830
enum FundingType {
785
831
/// This variant is useful when we want LDK to validate the funding transaction and
@@ -5749,10 +5795,9 @@ where
5749
5795
} else {
5750
5796
claimable_payment.onion_fields = Some(onion_fields);
5751
5797
}
5752
- let ref mut htlcs = &mut claimable_payment.htlcs;
5753
5798
let mut total_value = claimable_htlc.sender_intended_value;
5754
5799
let mut earliest_expiry = claimable_htlc.cltv_expiry;
5755
- for htlc in htlcs.iter() {
5800
+ for htlc in claimable_payment. htlcs.iter() {
5756
5801
total_value += htlc.sender_intended_value;
5757
5802
earliest_expiry = cmp::min(earliest_expiry, htlc.cltv_expiry);
5758
5803
if htlc.total_msat != claimable_htlc.total_msat {
@@ -5774,13 +5819,18 @@ where
5774
5819
#[allow(unused_assignments)] {
5775
5820
committed_to_claimable = true;
5776
5821
}
5777
- htlcs.push(claimable_htlc);
5778
- let amount_msat = htlcs.iter().map(|htlc| htlc.value).sum();
5779
- htlcs.iter_mut().for_each(|htlc| htlc.total_value_received = Some(amount_msat));
5780
- let counterparty_skimmed_fee_msat = htlcs.iter()
5822
+ claimable_payment.htlcs.push(claimable_htlc);
5823
+ let amount_msat =
5824
+ claimable_payment.htlcs.iter().map(|htlc| htlc.value).sum();
5825
+ claimable_payment.htlcs.iter_mut()
5826
+ .for_each(|htlc| htlc.total_value_received = Some(amount_msat));
5827
+ let counterparty_skimmed_fee_msat = claimable_payment.htlcs.iter()
5781
5828
.map(|htlc| htlc.counterparty_skimmed_fee_msat.unwrap_or(0)).sum();
5782
5829
debug_assert!(total_value.saturating_sub(amount_msat) <=
5783
5830
counterparty_skimmed_fee_msat);
5831
+ claimable_payment.htlcs.sort();
5832
+ let payment_id =
5833
+ claimable_payment.inbound_payment_id(&self.inbound_payment_id_secret);
5784
5834
new_events.push_back((events::Event::PaymentClaimable {
5785
5835
receiver_node_id: Some(receiver_node_id),
5786
5836
payment_hash,
@@ -5791,13 +5841,14 @@ where
5791
5841
via_user_channel_id: Some(prev_user_channel_id),
5792
5842
claim_deadline: Some(earliest_expiry - HTLC_FAIL_BACK_BUFFER),
5793
5843
onion_fields: claimable_payment.onion_fields.clone(),
5844
+ payment_id: Some(payment_id),
5794
5845
}, None));
5795
5846
payment_claimable_generated = true;
5796
5847
} else {
5797
5848
// Nothing to do - we haven't reached the total
5798
5849
// payment value yet, wait until we receive more
5799
5850
// MPP parts.
5800
- htlcs.push(claimable_htlc);
5851
+ claimable_payment. htlcs.push(claimable_htlc);
5801
5852
#[allow(unused_assignments)] {
5802
5853
committed_to_claimable = true;
5803
5854
}
@@ -6594,6 +6645,7 @@ where
6594
6645
}
6595
6646
}
6596
6647
6648
+ let payment_id = payment.inbound_payment_id(&self.inbound_payment_id_secret);
6597
6649
let claiming_payment = claimable_payments.pending_claiming_payments
6598
6650
.entry(payment_hash)
6599
6651
.and_modify(|_| {
@@ -6611,6 +6663,7 @@ where
6611
6663
htlcs,
6612
6664
sender_intended_value,
6613
6665
onion_fields: payment.onion_fields,
6666
+ payment_id: Some(payment_id),
6614
6667
}
6615
6668
});
6616
6669
@@ -7128,6 +7181,7 @@ where
7128
7181
htlcs,
7129
7182
sender_intended_value: sender_intended_total_msat,
7130
7183
onion_fields,
7184
+ payment_id,
7131
7185
}) = payment {
7132
7186
self.pending_events.lock().unwrap().push_back((events::Event::PaymentClaimed {
7133
7187
payment_hash,
@@ -7137,6 +7191,7 @@ where
7137
7191
htlcs,
7138
7192
sender_intended_total_msat,
7139
7193
onion_fields,
7194
+ payment_id,
7140
7195
}, None));
7141
7196
}
7142
7197
},
@@ -12863,6 +12918,7 @@ where
12863
12918
previous_hop_monitor.provide_payment_preimage(&payment_hash, &payment_preimage, &args.tx_broadcaster, &bounded_fee_estimator, &args.logger);
12864
12919
}
12865
12920
}
12921
+ let payment_id = payment.inbound_payment_id(&inbound_payment_id_secret.unwrap());
12866
12922
pending_events_read.push_back((events::Event::PaymentClaimed {
12867
12923
receiver_node_id,
12868
12924
payment_hash,
@@ -12871,6 +12927,7 @@ where
12871
12927
htlcs: payment.htlcs.iter().map(events::ClaimedHTLC::from).collect(),
12872
12928
sender_intended_total_msat: payment.htlcs.first().map(|htlc| htlc.total_msat),
12873
12929
onion_fields: payment.onion_fields,
12930
+ payment_id: Some(payment_id),
12874
12931
}, None));
12875
12932
}
12876
12933
}
0 commit comments