@@ -104,6 +104,9 @@ pub(crate) enum PendingOutboundPayment {
104
104
payment_metadata : Option < Vec < u8 > > ,
105
105
keysend_preimage : Option < PaymentPreimage > ,
106
106
invoice_request : Option < InvoiceRequest > ,
107
+ // Storing the bolt12 invoice here to allow Proof of Payment after
108
+ // the payment is made.
109
+ bolt12_invoice : Option < Bolt12Invoice > ,
107
110
custom_tlvs : Vec < ( u64 , Vec < u8 > ) > ,
108
111
pending_amt_msat : u64 ,
109
112
/// Used to track the fee paid. Present iff the payment was serialized on 0.0.103+.
@@ -153,6 +156,12 @@ impl_writeable_tlv_based!(RetryableInvoiceRequest, {
153
156
} ) ;
154
157
155
158
impl PendingOutboundPayment {
159
+ fn bolt12_invoice ( & self ) -> Option < & Bolt12Invoice > {
160
+ match self {
161
+ PendingOutboundPayment :: Retryable { bolt12_invoice, .. } => bolt12_invoice. as_ref ( ) ,
162
+ _ => None ,
163
+ }
164
+ }
156
165
fn increment_attempts ( & mut self ) {
157
166
if let PendingOutboundPayment :: Retryable { attempts, .. } = self {
158
167
attempts. count += 1 ;
@@ -896,7 +905,7 @@ impl OutboundPayments {
896
905
route_params. max_total_routing_fee_msat = Some ( max_fee_msat) ;
897
906
}
898
907
self . send_payment_for_bolt12_invoice_internal (
899
- payment_id, payment_hash, None , None , route_params, retry_strategy, router, first_hops,
908
+ payment_id, payment_hash, None , None , Some ( invoice ) , route_params, retry_strategy, router, first_hops,
900
909
inflight_htlcs, entropy_source, node_signer, node_id_lookup, secp_ctx, best_block_height,
901
910
logger, pending_events, send_payment_along_path
902
911
)
@@ -907,6 +916,7 @@ impl OutboundPayments {
907
916
> (
908
917
& self , payment_id : PaymentId , payment_hash : PaymentHash ,
909
918
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
919
+ bolt12_invoice : Option < & Bolt12Invoice > ,
910
920
mut route_params : RouteParameters , retry_strategy : Retry , router : & R ,
911
921
first_hops : Vec < ChannelDetails > , inflight_htlcs : IH , entropy_source : & ES , node_signer : & NS ,
912
922
node_id_lookup : & NL , secp_ctx : & Secp256k1 < secp256k1:: All > , best_block_height : u32 , logger : & L ,
@@ -969,18 +979,20 @@ impl OutboundPayments {
969
979
hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
970
980
PendingOutboundPayment :: InvoiceReceived { .. } => {
971
981
let ( retryable_payment, onion_session_privs) = Self :: create_pending_payment (
972
- payment_hash, recipient_onion. clone ( ) , keysend_preimage, None , & route,
973
- Some ( retry_strategy) , payment_params, entropy_source, best_block_height
982
+ payment_hash, recipient_onion. clone ( ) , keysend_preimage, None , bolt12_invoice . cloned ( ) , & route,
983
+ Some ( retry_strategy) , payment_params, entropy_source, best_block_height,
974
984
) ;
975
985
* entry. into_mut ( ) = retryable_payment;
976
986
onion_session_privs
977
987
} ,
988
+ // TODO(vincenzopalazzo): What about static invoices? There is no proof of payment with async payment because we need PTLC
989
+ // so we can ingore it for now
978
990
PendingOutboundPayment :: StaticInvoiceReceived { .. } => {
979
991
let invreq = if let PendingOutboundPayment :: StaticInvoiceReceived { invoice_request, .. } = entry. remove ( ) {
980
992
invoice_request
981
993
} else { unreachable ! ( ) } ;
982
994
let ( retryable_payment, onion_session_privs) = Self :: create_pending_payment (
983
- payment_hash, recipient_onion. clone ( ) , keysend_preimage, Some ( invreq) , & route,
995
+ payment_hash, recipient_onion. clone ( ) , keysend_preimage, Some ( invreq) , None , & route,
984
996
Some ( retry_strategy) , payment_params, entropy_source, best_block_height
985
997
) ;
986
998
outbounds. insert ( payment_id, retryable_payment) ;
@@ -1130,7 +1142,7 @@ impl OutboundPayments {
1130
1142
} ;
1131
1143
1132
1144
self . send_payment_for_bolt12_invoice_internal (
1133
- payment_id, payment_hash, Some ( keysend_preimage) , Some ( & invoice_request) , route_params,
1145
+ payment_id, payment_hash, Some ( keysend_preimage) , Some ( & invoice_request) , None , route_params,
1134
1146
retry_strategy, router, first_hops, inflight_htlcs, entropy_source, node_signer,
1135
1147
node_id_lookup, secp_ctx, best_block_height, logger, pending_events, send_payment_along_path
1136
1148
)
@@ -1276,7 +1288,7 @@ impl OutboundPayments {
1276
1288
1277
1289
let onion_session_privs = self . add_new_pending_payment ( payment_hash,
1278
1290
recipient_onion. clone ( ) , payment_id, keysend_preimage, & route, Some ( retry_strategy) ,
1279
- Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height)
1291
+ Some ( route_params. payment_params . clone ( ) ) , entropy_source, best_block_height, None )
1280
1292
. map_err ( |_| {
1281
1293
log_error ! ( logger, "Payment with id {} is already pending. New payment had payment hash {}" ,
1282
1294
payment_id, payment_hash) ;
@@ -1590,7 +1602,7 @@ impl OutboundPayments {
1590
1602
let route = Route { paths : vec ! [ path] , route_params : None } ;
1591
1603
let onion_session_privs = self . add_new_pending_payment ( payment_hash,
1592
1604
RecipientOnionFields :: secret_only ( payment_secret) , payment_id, None , & route, None , None ,
1593
- entropy_source, best_block_height
1605
+ entropy_source, best_block_height, None
1594
1606
) . map_err ( |e| {
1595
1607
debug_assert ! ( matches!( e, PaymentSendFailure :: DuplicatePayment ) ) ;
1596
1608
ProbeSendFailure :: DuplicateProbe
@@ -1645,20 +1657,21 @@ impl OutboundPayments {
1645
1657
& self , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields , payment_id : PaymentId ,
1646
1658
route : & Route , retry_strategy : Option < Retry > , entropy_source : & ES , best_block_height : u32
1647
1659
) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
1648
- self . add_new_pending_payment ( payment_hash, recipient_onion, payment_id, None , route, retry_strategy, None , entropy_source, best_block_height)
1660
+ self . add_new_pending_payment ( payment_hash, recipient_onion, payment_id, None , route, retry_strategy, None , entropy_source, best_block_height, None )
1649
1661
}
1650
1662
1651
1663
pub ( super ) fn add_new_pending_payment < ES : Deref > (
1652
1664
& self , payment_hash : PaymentHash , recipient_onion : RecipientOnionFields , payment_id : PaymentId ,
1653
1665
keysend_preimage : Option < PaymentPreimage > , route : & Route , retry_strategy : Option < Retry > ,
1654
- payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1666
+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32 ,
1667
+ bolt12_invoice : Option < Bolt12Invoice >
1655
1668
) -> Result < Vec < [ u8 ; 32 ] > , PaymentSendFailure > where ES :: Target : EntropySource {
1656
1669
let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1657
1670
match pending_outbounds. entry ( payment_id) {
1658
1671
hash_map:: Entry :: Occupied ( _) => Err ( PaymentSendFailure :: DuplicatePayment ) ,
1659
1672
hash_map:: Entry :: Vacant ( entry) => {
1660
1673
let ( payment, onion_session_privs) = Self :: create_pending_payment (
1661
- payment_hash, recipient_onion, keysend_preimage, None , route, retry_strategy,
1674
+ payment_hash, recipient_onion, keysend_preimage, None , bolt12_invoice , route, retry_strategy,
1662
1675
payment_params, entropy_source, best_block_height
1663
1676
) ;
1664
1677
entry. insert ( payment) ;
@@ -1670,8 +1683,8 @@ impl OutboundPayments {
1670
1683
fn create_pending_payment < ES : Deref > (
1671
1684
payment_hash : PaymentHash , recipient_onion : RecipientOnionFields ,
1672
1685
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < InvoiceRequest > ,
1673
- route : & Route , retry_strategy : Option < Retry > , payment_params : Option < PaymentParameters > ,
1674
- entropy_source : & ES , best_block_height : u32
1686
+ bolt12_invoice : Option < Bolt12Invoice > , route : & Route , retry_strategy : Option < Retry > ,
1687
+ payment_params : Option < PaymentParameters > , entropy_source : & ES , best_block_height : u32
1675
1688
) -> ( PendingOutboundPayment , Vec < [ u8 ; 32 ] > )
1676
1689
where
1677
1690
ES :: Target : EntropySource ,
@@ -1693,6 +1706,7 @@ impl OutboundPayments {
1693
1706
payment_metadata : recipient_onion. payment_metadata ,
1694
1707
keysend_preimage,
1695
1708
invoice_request,
1709
+ bolt12_invoice,
1696
1710
custom_tlvs : recipient_onion. custom_tlvs ,
1697
1711
starting_block_height : best_block_height,
1698
1712
total_msat : route. get_total_amount ( ) ,
@@ -2310,6 +2324,7 @@ impl OutboundPayments {
2310
2324
payment_metadata: None , // only used for retries, and we'll never retry on startup
2311
2325
keysend_preimage: None , // only used for retries, and we'll never retry on startup
2312
2326
invoice_request: None , // only used for retries, and we'll never retry on startup
2327
+ bolt12_invoice: None , // only used for retries, and we'll never retry on startup! TODO(vincenzopalazzo): double check this
2313
2328
custom_tlvs: Vec :: new( ) , // only used for retries, and we'll never retry on startup
2314
2329
pending_amt_msat: path_amt,
2315
2330
pending_fee_msat: Some ( path_fee) ,
@@ -2399,6 +2414,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
2399
2414
( 10 , starting_block_height, required) ,
2400
2415
( 11 , remaining_max_total_routing_fee_msat, option) ,
2401
2416
( 13 , invoice_request, option) ,
2417
+ ( 15 , bolt12_invoice, option) ,
2402
2418
( not_written, retry_strategy, ( static_value, None ) ) ,
2403
2419
( not_written, attempts, ( static_value, PaymentAttempts :: new( ) ) ) ,
2404
2420
} ,
@@ -2516,7 +2532,7 @@ mod tests {
2516
2532
outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , RecipientOnionFields :: spontaneous_empty ( ) ,
2517
2533
PaymentId ( [ 0 ; 32 ] ) , None , & Route { paths : vec ! [ ] , route_params : None } ,
2518
2534
Some ( Retry :: Attempts ( 1 ) ) , Some ( expired_route_params. payment_params . clone ( ) ) ,
2519
- & & keys_manager, 0 ) . unwrap ( ) ;
2535
+ & & keys_manager, 0 , None ) . unwrap ( ) ;
2520
2536
outbound_payments. find_route_and_send_payment (
2521
2537
PaymentHash ( [ 0 ; 32 ] ) , PaymentId ( [ 0 ; 32 ] ) , expired_route_params, & & router, vec ! [ ] ,
2522
2538
& || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger, & pending_events,
@@ -2559,7 +2575,7 @@ mod tests {
2559
2575
outbound_payments. add_new_pending_payment ( PaymentHash ( [ 0 ; 32 ] ) , RecipientOnionFields :: spontaneous_empty ( ) ,
2560
2576
PaymentId ( [ 0 ; 32 ] ) , None , & Route { paths : vec ! [ ] , route_params : None } ,
2561
2577
Some ( Retry :: Attempts ( 1 ) ) , Some ( route_params. payment_params . clone ( ) ) ,
2562
- & & keys_manager, 0 ) . unwrap ( ) ;
2578
+ & & keys_manager, 0 , None ) . unwrap ( ) ;
2563
2579
outbound_payments. find_route_and_send_payment (
2564
2580
PaymentHash ( [ 0 ; 32 ] ) , PaymentId ( [ 0 ; 32 ] ) , route_params, & & router, vec ! [ ] ,
2565
2581
& || InFlightHtlcs :: new ( ) , & & keys_manager, & & keys_manager, 0 , & & logger, & pending_events,
0 commit comments