@@ -106,6 +106,9 @@ pub(crate) enum PendingOutboundPayment {
106106 payment_metadata : Option < Vec < u8 > > ,
107107 keysend_preimage : Option < PaymentPreimage > ,
108108 invoice_request : Option < InvoiceRequest > ,
109+ // Storing the bolt12 invoice here to allow Proof of Payment after
110+ // the payment is made.
111+ bolt12_invoice : Option < Bolt12Invoice > ,
109112 custom_tlvs : Vec < ( u64 , Vec < u8 > ) > ,
110113 pending_amt_msat : u64 ,
111114 /// Used to track the fee paid. Present iff the payment was serialized on 0.0.103+.
@@ -155,6 +158,12 @@ impl_writeable_tlv_based!(RetryableInvoiceRequest, {
155158} ) ;
156159
157160impl PendingOutboundPayment {
161+ fn bolt12_invoice ( & self ) -> Option < & Bolt12Invoice > {
162+ match self {
163+ PendingOutboundPayment :: Retryable { bolt12_invoice, .. } => bolt12_invoice. as_ref ( ) ,
164+ _ => None ,
165+ }
166+ }
158167 fn increment_attempts ( & mut self ) {
159168 if let PendingOutboundPayment :: Retryable { attempts, .. } = self {
160169 attempts. count += 1 ;
@@ -831,7 +840,7 @@ impl OutboundPayments {
831840 IH : Fn ( ) -> InFlightHtlcs ,
832841 SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
833842 {
834- self . send_payment_internal ( payment_id, payment_hash, recipient_onion, None , retry_strategy,
843+ self . send_payment_for_non_bolt12_invoice ( payment_id, payment_hash, recipient_onion, None , retry_strategy,
835844 route_params, router, first_hops, & compute_inflight_htlcs, entropy_source, node_signer,
836845 best_block_height, logger, pending_events, & send_payment_along_path)
837846 }
@@ -854,7 +863,7 @@ impl OutboundPayments {
854863 let preimage = payment_preimage
855864 . unwrap_or_else ( || PaymentPreimage ( entropy_source. get_secure_random_bytes ( ) ) ) ;
856865 let payment_hash = PaymentHash ( Sha256 :: hash ( & preimage. 0 ) . to_byte_array ( ) ) ;
857- self . send_payment_internal ( payment_id, payment_hash, recipient_onion, Some ( preimage) ,
866+ self . send_payment_for_non_bolt12_invoice ( payment_id, payment_hash, recipient_onion, Some ( preimage) ,
858867 retry_strategy, route_params, router, first_hops, inflight_htlcs, entropy_source,
859868 node_signer, best_block_height, logger, pending_events, send_payment_along_path)
860869 . map ( |( ) | payment_hash)
@@ -897,7 +906,7 @@ impl OutboundPayments {
897906 route_params. max_total_routing_fee_msat = Some ( max_fee_msat) ;
898907 }
899908
900- self . send_payment_internal ( payment_id, payment_hash, recipient_onion, None , retry_strategy, route_params,
909+ self . send_payment_for_non_bolt12_invoice ( payment_id, payment_hash, recipient_onion, None , retry_strategy, route_params,
901910 router, first_hops, compute_inflight_htlcs,
902911 entropy_source, node_signer, best_block_height, logger,
903912 pending_events, send_payment_along_path
@@ -959,7 +968,7 @@ impl OutboundPayments {
959968 route_params. max_total_routing_fee_msat = Some ( max_fee_msat) ;
960969 }
961970 self . send_payment_for_bolt12_invoice_internal (
962- payment_id, payment_hash, None , None , route_params, retry_strategy, router, first_hops,
971+ payment_id, payment_hash, None , None , Some ( invoice ) , route_params, retry_strategy, router, first_hops,
963972 inflight_htlcs, entropy_source, node_signer, node_id_lookup, secp_ctx, best_block_height,
964973 logger, pending_events, send_payment_along_path
965974 )
@@ -970,6 +979,7 @@ impl OutboundPayments {
970979 > (
971980 & self , payment_id : PaymentId , payment_hash : PaymentHash ,
972981 keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
982+ bolt12_invoice : Option < & Bolt12Invoice > ,
973983 mut route_params : RouteParameters , retry_strategy : Retry , router : & R ,
974984 first_hops : Vec < ChannelDetails > , inflight_htlcs : IH , entropy_source : & ES , node_signer : & NS ,
975985 node_id_lookup : & NL , secp_ctx : & Secp256k1 < secp256k1:: All > , best_block_height : u32 , logger : & L ,
@@ -1032,8 +1042,8 @@ impl OutboundPayments {
10321042 hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
10331043 PendingOutboundPayment :: InvoiceReceived { .. } => {
10341044 let ( retryable_payment, onion_session_privs) = Self :: create_pending_payment (
1035- payment_hash, recipient_onion. clone ( ) , keysend_preimage, None , & route,
1036- Some ( retry_strategy) , payment_params, entropy_source, best_block_height
1045+ payment_hash, recipient_onion. clone ( ) , keysend_preimage, None , bolt12_invoice . cloned ( ) , & route,
1046+ Some ( retry_strategy) , payment_params, entropy_source, best_block_height,
10371047 ) ;
10381048 * entry. into_mut ( ) = retryable_payment;
10391049 onion_session_privs
@@ -1043,7 +1053,7 @@ impl OutboundPayments {
10431053 invoice_request
10441054 } else { unreachable ! ( ) } ;
10451055 let ( retryable_payment, onion_session_privs) = Self :: create_pending_payment (
1046- payment_hash, recipient_onion. clone ( ) , keysend_preimage, Some ( invreq) , & route,
1056+ payment_hash, recipient_onion. clone ( ) , keysend_preimage, Some ( invreq) , bolt12_invoice . cloned ( ) , & route,
10471057 Some ( retry_strategy) , payment_params, entropy_source, best_block_height
10481058 ) ;
10491059 outbounds. insert ( payment_id, retryable_payment) ;
@@ -1194,7 +1204,7 @@ impl OutboundPayments {
11941204 } ;
11951205
11961206 self . send_payment_for_bolt12_invoice_internal (
1197- payment_id, payment_hash, Some ( keysend_preimage) , Some ( & invoice_request) , route_params,
1207+ payment_id, payment_hash, Some ( keysend_preimage) , Some ( & invoice_request) , None , route_params,
11981208 retry_strategy, router, first_hops, inflight_htlcs, entropy_source, node_signer,
11991209 node_id_lookup, secp_ctx, best_block_height, logger, pending_events, send_payment_along_path
12001210 )
@@ -1318,7 +1328,7 @@ impl OutboundPayments {
13181328 ///
13191329 /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed
13201330 /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed
1321- fn send_payment_internal < R : Deref , NS : Deref , ES : Deref , IH , SP , L : Deref > (
1331+ fn send_payment_for_non_bolt12_invoice < R : Deref , NS : Deref , ES : Deref , IH , SP , L : Deref > (
13221332 & self , payment_id : PaymentId , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields ,
13231333 keysend_preimage : Option < PaymentPreimage > , retry_strategy : Retry , mut route_params : RouteParameters ,
13241334 router : & R , first_hops : Vec < ChannelDetails > , inflight_htlcs : IH , entropy_source : & ES ,
@@ -1340,7 +1350,7 @@ impl OutboundPayments {
13401350
13411351 let onion_session_privs = self . add_new_pending_payment ( payment_hash,
13421352 recipient_onion. clone ( ) , payment_id, keysend_preimage, & route, Some ( retry_strategy) ,
1343- Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height)
1353+ Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height, None )
13441354 . map_err ( |_| {
13451355 log_error ! ( logger, "Payment with id {} is already pending. New payment had payment hash {}" ,
13461356 payment_id, payment_hash) ;
@@ -1654,7 +1664,7 @@ impl OutboundPayments {
16541664 let route = Route { paths : vec ! [ path] , route_params : None } ;
16551665 let onion_session_privs = self . add_new_pending_payment ( payment_hash,
16561666 RecipientOnionFields :: secret_only ( payment_secret) , payment_id, None , & route, None , None ,
1657- entropy_source, best_block_height
1667+ entropy_source, best_block_height, None
16581668 ) . map_err ( |e| {
16591669 debug_assert ! ( matches!( e, PaymentSendFailure :: DuplicatePayment ) ) ;
16601670 ProbeSendFailure :: DuplicateProbe
@@ -1709,20 +1719,21 @@ impl OutboundPayments {
17091719 & self , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields , payment_id : PaymentId ,
17101720 route : & Route , retry_strategy : Option < Retry > , entropy_source : & ES , best_block_height : u32
17111721 ) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
1712- self . add_new_pending_payment ( payment_hash, recipient_onion, payment_id, None , route, retry_strategy, None , entropy_source, best_block_height)
1722+ self . add_new_pending_payment ( payment_hash, recipient_onion, payment_id, None , route, retry_strategy, None , entropy_source, best_block_height, None )
17131723 }
17141724
17151725 pub ( super ) fn add_new_pending_payment < ES : Deref > (
17161726 & self , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields , payment_id : PaymentId ,
17171727 keysend_preimage : Option < PaymentPreimage > , route : & Route , retry_strategy : Option < Retry > ,
1718- payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1728+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32 ,
1729+ bolt12_invoice : Option < Bolt12Invoice >
17191730 ) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
17201731 let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
17211732 match pending_outbounds. entry ( payment_id) {
17221733 hash_map:: Entry :: Occupied ( _) => Err ( PaymentSendFailure :: DuplicatePayment ) ,
17231734 hash_map:: Entry :: Vacant ( entry) => {
17241735 let ( payment, onion_session_privs) = Self :: create_pending_payment (
1725- payment_hash, recipient_onion, keysend_preimage, None , route, retry_strategy,
1736+ payment_hash, recipient_onion, keysend_preimage, None , bolt12_invoice , route, retry_strategy,
17261737 payment_params, entropy_source, best_block_height
17271738 ) ;
17281739 entry. insert ( payment) ;
@@ -1734,8 +1745,8 @@ impl OutboundPayments {
17341745 fn create_pending_payment < ES : Deref > (
17351746 payment_hash : PaymentHash , recipient_onion : RecipientOnionFields ,
17361747 keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < InvoiceRequest > ,
1737- route : & Route , retry_strategy : Option < Retry > , payment_params : Option < PaymentParameters > ,
1738- entropy_source : & ES , best_block_height : u32
1748+ bolt12_invoice : Option < Bolt12Invoice > , route : & Route , retry_strategy : Option < Retry > ,
1749+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
17391750 ) -> ( PendingOutboundPayment , Vec < [ u8 ; 32 ] > )
17401751 where
17411752 ES :: Target : EntropySource ,
@@ -1757,6 +1768,7 @@ impl OutboundPayments {
17571768 payment_metadata : recipient_onion. payment_metadata ,
17581769 keysend_preimage,
17591770 invoice_request,
1771+ bolt12_invoice,
17601772 custom_tlvs : recipient_onion. custom_tlvs ,
17611773 starting_block_height : best_block_height,
17621774 total_msat : route. get_total_amount ( ) ,
@@ -2374,6 +2386,7 @@ impl OutboundPayments {
23742386 payment_metadata: None , // only used for retries, and we'll never retry on startup
23752387 keysend_preimage: None , // only used for retries, and we'll never retry on startup
23762388 invoice_request: None , // only used for retries, and we'll never retry on startup
2389+ bolt12_invoice: None , // only used for retries, and we'll never retry on startup! TODO(vincenzopalazzo): double check this
23772390 custom_tlvs: Vec :: new( ) , // only used for retries, and we'll never retry on startup
23782391 pending_amt_msat: path_amt,
23792392 pending_fee_msat: Some ( path_fee) ,
@@ -2463,6 +2476,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
24632476 ( 10 , starting_block_height, required) ,
24642477 ( 11 , remaining_max_total_routing_fee_msat, option) ,
24652478 ( 13 , invoice_request, option) ,
2479+ ( 15 , bolt12_invoice, option) ,
24662480 ( not_written, retry_strategy, ( static_value, None ) ) ,
24672481 ( not_written, attempts, ( static_value, PaymentAttempts :: new( ) ) ) ,
24682482 } ,
@@ -2613,7 +2627,7 @@ mod tests {
26132627 outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , RecipientOnionFields :: spontaneous_empty ( ) ,
26142628 PaymentId ( [ 0 ; 32 ] ) , None , & Route { paths : vec ! [ ] , route_params : None } ,
26152629 Some ( Retry :: Attempts ( 1 ) ) , Some ( expired_route_params. payment_params . clone ( ) ) ,
2616- & & keys_manager, 0 ) . unwrap ( ) ;
2630+ & & keys_manager, 0 , None ) . unwrap ( ) ;
26172631 outbound_payments. find_route_and_send_payment (
26182632 PaymentHash ( [ 0 ; 32 ] ) , PaymentId ( [ 0 ; 32 ] ) , expired_route_params, & & router, vec ! [ ] ,
26192633 & || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger, & pending_events,
@@ -2656,7 +2670,7 @@ mod tests {
26562670 outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , RecipientOnionFields :: spontaneous_empty ( ) ,
26572671 PaymentId ( [ 0 ; 32 ] ) , None , & Route { paths : vec ! [ ] , route_params : None } ,
26582672 Some ( Retry :: Attempts ( 1 ) ) , Some ( route_params. payment_params . clone ( ) ) ,
2659- & & keys_manager, 0 ) . unwrap ( ) ;
2673+ & & keys_manager, 0 , None ) . unwrap ( ) ;
26602674 outbound_payments. find_route_and_send_payment (
26612675 PaymentHash ( [ 0 ; 32 ] ) , PaymentId ( [ 0 ; 32 ] ) , route_params, & & router, vec ! [ ] ,
26622676 & || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger, & pending_events,
0 commit comments