@@ -98,6 +98,7 @@ enum Method {
98
98
UserPaymentHash = 1 ,
99
99
LdkPaymentHashCustomFinalCltv = 2 ,
100
100
UserPaymentHashCustomFinalCltv = 3 ,
101
+ SpontaneousPayment = 4 ,
101
102
}
102
103
103
104
impl Method {
@@ -107,6 +108,7 @@ impl Method {
107
108
bits if bits == Method :: UserPaymentHash as u8 => Ok ( Method :: UserPaymentHash ) ,
108
109
bits if bits == Method :: LdkPaymentHashCustomFinalCltv as u8 => Ok ( Method :: LdkPaymentHashCustomFinalCltv ) ,
109
110
bits if bits == Method :: UserPaymentHashCustomFinalCltv as u8 => Ok ( Method :: UserPaymentHashCustomFinalCltv ) ,
111
+ bits if bits == Method :: SpontaneousPayment as u8 => Ok ( Method :: SpontaneousPayment ) ,
110
112
unknown => Err ( unknown) ,
111
113
}
112
114
}
@@ -186,6 +188,26 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment
186
188
Ok ( construct_payment_secret ( & iv_bytes, & metadata_bytes, & keys. metadata_key ) )
187
189
}
188
190
191
+ #[ cfg( async_payments) ]
192
+ pub ( super ) fn create_for_spontaneous_payment (
193
+ keys : & ExpandedKey , min_value_msat : Option < u64 > , invoice_expiry_delta_secs : u32 ,
194
+ current_time : u64 , min_final_cltv_expiry_delta : Option < u16 >
195
+ ) -> Result < PaymentSecret , ( ) > {
196
+ let metadata_bytes = construct_metadata_bytes (
197
+ min_value_msat, Method :: SpontaneousPayment , invoice_expiry_delta_secs, current_time,
198
+ min_final_cltv_expiry_delta
199
+ ) ?;
200
+
201
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. offers_base_key ) ;
202
+ hmac. input ( & metadata_bytes) ;
203
+ let hmac_bytes = Hmac :: from_engine ( hmac) . to_byte_array ( ) ;
204
+
205
+ let mut iv_bytes = [ 0 as u8 ; IV_LEN ] ;
206
+ iv_bytes. copy_from_slice ( & hmac_bytes[ ..IV_LEN ] ) ;
207
+
208
+ Ok ( construct_payment_secret ( & iv_bytes, & metadata_bytes, & keys. metadata_key ) )
209
+ }
210
+
189
211
fn construct_metadata_bytes ( min_value_msat : Option < u64 > , payment_type : Method ,
190
212
invoice_expiry_delta_secs : u32 , highest_seen_timestamp : u64 , min_final_cltv_expiry_delta : Option < u16 > ) -> Result < [ u8 ; METADATA_LEN ] , ( ) > {
191
213
if min_value_msat. is_some ( ) && min_value_msat. unwrap ( ) > MAX_VALUE_MSAT {
@@ -315,6 +337,14 @@ pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::F
315
337
}
316
338
}
317
339
} ,
340
+ Ok ( Method :: SpontaneousPayment ) => {
341
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. offers_base_key ) ;
342
+ hmac. input ( & metadata_bytes[ ..] ) ;
343
+ if !fixed_time_eq ( & iv_bytes, & Hmac :: from_engine ( hmac) . to_byte_array ( ) . split_at_mut ( IV_LEN ) . 0 ) {
344
+ log_trace ! ( logger, "Failing async payment HTLC with sender-generated payment_hash {}: unexpected payment_secret" , & payment_hash) ;
345
+ return Err ( ( ) )
346
+ }
347
+ } ,
318
348
Err ( unknown_bits) => {
319
349
log_trace ! ( logger, "Failing HTLC with payment hash {} due to unknown payment type {}" , & payment_hash, unknown_bits) ;
320
350
return Err ( ( ) ) ;
@@ -360,6 +390,9 @@ pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: Pa
360
390
Ok ( Method :: UserPaymentHash ) | Ok ( Method :: UserPaymentHashCustomFinalCltv ) => Err ( APIError :: APIMisuseError {
361
391
err : "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash" . to_string ( )
362
392
} ) ,
393
+ Ok ( Method :: SpontaneousPayment ) => Err ( APIError :: APIMisuseError {
394
+ err : "Can't extract payment preimage for spontaneous payments" . to_string ( )
395
+ } ) ,
363
396
Err ( other) => Err ( APIError :: APIMisuseError { err : format ! ( "Unknown payment type: {}" , other) } ) ,
364
397
}
365
398
}
0 commit comments