Skip to content

Commit 34c2f25

Browse files
Support verifying payment_secrets for inbound static invoice payments
Add a new payment type for this, because normally the payment hash is factored into the payment secrets we create for invoices, but static invoices don't have a payment hash since they are paid via keysend.
1 parent 45f88ee commit 34c2f25

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

lightning/src/ln/inbound_payment.rs

+34
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,13 @@ impl ExpandedKey {
9898
}
9999
}
100100

101+
/// We currently set aside 3 bits for the `Method` in the `PaymentSecret`.
101102
enum Method {
102103
LdkPaymentHash = 0,
103104
UserPaymentHash = 1,
104105
LdkPaymentHashCustomFinalCltv = 2,
105106
UserPaymentHashCustomFinalCltv = 3,
107+
SpontaneousPayment = 4,
106108
}
107109

108110
impl Method {
@@ -112,6 +114,7 @@ impl Method {
112114
bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash),
113115
bits if bits == Method::LdkPaymentHashCustomFinalCltv as u8 => Ok(Method::LdkPaymentHashCustomFinalCltv),
114116
bits if bits == Method::UserPaymentHashCustomFinalCltv as u8 => Ok(Method::UserPaymentHashCustomFinalCltv),
117+
bits if bits == Method::SpontaneousPayment as u8 => Ok(Method::SpontaneousPayment),
115118
unknown => Err(unknown),
116119
}
117120
}
@@ -191,6 +194,26 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment
191194
Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
192195
}
193196

197+
#[cfg(async_payments)]
198+
pub(super) fn create_for_spontaneous_payment(
199+
keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
200+
current_time: u64, min_final_cltv_expiry_delta: Option<u16>
201+
) -> Result<PaymentSecret, ()> {
202+
let metadata_bytes = construct_metadata_bytes(
203+
min_value_msat, Method::SpontaneousPayment, invoice_expiry_delta_secs, current_time,
204+
min_final_cltv_expiry_delta
205+
)?;
206+
207+
let mut hmac = HmacEngine::<Sha256>::new(&keys.spontaneous_pmt_key);
208+
hmac.input(&metadata_bytes);
209+
let hmac_bytes = Hmac::from_engine(hmac).to_byte_array();
210+
211+
let mut iv_bytes = [0 as u8; IV_LEN];
212+
iv_bytes.copy_from_slice(&hmac_bytes[..IV_LEN]);
213+
214+
Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
215+
}
216+
194217
fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method,
195218
invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option<u16>) -> Result<[u8; METADATA_LEN], ()> {
196219
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
@@ -320,6 +343,14 @@ pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::F
320343
}
321344
}
322345
},
346+
Ok(Method::SpontaneousPayment) => {
347+
let mut hmac = HmacEngine::<Sha256>::new(&keys.spontaneous_pmt_key);
348+
hmac.input(&metadata_bytes[..]);
349+
if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0) {
350+
log_trace!(logger, "Failing async payment HTLC with sender-generated payment_hash {}: unexpected payment_secret", &payment_hash);
351+
return Err(())
352+
}
353+
},
323354
Err(unknown_bits) => {
324355
log_trace!(logger, "Failing HTLC with payment hash {} due to unknown payment type {}", &payment_hash, unknown_bits);
325356
return Err(());
@@ -365,6 +396,9 @@ pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: Pa
365396
Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => Err(APIError::APIMisuseError {
366397
err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string()
367398
}),
399+
Ok(Method::SpontaneousPayment) => Err(APIError::APIMisuseError {
400+
err: "Can't extract payment preimage for spontaneous payments".to_string()
401+
}),
368402
Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }),
369403
}
370404
}

0 commit comments

Comments
 (0)