Skip to content

Commit 05e5072

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 beb3059 commit 05e5072

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

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>,
@@ -1650,7 +1655,7 @@ impl OutboundPayments {
16501655
match payment.get() {
16511656
PendingOutboundPayment::Retryable {
16521657
total_msat, keysend_preimage, payment_secret, payment_metadata,
1653-
custom_tlvs, pending_amt_msat, invoice_request, ..
1658+
custom_tlvs, pending_amt_msat, invoice_request, onion_total_msat, ..
16541659
} => {
16551660
const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
16561661
let retry_amt_msat = route.get_total_amount();
@@ -1670,7 +1675,7 @@ impl OutboundPayments {
16701675
payment_secret: *payment_secret,
16711676
payment_metadata: payment_metadata.clone(),
16721677
custom_tlvs: custom_tlvs.clone(),
1673-
total_mpp_amount_msat: *total_msat,
1678+
total_mpp_amount_msat: *onion_total_msat,
16741679
};
16751680
let keysend_preimage = *keysend_preimage;
16761681
let invoice_request = invoice_request.clone();
@@ -1986,6 +1991,7 @@ impl OutboundPayments {
19861991
custom_tlvs: recipient_onion.custom_tlvs,
19871992
starting_block_height: best_block_height,
19881993
total_msat: route.get_total_amount(),
1994+
onion_total_msat: recipient_onion.total_mpp_amount_msat,
19891995
remaining_max_total_routing_fee_msat:
19901996
route.route_params.as_ref().and_then(|p| p.max_total_routing_fee_msat),
19911997
};
@@ -2693,6 +2699,7 @@ impl OutboundPayments {
26932699
pending_amt_msat: path_amt,
26942700
pending_fee_msat: Some(path_fee),
26952701
total_msat: path_amt,
2702+
onion_total_msat: path_amt,
26962703
starting_block_height: best_block_height,
26972704
remaining_max_total_routing_fee_msat: None, // only used for retries, and we'll never retry on startup
26982705
}
@@ -2775,6 +2782,21 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
27752782
(9, custom_tlvs, optional_vec),
27762783
(10, starting_block_height, required),
27772784
(11, remaining_max_total_routing_fee_msat, option),
2785+
(12, onion_total_msat, (custom, u64,
2786+
// Once we get here, `total_msat` will have been read (or we'll fail to read)
2787+
|read_val: Option<u64>| Ok(read_val.unwrap_or(total_msat.0.unwrap())),
2788+
|us: &PendingOutboundPayment| {
2789+
match us {
2790+
PendingOutboundPayment::Retryable { total_msat, onion_total_msat, .. } => {
2791+
if total_msat != onion_total_msat {
2792+
Some(*onion_total_msat)
2793+
} else {
2794+
None
2795+
}
2796+
},
2797+
_ => unreachable!(),
2798+
}
2799+
})),
27782800
(13, invoice_request, option),
27792801
(15, bolt12_invoice, option),
27802802
(not_written, retry_strategy, (static_value, None)),

0 commit comments

Comments
 (0)