Skip to content

Commit 5bbb2c7

Browse files
committed
XXX docs/commitmsg Add payment secret and preimage tracking in ChannelManager
This doesn't yet use such tracking anywhere.
1 parent 6d3b752 commit 5bbb2c7

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,18 @@ struct PeerState {
352352
latest_features: InitFeatures,
353353
}
354354

355+
/// Stores a PaymentSecret and any other data we may need to validate an inbound payment is
356+
/// actually ours and not some duplicate HTLC sent to us by a node along the route.
357+
///
358+
/// For users who don't want to bother doing their own payment preimage storage, we also store that
359+
/// here.
360+
struct PendingInboundPayment {
361+
payment_secret: PaymentSecret,
362+
expiry_height: u32,
363+
value_msat: Option<u64>,
364+
payment_preimage: Option<PaymentPreimage>,
365+
}
366+
355367
/// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
356368
/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
357369
/// lifetimes). Other times you can afford a reference, which is more efficient, in which case
@@ -430,6 +442,10 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
430442
pub(super) channel_state: Mutex<ChannelHolder<Signer>>,
431443
#[cfg(not(any(test, feature = "_test_utils")))]
432444
channel_state: Mutex<ChannelHolder<Signer>>,
445+
446+
/// Locked *after* channel_state.
447+
payment_secrets: Mutex<HashMap<PaymentHash, PendingInboundPayment>>,
448+
433449
our_network_key: SecretKey,
434450
our_network_pubkey: PublicKey,
435451

@@ -852,6 +868,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
852868
claimable_htlcs: HashMap::new(),
853869
pending_msg_events: Vec::new(),
854870
}),
871+
payment_secrets: Mutex::new(HashMap::new()),
872+
855873
our_network_key: keys_manager.get_node_secret(),
856874
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()),
857875
secp_ctx,
@@ -3305,6 +3323,67 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33053323
self.finish_force_close_channel(failure);
33063324
}
33073325
}
3326+
3327+
/// Gets a payment secret, payment hash, and absolute CLTV expiry for use in an invoice given
3328+
/// to a third party wishing to pay us.
3329+
///
3330+
/// A [`PaymentReceived`] event will only be generated if the payment secret matches a payment
3331+
/// secret fetched via this method or [`get_payment_secret`], and which is at least the `value`
3332+
/// provided here, if one is provided.
3333+
///
3334+
/// invoice_expiry_delta_blocks describes the number of blocks which the invoice is valid for,
3335+
/// in excess of the current block height. This should match the value set in the invoice.
3336+
///
3337+
/// May panic if invoice_expiry_delta_blocks is greater than one year of blocks (52,560).
3338+
pub fn get_payment_secret_preimage(&self, value_msat: Option<u64>, invoice_expiry_delta_blocks: u32) -> (PaymentHash, PaymentSecret) {
3339+
assert!(invoice_expiry_delta_blocks <= 6*24*365); // We may overflow later if this value is too large
3340+
3341+
let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
3342+
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
3343+
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
3344+
3345+
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3346+
let mut payment_secrets = self.payment_secrets.lock().unwrap();
3347+
if payment_secrets.insert(payment_hash, PendingInboundPayment {
3348+
payment_secret, value_msat,
3349+
expiry_height: self.best_block.read().unwrap().height() + HTLC_FAIL_BACK_BUFFER + invoice_expiry_delta_blocks,
3350+
payment_preimage: Some(payment_preimage)
3351+
}).is_some() {
3352+
panic!("RNG Generated Duplicate PaymentHash");
3353+
}
3354+
(payment_hash, payment_secret)
3355+
}
3356+
3357+
/// Gets a payment_secret for a given payment hash, for which the payment preimage is stored
3358+
/// external to LDK.
3359+
///
3360+
/// A [`PaymentReceived`] event will only be generated if the payment secret matches a payment
3361+
/// secret fetched via this method or [`get_payment_secret_preimage`], and which is at least
3362+
/// the `value` provided here, if one is provided.
3363+
///
3364+
/// The payment_hash (and corresponding payment preimage) must be globally unique. This method
3365+
/// may return an Err if another payment with the same payment_hash is still pending.
3366+
///
3367+
/// invoice_expiry_delta_blocks describes the number of blocks which the invoice is valid for,
3368+
/// in excess of the current block height. This should match the value set in the invoice.
3369+
///
3370+
/// May panic if invoice_expiry_delta_blocks is greater than one year of blocks (52,560).
3371+
pub fn get_payment_secret(&self, payment_hash: PaymentHash, value_msat: Option<u64>, invoice_expiry_delta_blocks: u32) -> Result<PaymentSecret, APIError> {
3372+
let payment_secret = PaymentSecret(self.keys_manager.get_secure_random_bytes());
3373+
3374+
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3375+
let mut payment_secrets = self.payment_secrets.lock().unwrap();
3376+
match payment_secrets.entry(payment_hash) {
3377+
hash_map::Entry::Vacant(e) => {
3378+
e.insert(PendingInboundPayment {
3379+
payment_secret, value_msat, payment_preimage: None,
3380+
expiry_height: self.best_block.read().unwrap().height() + HTLC_FAIL_BACK_BUFFER + invoice_expiry_delta_blocks,
3381+
});
3382+
},
3383+
hash_map::Entry::Occupied(_) => return Err(APIError::APIMisuseError { err: "Duplicate payment hash".to_owned() }),
3384+
}
3385+
Ok(payment_secret)
3386+
}
33083387
}
33093388

33103389
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> MessageSendEventsProvider for ChannelManager<Signer, M, T, K, F, L>
@@ -4153,6 +4232,13 @@ impl Readable for HTLCForwardInfo {
41534232
}
41544233
}
41554234

4235+
impl_writeable!(PendingInboundPayment, 0, {
4236+
payment_secret,
4237+
expiry_height,
4238+
value_msat,
4239+
payment_preimage
4240+
});
4241+
41564242
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
41574243
where M::Target: chain::Watch<Signer>,
41584244
T::Target: BroadcasterInterface,
@@ -4233,6 +4319,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
42334319

42344320
(self.last_node_announcement_serial.load(Ordering::Acquire) as u32).write(writer)?;
42354321

4322+
let payment_secrets = self.payment_secrets.lock().unwrap();
4323+
(payment_secrets.len() as u64).write(writer)?;
4324+
for (hash, pending_payment) in payment_secrets.iter() {
4325+
hash.write(writer)?;
4326+
pending_payment.write(writer)?;
4327+
}
4328+
42364329
Ok(())
42374330
}
42384331
}
@@ -4463,6 +4556,14 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
44634556

44644557
let last_node_announcement_serial: u32 = Readable::read(reader)?;
44654558

4559+
let payment_secret_count: u64 = Readable::read(reader)?;
4560+
let mut payment_secrets: HashMap<PaymentHash, PendingInboundPayment> = HashMap::with_capacity(cmp::min(payment_secret_count as usize, MAX_ALLOC_SIZE/(3*32)));
4561+
for _ in 0..payment_secret_count {
4562+
if payment_secrets.insert(Readable::read(reader)?, Readable::read(reader)?).is_some() {
4563+
return Err(DecodeError::InvalidValue);
4564+
}
4565+
}
4566+
44664567
let mut secp_ctx = Secp256k1::new();
44674568
secp_ctx.seeded_randomize(&args.keys_manager.get_secure_random_bytes());
44684569

@@ -4481,6 +4582,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
44814582
claimable_htlcs,
44824583
pending_msg_events: Vec::new(),
44834584
}),
4585+
payment_secrets: Mutex::new(payment_secrets),
4586+
44844587
our_network_key: args.keys_manager.get_node_secret(),
44854588
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &args.keys_manager.get_node_secret()),
44864589
secp_ctx,

0 commit comments

Comments
 (0)