Skip to content

Commit 6eaa047

Browse files
committed
Drop total_msat from individual ClaimableHTLCs
Now that we have `total_mpp_amount_msat` in the now-required `RecipientOnionFields` in `ClaimablePayment`s, the `total_msat` field in `ClaimableHTLC` is redundant. Given it was already awkward that we stored it in *each` `ClaimableHTLC` despite it being required to match in all of them, its good to drop it.
1 parent 816a1eb commit 6eaa047

File tree

1 file changed

+56
-67
lines changed

1 file changed

+56
-67
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,6 @@ struct ClaimableHTLC {
539539
/// The total value received for a payment (sum of all MPP parts if the payment is a MPP).
540540
/// Gets set to the amount reported when pushing [`Event::PaymentClaimable`].
541541
total_value_received: Option<u64>,
542-
/// The sender intended sum total of all MPP parts specified in the onion
543-
total_msat: u64,
544542
/// The extra fee our counterparty skimmed off the top of this HTLC.
545543
counterparty_skimmed_fee_msat: Option<u64>,
546544
}
@@ -1255,7 +1253,7 @@ impl ClaimablePayments {
12551253
})
12561254
.or_insert_with(|| {
12571255
let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect();
1258-
let sender_intended_value = payment.htlcs.first().map(|htlc| htlc.total_msat);
1256+
let sender_intended_value = payment.onion_fields.total_mpp_amount_msat;
12591257
// Pick an "arbitrary" channel to block RAAs on until the `PaymentSent`
12601258
// event is processed, specifically the last channel to get claimed.
12611259
let durable_preimage_channel = payment.htlcs.last().map_or(None, |htlc| {
@@ -1271,7 +1269,7 @@ impl ClaimablePayments {
12711269
payment_purpose: payment.purpose,
12721270
receiver_node_id,
12731271
htlcs,
1274-
sender_intended_value,
1272+
sender_intended_value: Some(sender_intended_value),
12751273
onion_fields: payment.onion_fields,
12761274
payment_id: Some(payment_id),
12771275
durable_preimage_channel,
@@ -7885,11 +7883,6 @@ impl<
78857883
sender_intended_value: outgoing_amt_msat,
78867884
timer_ticks: 0,
78877885
total_value_received: None,
7888-
total_msat: if let Some(data) = &payment_data {
7889-
data.total_msat
7890-
} else {
7891-
outgoing_amt_msat
7892-
},
78937886
cltv_expiry,
78947887
onion_payload,
78957888
counterparty_skimmed_fee_msat: skimmed_fee_msat,
@@ -7970,27 +7963,25 @@ impl<
79707963
if onions_compatible.is_err() {
79717964
fail_htlc!(claimable_htlc, payment_hash);
79727965
}
7973-
let mut total_value = claimable_htlc.sender_intended_value;
7966+
let mut total_intended_recvd_value =
7967+
claimable_htlc.sender_intended_value;
79747968
let mut earliest_expiry = claimable_htlc.cltv_expiry;
79757969
for htlc in claimable_payment.htlcs.iter() {
7976-
total_value += htlc.sender_intended_value;
7970+
total_intended_recvd_value += htlc.sender_intended_value;
79777971
earliest_expiry = cmp::min(earliest_expiry, htlc.cltv_expiry);
7978-
if htlc.total_msat != claimable_htlc.total_msat {
7979-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
7980-
&payment_hash, claimable_htlc.total_msat, htlc.total_msat);
7981-
total_value = msgs::MAX_VALUE_MSAT;
7982-
}
7983-
if total_value >= msgs::MAX_VALUE_MSAT { break; }
7972+
if total_intended_recvd_value >= msgs::MAX_VALUE_MSAT { break; }
79847973
}
7974+
let total_mpp_value =
7975+
claimable_payment.onion_fields.total_mpp_amount_msat;
79857976
// The condition determining whether an MPP is complete must
79867977
// match exactly the condition used in `timer_tick_occurred`
7987-
if total_value >= msgs::MAX_VALUE_MSAT {
7978+
if total_intended_recvd_value >= msgs::MAX_VALUE_MSAT {
79887979
fail_htlc!(claimable_htlc, payment_hash);
7989-
} else if total_value - claimable_htlc.sender_intended_value >= claimable_htlc.total_msat {
7980+
} else if total_intended_recvd_value - claimable_htlc.sender_intended_value >= total_mpp_value {
79907981
log_trace!(self.logger, "Failing HTLC with payment_hash {} as payment is already claimable",
79917982
&payment_hash);
79927983
fail_htlc!(claimable_htlc, payment_hash);
7993-
} else if total_value >= claimable_htlc.total_msat {
7984+
} else if total_intended_recvd_value >= total_mpp_value {
79947985
#[allow(unused_assignments)] {
79957986
committed_to_claimable = true;
79967987
}
@@ -8001,8 +7992,8 @@ impl<
80017992
.for_each(|htlc| htlc.total_value_received = Some(amount_msat));
80027993
let counterparty_skimmed_fee_msat = claimable_payment.htlcs.iter()
80037994
.map(|htlc| htlc.counterparty_skimmed_fee_msat.unwrap_or(0)).sum();
8004-
debug_assert!(total_value.saturating_sub(amount_msat) <=
8005-
counterparty_skimmed_fee_msat);
7995+
debug_assert!(total_intended_recvd_value.saturating_sub(amount_msat)
7996+
<= counterparty_skimmed_fee_msat);
80067997
claimable_payment.htlcs.sort();
80077998
let payment_id =
80087999
claimable_payment.inbound_payment_id(&self.inbound_payment_id_secret);
@@ -8497,9 +8488,10 @@ impl<
84978488
// In this case we're not going to handle any timeouts of the parts here.
84988489
// This condition determining whether the MPP is complete here must match
84998490
// exactly the condition used in `process_pending_htlc_forwards`.
8500-
let htlc_total_msat =
8491+
let total_intended_recvd_value =
85018492
payment.htlcs.iter().map(|h| h.sender_intended_value).sum();
8502-
if payment.htlcs[0].total_msat <= htlc_total_msat {
8493+
let total_mpp_value = payment.onion_fields.total_mpp_amount_msat;
8494+
if total_mpp_value <= total_intended_recvd_value {
85038495
return true;
85048496
} else if payment.htlcs.iter_mut().any(|htlc| {
85058497
htlc.timer_ticks += 1;
@@ -8914,20 +8906,11 @@ impl<
89148906
// amount we told the user in the last `PaymentClaimable`. We also do a sanity-check that
89158907
// the MPP parts all have the same `total_msat`.
89168908
let mut claimable_amt_msat = 0;
8917-
let mut prev_total_msat = None;
89188909
let mut expected_amt_msat = None;
89198910
let mut valid_mpp = true;
89208911
let mut errs = Vec::new();
89218912
let per_peer_state = self.per_peer_state.read().unwrap();
89228913
for htlc in sources.iter() {
8923-
if prev_total_msat.is_some() && prev_total_msat != Some(htlc.total_msat) {
8924-
log_error!(self.logger, "Somehow ended up with an MPP payment with different expected total amounts - this should not be reachable!");
8925-
debug_assert!(false);
8926-
valid_mpp = false;
8927-
break;
8928-
}
8929-
prev_total_msat = Some(htlc.total_msat);
8930-
89318914
if expected_amt_msat.is_some() && expected_amt_msat != htlc.total_value_received {
89328915
log_error!(self.logger, "Somehow ended up with an MPP payment with different received total amounts - this should not be reachable!");
89338916
debug_assert!(false);
@@ -16938,28 +16921,28 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
1693816921
(13, trampoline_shared_secret, option),
1693916922
});
1694016923

16941-
impl Writeable for ClaimableHTLC {
16942-
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
16943-
let (payment_data, keysend_preimage) = match &self.onion_payload {
16944-
OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None),
16945-
OnionPayload::Spontaneous(preimage) => (None, Some(preimage)),
16946-
};
16947-
write_tlv_fields!(writer, {
16948-
(0, self.prev_hop, required),
16949-
(1, self.total_msat, required),
16950-
(2, self.value, required),
16951-
(3, self.sender_intended_value, required),
16952-
(4, payment_data, option),
16953-
(5, self.total_value_received, option),
16954-
(6, self.cltv_expiry, required),
16955-
(8, keysend_preimage, option),
16956-
(10, self.counterparty_skimmed_fee_msat, option),
16957-
});
16958-
Ok(())
16959-
}
16924+
fn write_claimable_htlc<W: Writer>(
16925+
htlc: &ClaimableHTLC, total_mpp_value_msat: u64, writer: &mut W,
16926+
) -> Result<(), io::Error> {
16927+
let (payment_data, keysend_preimage) = match &htlc.onion_payload {
16928+
OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None),
16929+
OnionPayload::Spontaneous(preimage) => (None, Some(preimage)),
16930+
};
16931+
write_tlv_fields!(writer, {
16932+
(0, htlc.prev_hop, required),
16933+
(1, total_mpp_value_msat, required),
16934+
(2, htlc.value, required),
16935+
(3, htlc.sender_intended_value, required),
16936+
(4, payment_data, option),
16937+
(5, htlc.total_value_received, option),
16938+
(6, htlc.cltv_expiry, required),
16939+
(8, keysend_preimage, option),
16940+
(10, htlc.counterparty_skimmed_fee_msat, option),
16941+
});
16942+
Ok(())
1696016943
}
1696116944

16962-
impl Readable for ClaimableHTLC {
16945+
impl Readable for (ClaimableHTLC, u64) {
1696316946
#[rustfmt::skip]
1696416947
fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
1696516948
_init_and_read_len_prefixed_tlv_fields!(reader, {
@@ -16995,17 +16978,16 @@ impl Readable for ClaimableHTLC {
1699516978
OnionPayload::Invoice { _legacy_hop_data: payment_data }
1699616979
},
1699716980
};
16998-
Ok(Self {
16981+
Ok((ClaimableHTLC {
1699916982
prev_hop: prev_hop.0.unwrap(),
1700016983
timer_ticks: 0,
1700116984
value,
1700216985
sender_intended_value: sender_intended_value.unwrap_or(value),
1700316986
total_value_received,
17004-
total_msat: total_msat.unwrap(),
1700516987
onion_payload,
1700616988
cltv_expiry: cltv_expiry.0.unwrap(),
1700716989
counterparty_skimmed_fee_msat,
17008-
})
16990+
}, total_msat.unwrap()))
1700916991
}
1701016992
}
1701116993

@@ -17271,7 +17253,7 @@ impl<
1727117253
payment_hash.write(writer)?;
1727217254
(payment.htlcs.len() as u64).write(writer)?;
1727317255
for htlc in payment.htlcs.iter() {
17274-
htlc.write(writer)?;
17256+
write_claimable_htlc(&htlc, payment.onion_fields.total_mpp_amount_msat, writer)?;
1727517257
}
1727617258
htlc_purposes.push(&payment.purpose);
1727717259
htlc_onion_fields.push(Some(&payment.onion_fields));
@@ -17611,10 +17593,20 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1761117593
previous_hops_len as usize,
1761217594
MAX_ALLOC_SIZE / mem::size_of::<ClaimableHTLC>(),
1761317595
));
17596+
let mut total_mpp_value_msat = None;
1761417597
for _ in 0..previous_hops_len {
17615-
previous_hops.push(<ClaimableHTLC as Readable>::read(reader)?);
17598+
let (htlc, total_mpp_value_msat_read) =
17599+
<(ClaimableHTLC, u64) as Readable>::read(reader)?;
17600+
if total_mpp_value_msat.is_some()
17601+
&& total_mpp_value_msat != Some(total_mpp_value_msat_read)
17602+
{
17603+
return Err(DecodeError::InvalidValue);
17604+
}
17605+
total_mpp_value_msat = Some(total_mpp_value_msat_read);
17606+
previous_hops.push(htlc);
1761617607
}
17617-
claimable_htlcs_list.push((payment_hash, previous_hops));
17608+
let total_mpp_value_msat = total_mpp_value_msat.ok_or(DecodeError::InvalidValue)?;
17609+
claimable_htlcs_list.push((payment_hash, previous_hops, total_mpp_value_msat));
1761817610
}
1761917611

1762017612
let peer_count: u64 = Readable::read(reader)?;
@@ -17793,19 +17785,17 @@ impl<'a, ES: EntropySource, SP: SignerProvider, L: Logger>
1779317785
if onion_fields.len() != claimable_htlcs_list.len() {
1779417786
return Err(DecodeError::InvalidValue);
1779517787
}
17796-
for (purpose, (onion, (payment_hash, htlcs))) in purposes
17788+
for (purpose, (onion, (payment_hash, htlcs, total_mpp_value_msat))) in purposes
1779717789
.into_iter()
1779817790
.zip(onion_fields.into_iter().zip(claimable_htlcs_list.into_iter()))
1779917791
{
17800-
let htlcs_total_msat =
17801-
htlcs.first().ok_or(DecodeError::InvalidValue)?.total_msat;
1780217792
let onion_fields = if let Some(mut onion) = onion {
1780317793
if onion.0.total_mpp_amount_msat != 0
17804-
&& onion.0.total_mpp_amount_msat != htlcs_total_msat
17794+
&& onion.0.total_mpp_amount_msat != total_mpp_value_msat
1780517795
{
1780617796
return Err(DecodeError::InvalidValue);
1780717797
}
17808-
onion.0.total_mpp_amount_msat = htlcs_total_msat;
17798+
onion.0.total_mpp_amount_msat = total_mpp_value_msat;
1780917799
onion.0
1781017800
} else {
1781117801
return Err(DecodeError::InvalidValue);
@@ -19755,16 +19745,15 @@ impl<
1975519745
let payment_id =
1975619746
payment.inbound_payment_id(&inbound_payment_id_secret.unwrap());
1975719747
let htlcs = payment.htlcs.iter().map(events::ClaimedHTLC::from).collect();
19758-
let sender_intended_total_msat =
19759-
payment.htlcs.first().map(|htlc| htlc.total_msat);
19748+
let sender_intended_total_msat = payment.onion_fields.total_mpp_amount_msat;
1976019749
pending_events.push_back((
1976119750
events::Event::PaymentClaimed {
1976219751
receiver_node_id,
1976319752
payment_hash,
1976419753
purpose: payment.purpose,
1976519754
amount_msat: claimable_amt_msat,
1976619755
htlcs,
19767-
sender_intended_total_msat,
19756+
sender_intended_total_msat: Some(sender_intended_total_msat),
1976819757
onion_fields: Some(payment.onion_fields),
1976919758
payment_id: Some(payment_id),
1977019759
},

0 commit comments

Comments
 (0)