Skip to content

Commit 2b48770

Browse files
committed
Add total-MPP-value storage in pending payments
In some uses of LDK we need the ability to send HTLCs for only a portion of some larger MPP payment. This allows payers to make single payments which spend funds from multiple wallets, which may be important for ecash wallets holding funds in multiple mints or graduated wallets which hold funds across a trusted wallet and a self-custodial wallet. In the previous commits we moved the total-MPP-value we set in onions from being manually passed through onion-building to passing it via `RecipientOnionFields`. This introduced a subtle bug, though - payments which are retried will get a fresh `RecipientOnionFields` built from the data in `PendingOutboundPayment::Retryable`, losing any custom total-MPP-value settings and causing retries to fail. Here we fix this by storing the total-MPP-value directly in `PendingOutboundPayment::Retryable`.
1 parent 050d6ef commit 2b48770

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

lightning/src/ln/outbound_payment.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ pub(crate) enum PendingOutboundPayment {
133133
pending_fee_msat: Option<u64>,
134134
/// The total payment amount across all paths, used to verify that a retry is not overpaying.
135135
total_msat: u64,
136+
/// The total payment amount which is set in the onion.
137+
///
138+
/// This is generally equal to [`Self::Retryable::total_msat`] but may differ when making
139+
/// payments which are sent MPP from different sources.
140+
onion_total_msat: u64,
136141
/// Our best known block height at the time this payment was initiated.
137142
starting_block_height: u32,
138143
remaining_max_total_routing_fee_msat: Option<u64>,
@@ -1700,7 +1705,7 @@ impl OutboundPayments {
17001705
match payment.get() {
17011706
PendingOutboundPayment::Retryable {
17021707
total_msat, keysend_preimage, payment_secret, payment_metadata,
1703-
custom_tlvs, pending_amt_msat, invoice_request, ..
1708+
custom_tlvs, pending_amt_msat, invoice_request, onion_total_msat, ..
17041709
} => {
17051710
const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
17061711
let retry_amt_msat = route.get_total_amount();
@@ -1720,7 +1725,7 @@ impl OutboundPayments {
17201725
payment_secret: *payment_secret,
17211726
payment_metadata: payment_metadata.clone(),
17221727
custom_tlvs: custom_tlvs.clone(),
1723-
total_mpp_amount_msat: *total_msat,
1728+
total_mpp_amount_msat: *onion_total_msat,
17241729
};
17251730
let keysend_preimage = *keysend_preimage;
17261731
let invoice_request = invoice_request.clone();
@@ -2036,6 +2041,7 @@ impl OutboundPayments {
20362041
custom_tlvs: recipient_onion.custom_tlvs,
20372042
starting_block_height: best_block_height,
20382043
total_msat: route.get_total_amount(),
2044+
onion_total_msat: recipient_onion.total_mpp_amount_msat,
20392045
remaining_max_total_routing_fee_msat:
20402046
route.route_params.as_ref().and_then(|p| p.max_total_routing_fee_msat),
20412047
};
@@ -2743,6 +2749,7 @@ impl OutboundPayments {
27432749
pending_amt_msat: path_amt,
27442750
pending_fee_msat: Some(path_fee),
27452751
total_msat: path_amt,
2752+
onion_total_msat: path_amt,
27462753
starting_block_height: best_block_height,
27472754
remaining_max_total_routing_fee_msat: None, // only used for retries, and we'll never retry on startup
27482755
}
@@ -2825,6 +2832,21 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
28252832
(9, custom_tlvs, optional_vec),
28262833
(10, starting_block_height, required),
28272834
(11, remaining_max_total_routing_fee_msat, option),
2835+
(12, onion_total_msat, (custom, u64,
2836+
// Once we get here, `total_msat` will have been read (or we'll fail to read)
2837+
|read_val: Option<u64>| Ok(read_val.unwrap_or(total_msat.0.unwrap())),
2838+
|us: &PendingOutboundPayment| {
2839+
match us {
2840+
PendingOutboundPayment::Retryable { total_msat, onion_total_msat, .. } => {
2841+
if total_msat != onion_total_msat {
2842+
Some(*onion_total_msat)
2843+
} else {
2844+
None
2845+
}
2846+
},
2847+
_ => unreachable!(),
2848+
}
2849+
})),
28282850
(13, invoice_request, option),
28292851
(15, bolt12_invoice, option),
28302852
(not_written, retry_strategy, (static_value, None)),

0 commit comments

Comments
 (0)