Skip to content

Commit 285f1b9

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 ea8533f commit 285f1b9

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
@@ -364,9 +364,12 @@ impl OutboundHTLCState {
364364

365365
fn preimage(&self) -> Option<PaymentPreimage> {
366366
match self {
367-
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(p)) |
368-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(p)) |
369-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(p)) => p.as_ref().copied(),
367+
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(preimage)) |
368+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(preimage)) |
369+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(preimage)) => {
370+
debug_assert!(preimage.is_some());
371+
*preimage
372+
},
370373
_ => None,
371374
}
372375
}
@@ -375,7 +378,10 @@ impl OutboundHTLCState {
375378
#[derive(Clone)]
376379
#[cfg_attr(test, derive(Debug, PartialEq))]
377380
enum OutboundHTLCOutcome {
378-
/// LDK version 0.0.105+ will always fill in the preimage here.
381+
/// Except briefly during deserialization and state transitions between success states,
382+
/// we require all success states to hold their corresponding preimage.
383+
/// We started always filling in the preimages here in 0.0.105, and the requirement
384+
/// that the preimages always be filled in was added in 0.2.
379385
Success(Option<PaymentPreimage>),
380386
Failure(HTLCFailReason),
381387
}
@@ -3876,7 +3882,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38763882
}
38773883
remote_htlc_total_msat += htlc.amount_msat;
38783884
} else {
3879-
if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_preimage)) = htlc.state {
3885+
if htlc.state.preimage().is_some() {
38803886
value_to_self_msat_offset += htlc.amount_msat as i64;
38813887
}
38823888
}
@@ -3889,10 +3895,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38893895
}
38903896
local_htlc_total_msat += htlc.amount_msat;
38913897
} else {
3892-
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) |
3893-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) |
3894-
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(_))
3895-
= htlc.state {
3898+
if htlc.state.preimage().is_some() {
38963899
value_to_self_msat_offset -= htlc.amount_msat as i64;
38973900
}
38983901
}
@@ -5801,6 +5804,7 @@ impl<SP: Deref> FundedChannel<SP> where
58015804
#[inline]
58025805
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentPreimage>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
58035806
assert!(!(check_preimage.is_some() && fail_reason.is_some()), "cannot fail while we have a preimage");
5807+
assert!(!(check_preimage.is_none() && fail_reason.is_none()), "success states must hold their corresponding preimage");
58045808
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
58055809
if htlc.htlc_id == htlc_id {
58065810
let outcome = match check_preimage {
@@ -10667,6 +10671,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1066710671
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
1066810672
3u8.write(writer)?;
1066910673
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10674+
debug_assert!(preimage.is_some(), "success states must hold their corresponding preimage");
1067010675
preimages.push(preimage);
1067110676
}
1067210677
let reason: Option<&HTLCFailReason> = outcome.into();
@@ -10675,6 +10680,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1067510680
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
1067610681
4u8.write(writer)?;
1067710682
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10683+
debug_assert!(preimage.is_some(), "success states must hold their corresponding preimage");
1067810684
preimages.push(preimage);
1067910685
}
1068010686
let reason: Option<&HTLCFailReason> = outcome.into();
@@ -11169,7 +11175,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1116911175
// only, so we default to that if none was written.
1117011176
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
1117111177
let mut channel_creation_height = 0u32;
11172-
let mut preimages_opt: Option<Vec<Option<PaymentPreimage>>> = None;
11178+
let mut preimages: Vec<Option<PaymentPreimage>> = Vec::new();
1117311179

1117411180
// If we read an old Channel, for simplicity we just treat it as "we never sent an
1117511181
// AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine.
@@ -11223,7 +11229,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1122311229
(10, monitor_pending_update_adds, option), // Added in 0.0.122
1122411230
(11, monitor_pending_finalized_fulfills, optional_vec),
1122511231
(13, channel_creation_height, required),
11226-
(15, preimages_opt, optional_vec),
11232+
(15, preimages, required_vec), // The preimages transitioned from optional to required in 0.2
1122711233
(17, announcement_sigs_state, required),
1122811234
(19, latest_inbound_scid_alias, option),
1122911235
(21, outbound_scid_alias, required),
@@ -11251,23 +11257,21 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1125111257

1125211258
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
1125311259

11254-
if let Some(preimages) = preimages_opt {
11255-
let mut iter = preimages.into_iter();
11256-
for htlc in pending_outbound_htlcs.iter_mut() {
11257-
match &htlc.state {
11258-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
11259-
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11260-
}
11261-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
11262-
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11263-
}
11264-
_ => {}
11260+
let mut iter = preimages.into_iter();
11261+
for htlc in pending_outbound_htlcs.iter_mut() {
11262+
match &htlc.state {
11263+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
11264+
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
1126511265
}
11266+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
11267+
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11268+
}
11269+
_ => {}
1126611270
}
11267-
// We expect all preimages to be consumed above
11268-
if iter.next().is_some() {
11269-
return Err(DecodeError::InvalidValue);
11270-
}
11271+
}
11272+
// We expect all preimages to be consumed above
11273+
if iter.next().is_some() {
11274+
return Err(DecodeError::InvalidValue);
1127111275
}
1127211276

1127311277
let chan_features = channel_type.unwrap();

0 commit comments

Comments
 (0)