@@ -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;
@@ -9011,8 +9004,8 @@ impl<SP: Deref> FundedChannel<SP> where
9011
9004
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
9012
9005
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
9013
9006
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
9014
- // Grab the preimage, if it exists, instead of cloning
9015
- let mut reason = OutboundHTLCOutcome::Success(None );
9007
+ // Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
9008
+ let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]) );
9016
9009
mem::swap(outcome, &mut reason);
9017
9010
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
9018
9011
}
@@ -10637,7 +10630,9 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
10637
10630
}
10638
10631
}
10639
10632
10640
- let mut preimages: Vec<&Option<PaymentPreimage>> = vec![];
10633
+ // The elements of this vector will always be `Some` starting in 0.2,
10634
+ // but we still serialize the option to maintain backwards compatibility
10635
+ let mut preimages: Vec<Option<&PaymentPreimage>> = vec![];
10641
10636
let mut pending_outbound_skimmed_fees: Vec<Option<u64>> = Vec::new();
10642
10637
let mut pending_outbound_blinding_points: Vec<Option<PublicKey>> = Vec::new();
10643
10638
@@ -10664,15 +10659,15 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
10664
10659
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
10665
10660
3u8.write(writer)?;
10666
10661
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10667
- preimages.push(preimage);
10662
+ preimages.push(Some( preimage) );
10668
10663
}
10669
10664
let reason: Option<&HTLCFailReason> = outcome.into();
10670
10665
reason.write(writer)?;
10671
10666
}
10672
10667
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
10673
10668
4u8.write(writer)?;
10674
10669
if let OutboundHTLCOutcome::Success(preimage) = outcome {
10675
- preimages.push(preimage);
10670
+ preimages.push(Some( preimage) );
10676
10671
}
10677
10672
let reason: Option<&HTLCFailReason> = outcome.into();
10678
10673
reason.write(writer)?;
@@ -11011,15 +11006,30 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11011
11006
1 => OutboundHTLCState::Committed,
11012
11007
2 => {
11013
11008
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11014
- OutboundHTLCState::RemoteRemoved(option.into())
11009
+ let outcome = match option {
11010
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11011
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11012
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11013
+ };
11014
+ OutboundHTLCState::RemoteRemoved(outcome)
11015
11015
},
11016
11016
3 => {
11017
11017
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11018
- OutboundHTLCState::AwaitingRemoteRevokeToRemove(option.into())
11018
+ let outcome = match option {
11019
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11020
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11021
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11022
+ };
11023
+ OutboundHTLCState::AwaitingRemoteRevokeToRemove(outcome)
11019
11024
},
11020
11025
4 => {
11021
11026
let option: Option<HTLCFailReason> = Readable::read(reader)?;
11022
- OutboundHTLCState::AwaitingRemovedRemoteRevoke(option.into())
11027
+ let outcome = match option {
11028
+ Some(r) => OutboundHTLCOutcome::Failure(r),
11029
+ // Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
11030
+ None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
11031
+ };
11032
+ OutboundHTLCState::AwaitingRemovedRemoteRevoke(outcome)
11023
11033
},
11024
11034
_ => return Err(DecodeError::InvalidValue),
11025
11035
},
@@ -11166,7 +11176,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11166
11176
// only, so we default to that if none was written.
11167
11177
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
11168
11178
let mut channel_creation_height = 0u32;
11169
- let mut preimages_opt: Option<Vec<Option<PaymentPreimage>>> = None;
11179
+ // Starting in 0.2, all the elements in this vector will be `Some`, but they are still
11180
+ // serialized as options to maintain backwards compatibility
11181
+ let mut preimages: Vec<Option<PaymentPreimage>> = Vec::new();
11170
11182
11171
11183
// If we read an old Channel, for simplicity we just treat it as "we never sent an
11172
11184
// AnnouncementSignatures" which implies we'll re-send it on reconnect, but that's fine.
@@ -11220,7 +11232,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11220
11232
(10, monitor_pending_update_adds, option), // Added in 0.0.122
11221
11233
(11, monitor_pending_finalized_fulfills, optional_vec),
11222
11234
(13, channel_creation_height, required),
11223
- (15, preimages_opt, optional_vec),
11235
+ (15, preimages, required_vec), // The preimages transitioned from optional to required in 0.2
11224
11236
(17, announcement_sigs_state, required),
11225
11237
(19, latest_inbound_scid_alias, option),
11226
11238
(21, outbound_scid_alias, required),
@@ -11248,23 +11260,27 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11248
11260
11249
11261
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
11250
11262
11251
- if let Some(preimages) = preimages_opt {
11252
- let mut iter = preimages.into_iter();
11253
- for htlc in pending_outbound_htlcs.iter_mut() {
11254
- match &htlc.state {
11255
- OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
11256
- htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11257
- }
11258
- OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
11259
- htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
11260
- }
11261
- _ => {}
11263
+ let mut iter = preimages.into_iter();
11264
+ for htlc in pending_outbound_htlcs.iter_mut() {
11265
+ match &mut htlc.state {
11266
+ OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(ref mut preimage)) => {
11267
+ // This variant was initialized like this further above
11268
+ debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));
11269
+ // Flatten and unwrap the preimage; they are always set starting in 0.2.
11270
+ *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?;
11262
11271
}
11272
+ OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(ref mut preimage)) => {
11273
+ // This variant was initialized like this further above
11274
+ debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));
11275
+ // Flatten and unwrap the preimage; they are always set starting in 0.2.
11276
+ *preimage = iter.next().flatten().ok_or(DecodeError::InvalidValue)?;
11277
+ }
11278
+ _ => {}
11263
11279
}
11264
- // We expect all preimages to be consumed above
11265
- if iter.next().is_some() {
11266
- return Err(DecodeError::InvalidValue);
11267
- }
11280
+ }
11281
+ // We expect all preimages to be consumed above
11282
+ if iter.next().is_some() {
11283
+ return Err(DecodeError::InvalidValue);
11268
11284
}
11269
11285
11270
11286
let chan_features = channel_type.unwrap();
0 commit comments