Skip to content

Commit 51cc639

Browse files
Drop need to store pending inbound payments
TODO commit msg
1 parent 01227de commit 51cc639

File tree

2 files changed

+241
-157
lines changed

2 files changed

+241
-157
lines changed

lightning/src/ln/channelmanager.rs

+176-93
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use core::{cmp, mem};
6565
use core::cell::RefCell;
6666
use io::{Cursor, Read};
6767
use sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
68+
use core::convert::TryInto;
6869
use core::sync::atomic::{AtomicUsize, Ordering};
6970
use core::time::Duration;
7071
#[cfg(any(test, feature = "allow_wallclock_use"))]
@@ -2585,6 +2586,52 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25852586
}
25862587
}
25872588

2589+
// Check that an inbound payment's `payment_data` field is sane.
2590+
fn verify_inbound_payment_data(&self, payment_hash: PaymentHash, payment_data: msgs::FinalOnionHopData) -> Result<Option<PaymentPreimage>, ()> {
2591+
let (metadata_bytes, hmac_bytes) = payment_data.payment_secret.0.split_at(16);
2592+
let expiry = u64::from_be_bytes(metadata_bytes[8..].try_into().unwrap());
2593+
if expiry < self.highest_seen_timestamp.load(Ordering::Acquire) as u64 {
2594+
log_trace!(self.logger, "Failing HTLC with payment_hash {}: expired payment", log_bytes!(payment_hash.0));
2595+
return Err(())
2596+
}
2597+
2598+
let is_user_payment_hash = metadata_bytes[0] & 1 << 7 != 0;
2599+
let mut payment_preimage = None;
2600+
if is_user_payment_hash {
2601+
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
2602+
hmac.input(&payment_hash.0[..]);
2603+
hmac.input(&metadata_bytes[..]);
2604+
if hmac_bytes != Hmac::from_engine(hmac).into_inner().split_at_mut(16).0 {
2605+
log_trace!(self.logger, "Failing HTLC with user-generated payment_hash {} due to mismatching HMAC", log_bytes!(payment_hash.0));
2606+
return Err(())
2607+
}
2608+
// Reset the bit that was set to indicate that the payment hash was user-generated.
2609+
let mut amt_msat_bytes = [0; 8];
2610+
amt_msat_bytes.copy_from_slice(&metadata_bytes[..8]);
2611+
amt_msat_bytes[0] ^= 1 << 7;
2612+
let min_amt_msat = u64::from_be_bytes(amt_msat_bytes.try_into().unwrap());
2613+
if payment_data.total_msat < min_amt_msat {
2614+
log_trace!(self.logger, "Failing HTLC with user-generated payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
2615+
return Err(())
2616+
}
2617+
} else {
2618+
let min_amt_msat = u64::from_be_bytes(metadata_bytes[..8].try_into().unwrap());
2619+
if payment_data.total_msat < min_amt_msat {
2620+
log_trace!(self.logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
2621+
return Err(())
2622+
}
2623+
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
2624+
hmac.input(&payment_data.payment_secret.0);
2625+
let decoded_payment_preimage = Hmac::from_engine(hmac).into_inner();
2626+
if payment_hash.0 != Sha256::hash(&decoded_payment_preimage).into_inner() {
2627+
log_trace!(self.logger, "Failing HTLC with payment_hash {}: payment preimage {} did not match", log_bytes!(payment_hash.0), log_bytes!(decoded_payment_preimage));
2628+
return Err(())
2629+
}
2630+
payment_preimage = Some(PaymentPreimage(decoded_payment_preimage));
2631+
}
2632+
Ok(payment_preimage)
2633+
}
2634+
25882635
/// Processes HTLCs which are pending waiting on random forward delay.
25892636
///
25902637
/// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -2800,6 +2847,56 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28002847
}
28012848
}
28022849

2850+
macro_rules! check_total_value {
2851+
($payment_data_total_msat: expr, $payment_secret: expr, $payment_preimage: expr) => {
2852+
let mut total_value = 0;
2853+
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2854+
.or_insert(Vec::new());
2855+
if htlcs.len() == 1 {
2856+
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2857+
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));
2858+
fail_htlc!(claimable_htlc);
2859+
continue
2860+
}
2861+
}
2862+
htlcs.push(claimable_htlc);
2863+
for htlc in htlcs.iter() {
2864+
total_value += htlc.value;
2865+
match &htlc.onion_payload {
2866+
OnionPayload::Invoice(htlc_payment_data) => {
2867+
if htlc_payment_data.total_msat != $payment_data_total_msat {
2868+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2869+
log_bytes!(payment_hash.0), $payment_data_total_msat, htlc_payment_data.total_msat);
2870+
total_value = msgs::MAX_VALUE_MSAT;
2871+
}
2872+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2873+
},
2874+
_ => unreachable!(),
2875+
}
2876+
}
2877+
if total_value >= msgs::MAX_VALUE_MSAT || total_value > $payment_data_total_msat {
2878+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2879+
log_bytes!(payment_hash.0), total_value, $payment_data_total_msat);
2880+
for htlc in htlcs.iter() {
2881+
fail_htlc!(htlc);
2882+
}
2883+
} else if total_value == $payment_data_total_msat {
2884+
new_events.push(events::Event::PaymentReceived {
2885+
payment_hash,
2886+
purpose: events::PaymentPurpose::InvoicePayment {
2887+
payment_preimage: $payment_preimage,
2888+
payment_secret: $payment_secret,
2889+
},
2890+
amt: total_value,
2891+
});
2892+
} else {
2893+
// Nothing to do - we haven't reached the total
2894+
// payment value yet, wait until we receive more
2895+
// MPP parts.
2896+
}
2897+
}
2898+
}
2899+
28032900
// Check that the payment hash and secret are known. Note that we
28042901
// MUST take care to handle the "unknown payment hash" and
28052902
// "incorrect payment secret" cases here identically or we'd expose
@@ -2810,9 +2907,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28102907
match payment_secrets.entry(payment_hash) {
28112908
hash_map::Entry::Vacant(_) => {
28122909
match claimable_htlc.onion_payload {
2813-
OnionPayload::Invoice(_) => {
2814-
log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we didn't have a corresponding inbound payment.", log_bytes!(payment_hash.0));
2815-
fail_htlc!(claimable_htlc);
2910+
OnionPayload::Invoice(ref payment_data) => {
2911+
let payment_preimage = match self.verify_inbound_payment_data(payment_hash, payment_data.clone()) {
2912+
Ok(payment_preimage) => payment_preimage,
2913+
Err(()) => {
2914+
fail_htlc!(claimable_htlc);
2915+
continue
2916+
}
2917+
};
2918+
let payment_data_total_msat = payment_data.total_msat;
2919+
let payment_secret = payment_data.payment_secret.clone();
2920+
check_total_value!(payment_data_total_msat, payment_secret, payment_preimage);
28162921
},
28172922
OnionPayload::Spontaneous(preimage) => {
28182923
match channel_state.claimable_htlcs.entry(payment_hash) {
@@ -2849,55 +2954,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28492954
log_bytes!(payment_hash.0), payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
28502955
fail_htlc!(claimable_htlc);
28512956
} else {
2852-
let mut total_value = 0;
2853-
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2854-
.or_insert(Vec::new());
2855-
if htlcs.len() == 1 {
2856-
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2857-
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));
2858-
fail_htlc!(claimable_htlc);
2859-
continue
2860-
}
2861-
}
2862-
htlcs.push(claimable_htlc);
2863-
for htlc in htlcs.iter() {
2864-
total_value += htlc.value;
2865-
match &htlc.onion_payload {
2866-
OnionPayload::Invoice(htlc_payment_data) => {
2867-
if htlc_payment_data.total_msat != payment_data.total_msat {
2868-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2869-
log_bytes!(payment_hash.0), payment_data.total_msat, htlc_payment_data.total_msat);
2870-
total_value = msgs::MAX_VALUE_MSAT;
2871-
}
2872-
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2873-
},
2874-
_ => unreachable!(),
2875-
}
2876-
}
2877-
if total_value >= msgs::MAX_VALUE_MSAT || total_value > payment_data.total_msat {
2878-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2879-
log_bytes!(payment_hash.0), total_value, payment_data.total_msat);
2880-
for htlc in htlcs.iter() {
2881-
fail_htlc!(htlc);
2882-
}
2883-
} else if total_value == payment_data.total_msat {
2884-
new_events.push(events::Event::PaymentReceived {
2885-
payment_hash,
2886-
purpose: events::PaymentPurpose::InvoicePayment {
2887-
payment_preimage: inbound_payment.get().payment_preimage,
2888-
payment_secret: payment_data.payment_secret,
2889-
},
2890-
amt: total_value,
2891-
});
2892-
// Only ever generate at most one PaymentReceived
2893-
// per registered payment_hash, even if it isn't
2894-
// claimed.
2895-
inbound_payment.remove_entry();
2896-
} else {
2897-
// Nothing to do - we haven't reached the total
2898-
// payment value yet, wait until we receive more
2899-
// MPP parts.
2900-
}
2957+
check_total_value!(payment_data.total_msat, payment_data.payment_secret, inbound_payment.get().payment_preimage);
29012958
}
29022959
},
29032960
};
@@ -4516,38 +4573,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
45164573
}
45174574
}
45184575

4519-
fn set_payment_hash_secret_map(&self, payment_hash: PaymentHash, payment_preimage: Option<PaymentPreimage>, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, APIError> {
4520-
assert!(invoice_expiry_delta_secs <= 60*60*24*365); // Sadly bitcoin timestamps are u32s, so panic before 2106
4521-
4522-
let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
4523-
4524-
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
4525-
let mut payment_secrets = self.pending_inbound_payments.lock().unwrap();
4526-
match payment_secrets.entry(payment_hash) {
4527-
hash_map::Entry::Vacant(e) => {
4528-
e.insert(PendingInboundPayment {
4529-
payment_secret, min_value_msat, payment_preimage,
4530-
user_payment_id: 0, // For compatibility with version 0.0.103 and earlier
4531-
// We assume that highest_seen_timestamp is pretty close to the current time -
4532-
// its updated when we receive a new block with the maximum time we've seen in
4533-
// a header. It should never be more than two hours in the future.
4534-
// Thus, we add two hours here as a buffer to ensure we absolutely
4535-
// never fail a payment too early.
4536-
// Note that we assume that received blocks have reasonably up-to-date
4537-
// timestamps.
4538-
expiry_time: self.highest_seen_timestamp.load(Ordering::Acquire) as u64 + invoice_expiry_delta_secs as u64 + 7200,
4539-
});
4540-
},
4541-
hash_map::Entry::Occupied(_) => return Err(APIError::APIMisuseError { err: "Duplicate payment hash".to_owned() }),
4542-
}
4543-
Ok(payment_secret)
4544-
}
4545-
45464576
/// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
45474577
/// to pay us.
45484578
///
45494579
/// This differs from [`create_inbound_payment_for_hash`] only in that it generates the
4550-
/// [`PaymentHash`] and [`PaymentPreimage`] for you, returning the first and storing the second.
4580+
/// [`PaymentHash`] and [`PaymentPreimage`] for you.
45514581
///
45524582
/// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentReceived`], which
45534583
/// will have the [`PaymentReceived::payment_preimage`] field filled in. That should then be
@@ -4560,12 +4590,38 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
45604590
/// [`PaymentReceived::payment_preimage`]: events::Event::PaymentReceived::payment_preimage
45614591
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
45624592
pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> (PaymentHash, PaymentSecret) {
4563-
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
4593+
let min_amt_msat_bytes: [u8; 8] = match min_value_msat {
4594+
Some(amt) => amt.to_be_bytes(),
4595+
None => [0; 8],
4596+
};
4597+
// We assume that highest_seen_timestamp is pretty close to the current time - its updated when
4598+
// we receive a new block with the maximum time we've seen in a header. It should never be more
4599+
// than two hours in the future. Thus, we add two hours here as a buffer to ensure we
4600+
// absolutely never fail a payment too early.
4601+
// Note that we assume that received blocks have reasonably up-to-date timestamps.
4602+
let expiry_bytes = (self.highest_seen_timestamp.load(Ordering::Acquire) as u64 + invoice_expiry_delta_secs as u64 + 7200).to_be_bytes();
4603+
let mut payment_secret_first_half: [u8; 16] = [0; 16];
4604+
{
4605+
let (min_amt_msat_slice, expiry_slice) = payment_secret_first_half.split_at_mut(8);
4606+
min_amt_msat_slice.copy_from_slice(&min_amt_msat_bytes);
4607+
expiry_slice.copy_from_slice(&expiry_bytes);
4608+
}
4609+
let rand_bytes = self.keys_manager.get_secure_random_bytes();
4610+
let mut payment_secret_bytes: [u8; 32] = [0; 32];
4611+
{
4612+
let (metadata_slice, rand_slice) = payment_secret_bytes.split_at_mut(16);
4613+
metadata_slice.copy_from_slice(&payment_secret_first_half);
4614+
rand_slice.copy_from_slice(&rand_bytes.split_at(16).0);
4615+
}
4616+
4617+
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
4618+
hmac.input(&payment_secret_bytes);
4619+
let payment_preimage_bytes = Hmac::from_engine(hmac).into_inner();
4620+
let payment_secret = PaymentSecret(payment_secret_bytes);
4621+
let payment_preimage = PaymentPreimage(payment_preimage_bytes);
45644622
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
45654623

4566-
(payment_hash,
4567-
self.set_payment_hash_secret_map(payment_hash, Some(payment_preimage), min_value_msat, invoice_expiry_delta_secs)
4568-
.expect("RNG Generated Duplicate PaymentHash"))
4624+
(payment_hash, payment_secret)
45694625
}
45704626

45714627
/// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is
@@ -4587,18 +4643,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
45874643
/// in excess of the current time. This should roughly match the expiry time set in the invoice.
45884644
/// After this many seconds, we will remove the inbound payment, resulting in any attempts to
45894645
/// pay the invoice failing. The BOLT spec suggests 3,600 secs as a default validity time for
4590-
/// invoices when no timeout is set.
4591-
///
4592-
/// Note that we use block header time to time-out pending inbound payments (with some margin
4593-
/// to compensate for the inaccuracy of block header timestamps). Thus, in practice we will
4646+
/// invoices when no timeout is set. Note that we use block header time to time-out pending
4647+
/// inbound payments (with some margin to compensate for the inaccuracy of block header
4648+
/// timestamps). Thus, in practice we will
45944649
/// accept a payment and generate a [`PaymentReceived`] event for some time after the expiry.
45954650
/// If you need exact expiry semantics, you should enforce them upon receipt of
45964651
/// [`PaymentReceived`].
45974652
///
4598-
/// Pending inbound payments are stored in memory and in serialized versions of this
4599-
/// [`ChannelManager`]. If potentially unbounded numbers of inbound payments may exist and
4600-
/// space is limited, you may wish to rate-limit inbound payment creation.
4601-
///
46024653
/// May panic if `invoice_expiry_delta_secs` is greater than one year.
46034654
///
46044655
/// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry`
@@ -4607,7 +4658,39 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
46074658
/// [`create_inbound_payment`]: Self::create_inbound_payment
46084659
/// [`PaymentReceived`]: events::Event::PaymentReceived
46094660
pub fn create_inbound_payment_for_hash(&self, payment_hash: PaymentHash, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32) -> Result<PaymentSecret, APIError> {
4610-
self.set_payment_hash_secret_map(payment_hash, None, min_value_msat, invoice_expiry_delta_secs)
4661+
let mut min_amt_msat_bytes: [u8; 8] = match min_value_msat {
4662+
Some(amt) => amt.to_be_bytes(),
4663+
None => [0; 8],
4664+
};
4665+
// Flip the highest bit of the min_amt_msat field to indicate that this payment has a
4666+
// user-generated PaymentHash.
4667+
min_amt_msat_bytes[0] |= 1 << 7;
4668+
4669+
// We assume that highest_seen_timestamp is pretty close to the current time - its updated when
4670+
// we receive a new block with the maximum time we've seen in a header. It should never be more
4671+
// than two hours in the future. Thus, we add two hours here as a buffer to ensure we
4672+
// absolutely never fail a payment too early.
4673+
// Note that we assume that received blocks have reasonably up-to-date timestamps.
4674+
let expiry_bytes = (self.highest_seen_timestamp.load(Ordering::Acquire) as u64 + invoice_expiry_delta_secs as u64 + 7200).to_be_bytes();
4675+
4676+
let mut payment_secret_metadata_bytes: [u8; 16] = [0; 16];
4677+
{
4678+
let (min_amt_msat_slice, expiry_slice) = payment_secret_metadata_bytes.split_at_mut(8);
4679+
min_amt_msat_slice.copy_from_slice(&min_amt_msat_bytes);
4680+
expiry_slice.copy_from_slice(&expiry_bytes);
4681+
}
4682+
let mut hmac = HmacEngine::<Sha256>::new(&self.our_network_key[..]);
4683+
hmac.input(&payment_hash.0[..]);
4684+
hmac.input(&min_amt_msat_bytes);
4685+
hmac.input(&expiry_bytes);
4686+
4687+
let mut payment_secret_bytes: [u8; 32] = [0; 32];
4688+
{
4689+
let (metadata_slice, hmac_slice) = payment_secret_bytes.split_at_mut(16);
4690+
metadata_slice.copy_from_slice(&payment_secret_metadata_bytes);
4691+
hmac_slice.copy_from_slice(&Hmac::from_engine(hmac).into_inner().split_at_mut(16).0);
4692+
}
4693+
Ok(PaymentSecret(payment_secret_bytes))
46114694
}
46124695

46134696
#[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))]

0 commit comments

Comments
 (0)