}
}
+/// We currently set aside 3 bits for the `Method` in the `PaymentSecret`.
enum Method {
LdkPaymentHash = 0,
UserPaymentHash = 1,
LdkPaymentHashCustomFinalCltv = 2,
UserPaymentHashCustomFinalCltv = 3,
+ SpontaneousPayment = 4,
}
impl Method {
bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash),
bits if bits == Method::LdkPaymentHashCustomFinalCltv as u8 => Ok(Method::LdkPaymentHashCustomFinalCltv),
bits if bits == Method::UserPaymentHashCustomFinalCltv as u8 => Ok(Method::UserPaymentHashCustomFinalCltv),
+ bits if bits == Method::SpontaneousPayment as u8 => Ok(Method::SpontaneousPayment),
unknown => Err(unknown),
}
}
Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
}
+#[cfg(async_payments)]
+pub(super) fn create_for_spontaneous_payment(
+ keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
+ current_time: u64, min_final_cltv_expiry_delta: Option<u16>
+) -> Result<PaymentSecret, ()> {
+ let metadata_bytes = construct_metadata_bytes(
+ min_value_msat, Method::SpontaneousPayment, invoice_expiry_delta_secs, current_time,
+ min_final_cltv_expiry_delta
+ )?;
+
+ let mut hmac = HmacEngine::<Sha256>::new(&keys.spontaneous_pmt_key);
+ hmac.input(&metadata_bytes);
+ let hmac_bytes = Hmac::from_engine(hmac).to_byte_array();
+
+ let mut iv_bytes = [0 as u8; IV_LEN];
+ iv_bytes.copy_from_slice(&hmac_bytes[..IV_LEN]);
+
+ Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
+}
+
fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method,
invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64, min_final_cltv_expiry_delta: Option<u16>) -> Result<[u8; METADATA_LEN], ()> {
if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
}
}
},
+ Ok(Method::SpontaneousPayment) => {
+ let mut hmac = HmacEngine::<Sha256>::new(&keys.spontaneous_pmt_key);
+ hmac.input(&metadata_bytes[..]);
+ if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).to_byte_array().split_at_mut(IV_LEN).0) {
+ log_trace!(logger, "Failing async payment HTLC with sender-generated payment_hash {}: unexpected payment_secret", &payment_hash);
+ return Err(())
+ }
+ },
Err(unknown_bits) => {
log_trace!(logger, "Failing HTLC with payment hash {} due to unknown payment type {}", &payment_hash, unknown_bits);
return Err(());
Ok(Method::UserPaymentHash) | Ok(Method::UserPaymentHashCustomFinalCltv) => Err(APIError::APIMisuseError {
err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string()
}),
+ Ok(Method::SpontaneousPayment) => Err(APIError::APIMisuseError {
+ err: "Can't extract payment preimage for spontaneous payments".to_string()
+ }),
Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }),
}
}