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