@@ -364,9 +364,11 @@ impl OutboundHTLCState {
364
364
365
365
fn preimage(&self) -> Option<PaymentPreimage> {
366
366
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
+ Some(*preimage)
371
+ },
370
372
_ => None,
371
373
}
372
374
}
@@ -375,20 +377,12 @@ impl OutboundHTLCState {
375
377
#[derive(Clone)]
376
378
#[cfg_attr(test, derive(Debug, PartialEq))]
377
379
enum OutboundHTLCOutcome {
378
- /// LDK version 0.0.105+ will always fill in the preimage here.
379
- Success(Option<PaymentPreimage>),
380
+ /// We started always filling in the preimages here in 0.0.105, and the requirement
381
+ /// that the preimages always be filled in was added in 0.2.
382
+ Success(PaymentPreimage),
380
383
Failure(HTLCFailReason),
381
384
}
382
385
383
- impl From<Option<HTLCFailReason>> for OutboundHTLCOutcome {
384
- fn from(o: Option<HTLCFailReason>) -> Self {
385
- match o {
386
- None => OutboundHTLCOutcome::Success(None),
387
- Some(r) => OutboundHTLCOutcome::Failure(r)
388
- }
389
- }
390
- }
391
-
392
386
impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
393
387
fn into(self) -> Option<&'a HTLCFailReason> {
394
388
match self {
@@ -3876,7 +3870,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3876
3870
}
3877
3871
remote_htlc_total_msat += htlc.amount_msat;
3878
3872
} else {
3879
- if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_preimage)) = htlc.state {
3873
+ if htlc.state.preimage().is_some() {
3880
3874
value_to_self_msat_offset += htlc.amount_msat as i64;
3881
3875
}
3882
3876
}
@@ -3889,10 +3883,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3889
3883
}
3890
3884
local_htlc_total_msat += htlc.amount_msat;
3891
3885
} else {
3892
- if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) |
3893
- OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) |
3894
- OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(_))
3895
- = htlc.state {
3886
+ if htlc.state.preimage().is_some() {
3896
3887
value_to_self_msat_offset -= htlc.amount_msat as i64;
3897
3888
}
3898
3889
}
@@ -5801,16 +5792,18 @@ impl<SP: Deref> FundedChannel<SP> where
5801
5792
#[inline]
5802
5793
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentPreimage>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
5803
5794
assert!(!(check_preimage.is_some() && fail_reason.is_some()), "cannot fail while we have a preimage");
5795
+ assert!(!(check_preimage.is_none() && fail_reason.is_none()), "either provide a preimage, or a failure reason");
5804
5796
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
5805
5797
if htlc.htlc_id == htlc_id {
5806
5798
let outcome = match check_preimage {
5807
- None => fail_reason.into(),
5799
+ // We checked that either check_preimage or fail_reason is set above, so we can safely unwrap here
5800
+ None => OutboundHTLCOutcome::Failure(fail_reason.unwrap()),
5808
5801
Some(payment_preimage) => {
5809
5802
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array());
5810
5803
if payment_hash != htlc.payment_hash {
5811
5804
return Err(ChannelError::close(format!("Remote tried to fulfill HTLC ({}) with an incorrect preimage", htlc_id)));
5812
5805
}
5813
- OutboundHTLCOutcome::Success(Some( payment_preimage) )
5806
+ OutboundHTLCOutcome::Success(payment_preimage)
5814
5807
}
5815
5808
};
5816
5809
match htlc.state {
@@ -6014,10 +6007,10 @@ impl<SP: Deref> FundedChannel<SP> where
6014
6007
if let &mut OutboundHTLCState::RemoteRemoved(ref mut outcome) = &mut htlc.state {
6015
6008
log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}.",
6016
6009
&htlc.payment_hash, &self.context.channel_id);
6017
- // Grab the preimage, if it exists, instead of cloning
6018
- let mut reason = OutboundHTLCOutcome::Success(None );
6010
+ // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
6011
+ let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]) );
6019
6012
mem::swap(outcome, &mut reason);
6020
- if let OutboundHTLCOutcome::Success(Some( preimage) ) = reason {
6013
+ if let OutboundHTLCOutcome::Success(preimage) = reason {
6021
6014
// If a user (a) receives an HTLC claim using LDK 0.0.104 or before, then (b)
6022
6015
// upgrades to LDK 0.0.114 or later before the HTLC is fully resolved, we could
6023
6016
// have a `Success(None)` reason. In this case we could forget some HTLC
@@ -6435,8 +6428,8 @@ impl<SP: Deref> FundedChannel<SP> where
6435
6428
}
6436
6429
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
6437
6430
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
6438
- // Grab the preimage, if it exists, instead of cloning
6439
- let mut reason = OutboundHTLCOutcome::Success(None );
6431
+ // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
6432
+ let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]) );
6440
6433
mem::swap(outcome, &mut reason);
6441
6434
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
6442
6435
require_commitment = true;
@@ -9014,8 +9007,8 @@ impl<SP: Deref> FundedChannel<SP> where
9014
9007
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
9015
9008
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
9016
9009
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
9017
- // Grab the preimage, if it exists, instead of cloning
9018
- let mut reason = OutboundHTLCOutcome::Success(None );
9010
+ // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
9011
+ let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]) );
9019
9012
mem::swap(outcome, &mut reason);
9020
9013
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
9021
9014
}
@@ -10640,7 +10633,9 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
10640
10633
}
10641
10634
}
10642
10635
10643
- let mut preimages: Vec<&Option<PaymentPreimage>> = vec![];
10636
+ // The elements of this vector will always be `Some` starting in 0.2,
10637
+ // but we still serialize the option to maintain backwards compatibility
10638
+ let mut preimages: Vec<Option<&PaymentPreimage>> = vec![];
10644
10639
let mut pending_outbound_skimmed_fees: Vec<Option<u64>> = Vec::new();
10645
10640
let mut pending_outbound_blinding_points: Vec<Option<PublicKey>> = Vec::new();
10646
10641
@@ -10667,15 +10662,15 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
10667
10662
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
10668
10663
3u8.write(writer)?;
10669
10664
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10670
- preimages.push(preimage);
10665
+ preimages.push(Some( preimage) );
10671
10666
}
10672
10667
let reason: Option<&HTLCFailReason> = outcome.into();
10673
10668
reason.write(writer)?;
10674
10669
}
10675
10670
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
10676
10671
4u8.write(writer)?;
10677
10672
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10678
- preimages.push(preimage);
10673
+ preimages.push(Some( preimage) );
10679
10674
}
10680
10675
let reason: Option<&HTLCFailReason> = outcome.into();
10681
10676
reason.write(writer)?;
@@ -11014,15 +11009,30 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11014
11009
1 => OutboundHTLCState::Committed,
11015
11010
2 => {
11016
11011
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11017
- OutboundHTLCState::RemoteRemoved(option.into())
11012
+ let outcome = match option {
11013
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11014
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11015
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11016
+ };
11017
+ OutboundHTLCState::RemoteRemoved(outcome)
11018
11018
},
11019
11019
3 => {
11020
11020
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11021
- OutboundHTLCState::AwaitingRemoteRevokeToRemove(option.into())
11021
+ let outcome = match option {
11022
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11023
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11024
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11025
+ };
11026
+ OutboundHTLCState::AwaitingRemoteRevokeToRemove(outcome)
11022
11027
},
11023
11028
4 => {
11024
11029
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11025
- OutboundHTLCState::AwaitingRemovedRemoteRevoke(option.into())
11030
+ let outcome = match option {
11031
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11032
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11033
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11034
+ };
11035
+ OutboundHTLCState::AwaitingRemovedRemoteRevoke(outcome)
11026
11036
},
11027
11037
_ => return Err(DecodeError::InvalidValue),
11028
11038
},
@@ -11169,7 +11179,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11169
11179
// only, so we default to that if none was written.
11170
11180
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
11171
11181
let mut channel_creation_height = 0u32;
11172
- let mut preimages_opt: Option<Vec<Option<PaymentPreimage>>> = None;
11182
+ // Starting in 0.2, all the elements in this vector will be `Some`, but they are still
11183
+ // serialized as options to maintain backwards compatibility
11184
+ let mut preimages: Vec<Option<PaymentPreimage>> = Vec::new();
11173
11185
11174
11186
// If we read an old Channel, for simplicity we just treat it as "we never sent an
11175
11187
// AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine.
@@ -11223,7 +11235,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11223
11235
(10, monitor_pending_update_adds, option), // Added in 0.0.122
11224
11236
(11, monitor_pending_finalized_fulfills, optional_vec),
11225
11237
(13, channel_creation_height, required),
11226
- (15, preimages_opt, optional_vec),
11238
+ (15, preimages, required_vec), // The preimages transitioned from optional to required in 0.2
11227
11239
(17, announcement_sigs_state, required),
11228
11240
(19, latest_inbound_scid_alias, option),
11229
11241
(21, outbound_scid_alias, required),
@@ -11251,23 +11263,27 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11251
11263
11252
11264
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
11253
11265
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
- _ => {}
11266
+ let mut iter = preimages.into_iter();
11267
+ for htlc in pending_outbound_htlcs.iter_mut() {
11268
+ match &mut htlc.state {
11269
+ OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(ref mut preimage)) => {
11270
+ // This variant was initialized like this further above
11271
+ debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));
11272
+ // Flatten and unwrap the preimage; they are always set starting in 0.2.
11273
+ *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?;
11265
11274
}
11275
+ OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(ref mut preimage)) => {
11276
+ // This variant was initialized like this further above
11277
+ debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));
11278
+ // Flatten and unwrap the preimage; they are always set starting in 0.2.
11279
+ *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?;
11280
+ }
11281
+ _ => {}
11266
11282
}
11267
- // We expect all preimages to be consumed above
11268
- if iter.next().is_some() {
11269
- return Err(DecodeError::InvalidValue);
11270
- }
11283
+ }
11284
+ // We expect all preimages to be consumed above
11285
+ if iter.next().is_some() {
11286
+ return Err(DecodeError::InvalidValue);
11271
11287
}
11272
11288
11273
11289
let chan_features = channel_type.unwrap();
0 commit comments