@@ -55,6 +55,11 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
55
55
use crate :: ln:: outbound_payment;
56
56
use crate :: ln:: outbound_payment:: { OutboundPayments , PaymentAttempts , PendingOutboundPayment } ;
57
57
use crate :: ln:: wire:: Encode ;
58
+ use crate :: offers:: invoice:: { DEFAULT_RELATIVE_EXPIRY , DerivedSigningPubkey , InvoiceBuilder } ;
59
+ use crate :: offers:: invoice_error:: InvoiceError ;
60
+ use crate :: offers:: merkle:: SignError ;
61
+ use crate :: offers:: parse:: SemanticError ;
62
+ use crate :: onion_message:: { OffersMessage , OffersMessageHandler } ;
58
63
use crate :: sign:: { EntropySource , KeysManager , NodeSigner , Recipient , SignerProvider , ChannelSigner , WriteableEcdsaChannelSigner } ;
59
64
use crate :: util:: config:: { UserConfig , ChannelConfig , ChannelConfigUpdate } ;
60
65
use crate :: util:: wakers:: { Future , Notifier } ;
@@ -7202,6 +7207,133 @@ where
7202
7207
}
7203
7208
}
7204
7209
7210
+ const BOLT_12_INVOICE_RETRY_STRATEGY : Retry = Retry :: Attempts ( 3 ) ;
7211
+
7212
+ impl < M : Deref , T : Deref , ES : Deref , NS : Deref , SP : Deref , F : Deref , R : Deref , L : Deref >
7213
+ OffersMessageHandler for ChannelManager < M , T , ES , NS , SP , F , R , L >
7214
+ where
7215
+ M :: Target : chain:: Watch < <SP :: Target as SignerProvider >:: Signer > ,
7216
+ T :: Target : BroadcasterInterface ,
7217
+ ES :: Target : EntropySource ,
7218
+ NS :: Target : NodeSigner ,
7219
+ SP :: Target : SignerProvider ,
7220
+ F :: Target : FeeEstimator ,
7221
+ R :: Target : Router ,
7222
+ L :: Target : Logger ,
7223
+ {
7224
+ fn handle_message ( & self , message : OffersMessage ) -> Option < OffersMessage > {
7225
+ let secp_ctx = & self . secp_ctx ;
7226
+ let expanded_key = & self . inbound_payment_key ;
7227
+
7228
+ match message {
7229
+ OffersMessage :: InvoiceRequest ( invoice_request) => {
7230
+ let amount_msats = match InvoiceBuilder :: < DerivedSigningPubkey > :: amount_msats (
7231
+ & invoice_request
7232
+ ) {
7233
+ Ok ( amount_msats) => Some ( amount_msats) ,
7234
+ Err ( error) => return Some ( OffersMessage :: InvoiceError ( error. into ( ) ) ) ,
7235
+ } ;
7236
+ let invoice_request = match invoice_request. verify ( expanded_key, secp_ctx) {
7237
+ Ok ( invoice_request) => invoice_request,
7238
+ Err ( ( ) ) => {
7239
+ let error = SemanticError :: InvalidMetadata ;
7240
+ return Some ( OffersMessage :: InvoiceError ( error. into ( ) ) ) ;
7241
+ } ,
7242
+ } ;
7243
+ let relative_expiry = DEFAULT_RELATIVE_EXPIRY . as_secs ( ) as u32 ;
7244
+
7245
+ match self . create_inbound_payment ( amount_msats, relative_expiry, None ) {
7246
+ Ok ( ( payment_hash, _payment_secret) ) if invoice_request. keys . is_some ( ) => {
7247
+ // TODO: Include payment_secret in payment_paths.
7248
+ let payment_paths = vec ! [ ] ;
7249
+ #[ cfg( not( feature = "no-std" ) ) ]
7250
+ let builder = invoice_request. respond_using_derived_keys (
7251
+ payment_paths, payment_hash
7252
+ ) ;
7253
+ #[ cfg( feature = "no-std" ) ]
7254
+ let created_at = Duration :: from_secs (
7255
+ self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64
7256
+ ) ;
7257
+ #[ cfg( feature = "no-std" ) ]
7258
+ let builder = invoice_request. respond_using_derived_keys_no_std (
7259
+ payment_paths, payment_hash, created_at
7260
+ ) ;
7261
+ match builder. and_then ( |b| b. allow_mpp ( ) . build_and_sign ( secp_ctx) ) {
7262
+ Ok ( invoice) => Some ( OffersMessage :: Invoice ( invoice) ) ,
7263
+ Err ( error) => Some ( OffersMessage :: InvoiceError ( error. into ( ) ) ) ,
7264
+ }
7265
+ } ,
7266
+ Ok ( ( payment_hash, _payment_secret) ) => {
7267
+ // TODO: Include payment_secret in payment_paths.
7268
+ let payment_paths = vec ! [ ] ;
7269
+ #[ cfg( not( feature = "no-std" ) ) ]
7270
+ let builder = invoice_request. respond_with ( payment_paths, payment_hash) ;
7271
+ #[ cfg( feature = "no-std" ) ]
7272
+ let created_at = Duration :: from_secs (
7273
+ self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64
7274
+ ) ;
7275
+ #[ cfg( feature = "no-std" ) ]
7276
+ let builder = invoice_request. respond_with_no_std (
7277
+ payment_paths, payment_hash, created_at
7278
+ ) ;
7279
+ let response = builder. and_then ( |builder| builder. allow_mpp ( ) . build ( ) )
7280
+ . map_err ( |e| OffersMessage :: InvoiceError ( e. into ( ) ) )
7281
+ . and_then ( |invoice|
7282
+ match invoice. sign ( |digest, tag, bytes, metadata|
7283
+ self . node_signer . sign_bolt12_message ( digest, tag, bytes, metadata)
7284
+ ) {
7285
+ Ok ( invoice) => Ok ( OffersMessage :: Invoice ( invoice) ) ,
7286
+ Err ( SignError :: Signing ( ( ) ) ) => Err ( OffersMessage :: InvoiceError (
7287
+ InvoiceError :: from_str ( "Failed signing invoice" )
7288
+ ) ) ,
7289
+ Err ( SignError :: Verification ( _) ) => Err ( OffersMessage :: InvoiceError (
7290
+ InvoiceError :: from_str ( "Failed invoice signature verification" )
7291
+ ) ) ,
7292
+ } ) ;
7293
+ match response {
7294
+ Ok ( invoice) => Some ( invoice) ,
7295
+ Err ( error) => Some ( error) ,
7296
+ }
7297
+ } ,
7298
+ Err ( ( ) ) => {
7299
+ Some ( OffersMessage :: InvoiceError ( SemanticError :: InvalidAmount . into ( ) ) )
7300
+ } ,
7301
+ }
7302
+ } ,
7303
+ OffersMessage :: Invoice ( invoice) => {
7304
+ if !invoice. verify ( expanded_key, secp_ctx) {
7305
+ Some ( OffersMessage :: InvoiceError ( InvoiceError :: from_str ( "Unrecognized invoice" ) ) )
7306
+ } else if invoice. features ( ) . requires_unknown_bits ( ) {
7307
+ Some ( OffersMessage :: InvoiceError ( SemanticError :: UnknownRequiredFeatures . into ( ) ) )
7308
+ } else {
7309
+ let recipient_onion = RecipientOnionFields {
7310
+ payment_secret : None ,
7311
+ payment_metadata : None ,
7312
+ } ;
7313
+ let payment_hash = invoice. payment_hash ( ) ;
7314
+ let payment_id = PaymentId ( payment_hash. 0 ) ;
7315
+ let route_params = RouteParameters {
7316
+ payment_params : PaymentParameters :: from_bolt12_invoice ( & invoice) ,
7317
+ final_value_msat : invoice. amount_msats ( ) ,
7318
+ } ;
7319
+ if let Err ( e) = self . send_payment (
7320
+ payment_hash, recipient_onion, payment_id, route_params,
7321
+ BOLT_12_INVOICE_RETRY_STRATEGY
7322
+ ) {
7323
+ // TODO: Should we send an invoice_error?
7324
+ log_error ! ( self . logger, "Failed paying invoice: {:?}" , e) ;
7325
+ }
7326
+ None
7327
+ }
7328
+ } ,
7329
+ OffersMessage :: InvoiceError ( invoice_error) => {
7330
+ log_error ! ( self . logger, "Received invoice_error: {}" , invoice_error) ;
7331
+ None
7332
+ } ,
7333
+ }
7334
+ }
7335
+ }
7336
+
7205
7337
/// Fetches the set of [`NodeFeatures`] flags which are provided by or required by
7206
7338
/// [`ChannelManager`].
7207
7339
pub ( crate ) fn provided_node_features ( config : & UserConfig ) -> NodeFeatures {
0 commit comments