Skip to content

Commit a4d4989

Browse files
move the bolt12 invoice inside HTLCSource::OutboundRoute
Matt noted during the last round of review the following: >Oof. Sorry I missed this until now. This is not, in fact, "only used for retries", we use it on claims only, in fact. If a user is relying on the event field for PoP, what this can mean is that we can initiate a send, restart with a stale ChannelManager, notice the payment is pending, then when it claims fail to provide the invoice (only the preimage) to the payer. >In practice, to fix this, we'll need to include the PaidBolt12Invoice in the HTLCSource::OutboundRoute, I believe. This commit is trying to store the PaidBolt12Invoice inside the HTLCSource::OutboundRoute, but this is not enough because we have to store the invoice also inside the PendingOutboundPayment. Link: #3714 Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent 7b45811 commit a4d4989

File tree

4 files changed

+44
-22
lines changed

4 files changed

+44
-22
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11701,6 +11701,7 @@ mod tests {
1170111701
session_priv: SecretKey::from_slice(&<Vec<u8>>::from_hex("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
1170211702
first_hop_htlc_msat: 548,
1170311703
payment_id: PaymentId([42; 32]),
11704+
bolt12_invoice: None,
1170411705
},
1170511706
skimmed_fee_msat: None,
1170611707
blinding_point: None,
@@ -12079,6 +12080,7 @@ mod tests {
1207912080
session_priv: test_utils::privkey(42),
1208012081
first_hop_htlc_msat: 0,
1208112082
payment_id: PaymentId([42; 32]),
12083+
bolt12_invoice: None,
1208212084
};
1208312085
let dummy_outbound_output = OutboundHTLCOutput {
1208412086
htlc_id: 0,

lightning/src/ln/channelmanager.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use bitcoin::{secp256k1, Sequence};
3434
#[cfg(splicing)]
3535
use bitcoin::{TxIn, Weight};
3636

37-
use crate::events::FundingInfo;
37+
use crate::events::{FundingInfo, PaidBolt12Invoice};
3838
use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext};
3939
use crate::blinded_path::NodeIdLookUp;
4040
use crate::blinded_path::message::{BlindedMessagePath, MessageForwardNode};
@@ -666,6 +666,8 @@ mod fuzzy_channelmanager {
666666
/// doing a double-pass on route when we get a failure back
667667
first_hop_htlc_msat: u64,
668668
payment_id: PaymentId,
669+
// TODO(vincenzopalazzo): add the documentation for this field
670+
bolt12_invoice: Option<PaidBolt12Invoice>,
669671
},
670672
}
671673

@@ -703,7 +705,8 @@ impl core::hash::Hash for HTLCSource {
703705
0u8.hash(hasher);
704706
prev_hop_data.hash(hasher);
705707
},
706-
HTLCSource::OutboundRoute { path, session_priv, payment_id, first_hop_htlc_msat } => {
708+
// FIXME(vincenzopalazzo): we can ignore the bolt12_invoice here?
709+
HTLCSource::OutboundRoute { path, session_priv, payment_id, first_hop_htlc_msat, .. } => {
707710
1u8.hash(hasher);
708711
path.hash(hasher);
709712
session_priv[..].hash(hasher);
@@ -721,6 +724,7 @@ impl HTLCSource {
721724
session_priv: SecretKey::from_slice(&[1; 32]).unwrap(),
722725
first_hop_htlc_msat: 0,
723726
payment_id: PaymentId([2; 32]),
727+
bolt12_invoice: None,
724728
}
725729
}
726730

@@ -4634,14 +4638,14 @@ where
46344638
let _lck = self.total_consistency_lock.read().unwrap();
46354639
self.send_payment_along_path(SendAlongPathArgs {
46364640
path, payment_hash, recipient_onion: &recipient_onion, total_value,
4637-
cur_height, payment_id, keysend_preimage, invoice_request: None, session_priv_bytes
4641+
cur_height, payment_id, keysend_preimage, invoice_request: None, bolt12_invoice: None, session_priv_bytes
46384642
})
46394643
}
46404644

46414645
fn send_payment_along_path(&self, args: SendAlongPathArgs) -> Result<(), APIError> {
46424646
let SendAlongPathArgs {
46434647
path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage,
4644-
invoice_request, session_priv_bytes
4648+
invoice_request, bolt12_invoice, session_priv_bytes
46454649
} = args;
46464650
// The top-level caller should hold the total_consistency_lock read lock.
46474651
debug_assert!(self.total_consistency_lock.try_write().is_err());
@@ -4691,6 +4695,7 @@ where
46914695
session_priv: session_priv.clone(),
46924696
first_hop_htlc_msat: htlc_msat,
46934697
payment_id,
4698+
bolt12_invoice: bolt12_invoice.cloned(),
46944699
}, onion_packet, None, &self.fee_estimator, &&logger);
46954700
match break_channel_entry!(self, peer_state, send_res, chan_entry) {
46964701
Some(monitor_update) => {
@@ -7459,15 +7464,15 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
74597464
next_channel_outpoint: OutPoint, next_channel_id: ChannelId, next_user_channel_id: Option<u128>,
74607465
) {
74617466
match source {
7462-
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
7467+
HTLCSource::OutboundRoute { session_priv, payment_id, path, bolt12_invoice, .. } => {
74637468
debug_assert!(self.background_events_processed_since_startup.load(Ordering::Acquire),
74647469
"We don't support claim_htlc claims during startup - monitors may not be available yet");
74657470
debug_assert_eq!(next_channel_counterparty_node_id, path.hops[0].pubkey);
74667471
let ev_completion_action = EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
74677472
channel_funding_outpoint: next_channel_outpoint, channel_id: next_channel_id,
74687473
counterparty_node_id: path.hops[0].pubkey,
74697474
};
7470-
self.pending_outbound_payments.claim_htlc(payment_id, payment_preimage,
7475+
self.pending_outbound_payments.claim_htlc(payment_id, payment_preimage, bolt12_invoice,
74717476
session_priv, path, from_onchain, ev_completion_action, &self.pending_events,
74727477
&self.logger);
74737478
},
@@ -13144,13 +13149,15 @@ impl Readable for HTLCSource {
1314413149
let mut payment_id = None;
1314513150
let mut payment_params: Option<PaymentParameters> = None;
1314613151
let mut blinded_tail: Option<BlindedTail> = None;
13152+
let mut bolt12_invoice: Option<PaidBolt12Invoice> = None;
1314713153
read_tlv_fields!(reader, {
1314813154
(0, session_priv, required),
1314913155
(1, payment_id, option),
1315013156
(2, first_hop_htlc_msat, required),
1315113157
(4, path_hops, required_vec),
1315213158
(5, payment_params, (option: ReadableArgs, 0)),
1315313159
(6, blinded_tail, option),
13160+
(7, bolt12_invoice, option),
1315413161
});
1315513162
if payment_id.is_none() {
1315613163
// For backwards compat, if there was no payment_id written, use the session_priv bytes
@@ -13173,6 +13180,7 @@ impl Readable for HTLCSource {
1317313180
first_hop_htlc_msat,
1317413181
path,
1317513182
payment_id: payment_id.unwrap(),
13183+
bolt12_invoice,
1317613184
})
1317713185
}
1317813186
1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
@@ -13184,7 +13192,7 @@ impl Readable for HTLCSource {
1318413192
impl Writeable for HTLCSource {
1318513193
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), crate::io::Error> {
1318613194
match self {
13187-
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id } => {
13195+
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, bolt12_invoice } => {
1318813196
0u8.write(writer)?;
1318913197
let payment_id_opt = Some(payment_id);
1319013198
write_tlv_fields!(writer, {
@@ -13195,6 +13203,7 @@ impl Writeable for HTLCSource {
1319513203
(4, path.hops, required_vec),
1319613204
(5, None::<PaymentParameters>, option), // payment_params in LDK versions prior to 0.0.115
1319713205
(6, path.blinded_tail, option),
13206+
(7, bolt12_invoice, option),
1319813207
});
1319913208
}
1320013209
HTLCSource::PreviousHopData(ref field) => {
@@ -14381,7 +14390,7 @@ where
1438114390
} else { true }
1438214391
});
1438314392
},
14384-
HTLCSource::OutboundRoute { payment_id, session_priv, path, .. } => {
14393+
HTLCSource::OutboundRoute { payment_id, session_priv, path, bolt12_invoice, .. } => {
1438514394
if let Some(preimage) = preimage_opt {
1438614395
let pending_events = Mutex::new(pending_events_read);
1438714396
// Note that we set `from_onchain` to "false" here,
@@ -14398,7 +14407,7 @@ where
1439814407
channel_id: monitor.channel_id(),
1439914408
counterparty_node_id: path.hops[0].pubkey,
1440014409
};
14401-
pending_outbounds.claim_htlc(payment_id, preimage, session_priv,
14410+
pending_outbounds.claim_htlc(payment_id, preimage, bolt12_invoice, session_priv,
1440214411
path, false, compl_action, &pending_events, &&logger);
1440314412
pending_events_read = pending_events.into_inner().unwrap();
1440414413
}

lightning/src/ln/onion_utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,6 +2904,7 @@ mod tests {
29042904
session_priv: get_test_session_key(),
29052905
first_hop_htlc_msat: 0,
29062906
payment_id: PaymentId([1; 32]),
2907+
bolt12_invoice: None,
29072908
};
29082909

29092910
process_onion_failure(&ctx_full, &logger, &htlc_source, onion_error)
@@ -3029,6 +3030,7 @@ mod tests {
30293030
session_priv,
30303031
first_hop_htlc_msat: dummy_amt_msat,
30313032
payment_id: PaymentId([1; 32]),
3033+
bolt12_invoice: None,
30323034
};
30333035

30343036
{
@@ -3221,6 +3223,7 @@ mod tests {
32213223
session_priv: session_key,
32223224
first_hop_htlc_msat: 0,
32233225
payment_id: PaymentId([1; 32]),
3226+
bolt12_invoice: None,
32243227
};
32253228

32263229
// Iterate over all possible failure positions and check that the cases that can be attributed are.
@@ -3329,6 +3332,7 @@ mod tests {
33293332
session_priv: get_test_session_key(),
33303333
first_hop_htlc_msat: 0,
33313334
payment_id: PaymentId([1; 32]),
3335+
bolt12_invoice: None,
33323336
};
33333337

33343338
let decrypted_failure = process_onion_failure(&ctx_full, &logger, &htlc_source, packet);

lightning/src/ln/outbound_payment.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ impl PendingOutboundPayment {
163163
_ => None,
164164
}
165165
}
166+
166167
fn increment_attempts(&mut self) {
167168
if let PendingOutboundPayment::Retryable { attempts, .. } = self {
168169
attempts.count += 1;
@@ -797,6 +798,7 @@ pub(super) struct SendAlongPathArgs<'a> {
797798
pub payment_id: PaymentId,
798799
pub keysend_preimage: &'a Option<PaymentPreimage>,
799800
pub invoice_request: Option<&'a InvoiceRequest>,
801+
pub bolt12_invoice: Option<&'a PaidBolt12Invoice>,
800802
pub session_priv_bytes: [u8; 32],
801803
}
802804

@@ -1042,7 +1044,8 @@ impl OutboundPayments {
10421044
hash_map::Entry::Occupied(entry) => match entry.get() {
10431045
PendingOutboundPayment::InvoiceReceived { .. } => {
10441046
let (retryable_payment, onion_session_privs) = Self::create_pending_payment(
1045-
payment_hash, recipient_onion.clone(), keysend_preimage, None, Some(bolt12_invoice), &route,
1047+
// FIXME: remove the bolt12_invoice here! we need to clean up this part!
1048+
payment_hash, recipient_onion.clone(), keysend_preimage, None, Some(bolt12_invoice.clone()), &route,
10461049
Some(retry_strategy), payment_params, entropy_source, best_block_height,
10471050
);
10481051
*entry.into_mut() = retryable_payment;
@@ -1053,7 +1056,8 @@ impl OutboundPayments {
10531056
invoice_request
10541057
} else { unreachable!() };
10551058
let (retryable_payment, onion_session_privs) = Self::create_pending_payment(
1056-
payment_hash, recipient_onion.clone(), keysend_preimage, Some(invreq), Some(bolt12_invoice), &route,
1059+
// FIXME: We do not need anymore the bolt12_invoice here! we need to clean up this part!
1060+
payment_hash, recipient_onion.clone(), keysend_preimage, Some(invreq), Some(bolt12_invoice.clone()), &route,
10571061
Some(retry_strategy), payment_params, entropy_source, best_block_height
10581062
);
10591063
outbounds.insert(payment_id, retryable_payment);
@@ -1066,7 +1070,7 @@ impl OutboundPayments {
10661070
core::mem::drop(outbounds);
10671071

10681072
let result = self.pay_route_internal(
1069-
&route, payment_hash, &recipient_onion, keysend_preimage, invoice_request, payment_id,
1073+
&route, payment_hash, &recipient_onion, keysend_preimage, invoice_request, Some(bolt12_invoice), payment_id,
10701074
Some(route_params.final_value_msat), &onion_session_privs, node_signer, best_block_height,
10711075
&send_payment_along_path
10721076
);
@@ -1359,7 +1363,7 @@ impl OutboundPayments {
13591363
})?;
13601364

13611365
let res = self.pay_route_internal(&route, payment_hash, &recipient_onion,
1362-
keysend_preimage, None, payment_id, None, &onion_session_privs, node_signer,
1366+
keysend_preimage, None, None, payment_id, None, &onion_session_privs, node_signer,
13631367
best_block_height, &send_payment_along_path);
13641368
log_info!(logger, "Sending payment with id {} and hash {} returned {:?}",
13651369
payment_id, payment_hash, res);
@@ -1437,7 +1441,7 @@ impl OutboundPayments {
14371441
}
14381442
}
14391443
}
1440-
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request) = {
1444+
let (total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request, bolt12_invoice) = {
14411445
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
14421446
match outbounds.entry(payment_id) {
14431447
hash_map::Entry::Occupied(mut payment) => {
@@ -1479,8 +1483,9 @@ impl OutboundPayments {
14791483
}
14801484

14811485
payment.get_mut().increment_attempts();
1486+
let bolt12_invoice = payment.get().bolt12_invoice();
14821487

1483-
(total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request)
1488+
(total_msat, recipient_onion, keysend_preimage, onion_session_privs, invoice_request, bolt12_invoice.cloned())
14841489
},
14851490
PendingOutboundPayment::Legacy { .. } => {
14861491
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
@@ -1520,7 +1525,7 @@ impl OutboundPayments {
15201525
}
15211526
};
15221527
let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, keysend_preimage,
1523-
invoice_request.as_ref(), payment_id, Some(total_msat), &onion_session_privs, node_signer,
1528+
invoice_request.as_ref(), bolt12_invoice, payment_id, Some(total_msat), &onion_session_privs, node_signer,
15241529
best_block_height, &send_payment_along_path);
15251530
log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res);
15261531
if let Err(e) = res {
@@ -1673,7 +1678,7 @@ impl OutboundPayments {
16731678

16741679
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
16751680
match self.pay_route_internal(&route, payment_hash, &recipient_onion_fields,
1676-
None, None, payment_id, None, &onion_session_privs, node_signer, best_block_height,
1681+
None, None, None, payment_id, None, &onion_session_privs, node_signer, best_block_height,
16771682
&send_payment_along_path
16781683
) {
16791684
Ok(()) => Ok((payment_hash, payment_id)),
@@ -1865,7 +1870,7 @@ impl OutboundPayments {
18651870

18661871
fn pay_route_internal<NS: Deref, F>(
18671872
&self, route: &Route, payment_hash: PaymentHash, recipient_onion: &RecipientOnionFields,
1868-
keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<&InvoiceRequest>,
1873+
keysend_preimage: Option<PaymentPreimage>, invoice_request: Option<&InvoiceRequest>, bolt12_invoice: Option<PaidBolt12Invoice>,
18691874
payment_id: PaymentId, recv_value_msat: Option<u64>, onion_session_privs: &Vec<[u8; 32]>,
18701875
node_signer: &NS, best_block_height: u32, send_payment_along_path: &F
18711876
) -> Result<(), PaymentSendFailure>
@@ -1921,6 +1926,7 @@ impl OutboundPayments {
19211926
let path_res = send_payment_along_path(SendAlongPathArgs {
19221927
path: &path, payment_hash: &payment_hash, recipient_onion, total_value,
19231928
cur_height, payment_id, keysend_preimage: &keysend_preimage, invoice_request,
1929+
bolt12_invoice: bolt12_invoice.as_ref(),
19241930
session_priv_bytes: *session_priv_bytes
19251931
});
19261932
results.push(path_res);
@@ -1987,7 +1993,7 @@ impl OutboundPayments {
19871993
F: Fn(SendAlongPathArgs) -> Result<(), APIError>,
19881994
{
19891995
self.pay_route_internal(route, payment_hash, &recipient_onion,
1990-
keysend_preimage, None, payment_id, recv_value_msat, &onion_session_privs,
1996+
keysend_preimage, None, None, payment_id, recv_value_msat, &onion_session_privs,
19911997
node_signer, best_block_height, &send_payment_along_path)
19921998
.map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e })
19931999
}
@@ -2008,8 +2014,8 @@ impl OutboundPayments {
20082014
}
20092015

20102016
pub(super) fn claim_htlc<L: Deref>(
2011-
&self, payment_id: PaymentId, payment_preimage: PaymentPreimage, session_priv: SecretKey,
2012-
path: Path, from_onchain: bool, ev_completion_action: EventCompletionAction,
2017+
&self, payment_id: PaymentId, payment_preimage: PaymentPreimage, bolt12_invoice: Option<PaidBolt12Invoice>,
2018+
session_priv: SecretKey, path: Path, from_onchain: bool, ev_completion_action: EventCompletionAction,
20132019
pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>,
20142020
logger: &L,
20152021
) where L::Target: Logger {
@@ -2029,7 +2035,7 @@ impl OutboundPayments {
20292035
payment_hash,
20302036
amount_msat,
20312037
fee_paid_msat,
2032-
bolt12_invoice: payment.get().bolt12_invoice().cloned(),
2038+
bolt12_invoice: bolt12_invoice.clone(),
20332039
}, Some(ev_completion_action.clone())));
20342040
payment.get_mut().mark_fulfilled();
20352041
}
@@ -2061,6 +2067,7 @@ impl OutboundPayments {
20612067
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
20622068
let mut pending_events = pending_events.lock().unwrap();
20632069
for source in sources {
2070+
// TODO(vincenzopalazzo): This should contain the paid bolt12 invoice.
20642071
if let HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } = source {
20652072
let mut session_priv_bytes = [0; 32];
20662073
session_priv_bytes.copy_from_slice(&session_priv[..]);

0 commit comments

Comments
 (0)