Skip to content

Commit 0c7bab6

Browse files
committed
Require all HTLC success states to hold their corresponding preimage
This allows us to DRY the code that calculates the `value_to_self_msat_offset` in `ChannelContext::build_commitment_stats`. HTLC success states have held their corresponding preimage since 0.0.105, and the release notes of 0.1 already require users running 0.0.123 and earlier to resolve their HTLCs before upgrading to 0.1. So this change is fully compatible with existing upgrade paths to the yet-to-be-shipped 0.2 release.
1 parent 793d4d2 commit 0c7bab6

File tree

1 file changed

+30
-26
lines changed

1 file changed

+30
-26
lines changed

lightning/src/ln/channel.rs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,12 @@ impl OutboundHTLCState {
362362

363363
fn preimage(&self) -> Option<PaymentPreimage> {
364364
match self {
365-
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(p)) |
366-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(p)) |
367-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(p)) => p.as_ref().copied(),
365+
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(preimage)) |
366+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(preimage)) |
367+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(preimage)) => {
368+
debug_assert!(preimage.is_some());
369+
*preimage
370+
},
368371
_ => None,
369372
}
370373
}
@@ -373,7 +376,10 @@ impl OutboundHTLCState {
373376
#[derive(Clone)]
374377
#[cfg_attr(test, derive(Debug, PartialEq))]
375378
enum OutboundHTLCOutcome {
376-
/// LDK version 0.0.105+ will always fill in the preimage here.
379+
/// Except briefly during deserialization and state transitions between success states,
380+
/// we require all success states to hold their corresponding preimage.
381+
/// We started always filling in the preimages here in 0.0.105, and the requirement
382+
/// that the preimages always be filled in was added in 0.2.
377383
Success(Option<PaymentPreimage>),
378384
Failure(HTLCFailReason),
379385
}
@@ -3807,7 +3813,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38073813
}
38083814
remote_htlc_total_msat += htlc.amount_msat;
38093815
} else {
3810-
if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_preimage)) = htlc.state {
3816+
if htlc.state.preimage().is_some() {
38113817
value_to_self_msat_offset += htlc.amount_msat as i64;
38123818
}
38133819
}
@@ -3820,10 +3826,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38203826
}
38213827
local_htlc_total_msat += htlc.amount_msat;
38223828
} else {
3823-
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) |
3824-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) |
3825-
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(_))
3826-
= htlc.state {
3829+
if htlc.state.preimage().is_some() {
38273830
value_to_self_msat_offset -= htlc.amount_msat as i64;
38283831
}
38293832
}
@@ -5735,6 +5738,7 @@ impl<SP: Deref> FundedChannel<SP> where
57355738
#[inline]
57365739
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentPreimage>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
57375740
assert!(!(check_preimage.is_some() && fail_reason.is_some()), "cannot fail while we have a preimage");
5741+
assert!(!(check_preimage.is_none() && fail_reason.is_none()), "success states must hold their corresponding preimage");
57385742
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
57395743
if htlc.htlc_id == htlc_id {
57405744
let outcome = match check_preimage {
@@ -10483,6 +10487,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1048310487
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
1048410488
3u8.write(writer)?;
1048510489
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10490+
debug_assert!(preimage.is_some(), "success states must hold their corresponding preimage");
1048610491
preimages.push(preimage);
1048710492
}
1048810493
let reason: Option<&HTLCFailReason> = outcome.into();
@@ -10491,6 +10496,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1049110496
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
1049210497
4u8.write(writer)?;
1049310498
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10499+
debug_assert!(preimage.is_some(), "success states must hold their corresponding preimage");
1049410500
preimages.push(preimage);
1049510501
}
1049610502
let reason: Option<&HTLCFailReason> = outcome.into();
@@ -10984,7 +10990,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1098410990
// only, so we default to that if none was written.
1098510991
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
1098610992
let mut channel_creation_height = 0u32;
10987-
let mut preimages_opt: Option<Vec<Option<PaymentPreimage>>> = None;
10993+
let mut preimages: Vec<Option<PaymentPreimage>> = Vec::new();
1098810994

1098910995
// If we read an old Channel, for simplicity we just treat it as "we never sent an
1099010996
// AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine.
@@ -11036,7 +11042,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1103611042
(10, monitor_pending_update_adds, option), // Added in 0.0.122
1103711043
(11, monitor_pending_finalized_fulfills, optional_vec),
1103811044
(13, channel_creation_height, required),
11039-
(15, preimages_opt, optional_vec),
11045+
(15, preimages, required_vec), // The preimages transitioned from optional to required in 0.2
1104011046
(17, announcement_sigs_state, required),
1104111047
(19, latest_inbound_scid_alias, option),
1104211048
(21, outbound_scid_alias, required),
@@ -11063,23 +11069,21 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1106311069

1106411070
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
1106511071

11066-
if let Some(preimages) = preimages_opt {
11067-
let mut iter = preimages.into_iter();
11068-
for htlc in pending_outbound_htlcs.iter_mut() {
11069-
match &htlc.state {
11070-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
11071-
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11072-
}
11073-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
11074-
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11075-
}
11076-
_ => {}
11072+
let mut iter = preimages.into_iter();
11073+
for htlc in pending_outbound_htlcs.iter_mut() {
11074+
match &htlc.state {
11075+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
11076+
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
1107711077
}
11078+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
11079+
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11080+
}
11081+
_ => {}
1107811082
}
11079-
// We expect all preimages to be consumed above
11080-
if iter.next().is_some() {
11081-
return Err(DecodeError::InvalidValue);
11082-
}
11083+
}
11084+
// We expect all preimages to be consumed above
11085+
if iter.next().is_some() {
11086+
return Err(DecodeError::InvalidValue);
1108311087
}
1108411088

1108511089
let chan_features = channel_type.unwrap();

0 commit comments

Comments
 (0)