Skip to content

Commit 9aa786c

Browse files
committed
Keep track of preimage in OutboundHTLCState on success
1 parent 35d4ebb commit 9aa786c

File tree

1 file changed

+109
-37
lines changed

1 file changed

+109
-37
lines changed

lightning/src/ln/channel.rs

Lines changed: 109 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,43 @@ enum OutboundHTLCState {
162162
Committed,
163163
/// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize
164164
/// the change (though they'll need to revoke before we fail the payment).
165-
RemoteRemoved(Option<HTLCFailReason>),
165+
RemoteRemoved(OutboundHTLCOutcome),
166166
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
167167
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
168168
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
169169
/// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a
170170
/// remote revoke_and_ack on a previous state before we can do so.
171-
AwaitingRemoteRevokeToRemove(Option<HTLCFailReason>),
171+
AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome),
172172
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
173173
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
174174
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
175175
/// We have removed this HTLC in our latest commitment_signed and are now just waiting on a
176176
/// revoke_and_ack to drop completely.
177-
AwaitingRemovedRemoteRevoke(Option<HTLCFailReason>),
177+
AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome),
178+
}
179+
180+
#[derive(Clone)]
181+
enum OutboundHTLCOutcome {
182+
Success(Option<PaymentPreimage>),
183+
Failure(HTLCFailReason),
184+
}
185+
186+
impl From<Option<HTLCFailReason>> for OutboundHTLCOutcome {
187+
fn from(o: Option<HTLCFailReason>) -> Self {
188+
match o {
189+
None => OutboundHTLCOutcome::Success(None),
190+
Some(r) => OutboundHTLCOutcome::Failure(r)
191+
}
192+
}
193+
}
194+
195+
impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
196+
fn into(self) -> Option<&'a HTLCFailReason> {
197+
match self {
198+
OutboundHTLCOutcome::Success(_) => None,
199+
OutboundHTLCOutcome::Failure(ref r) => Some(r)
200+
}
201+
}
178202
}
179203

180204
struct OutboundHTLCOutput {
@@ -1289,10 +1313,10 @@ impl<Signer: Sign> Channel<Signer> {
12891313
} else {
12901314
log_trace!(logger, " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, log_bytes!(htlc.payment_hash.0), htlc.amount_msat, state_name);
12911315
match htlc.state {
1292-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(None)|OutboundHTLCState::AwaitingRemovedRemoteRevoke(None) => {
1316+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_))|OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) => {
12931317
value_to_self_msat_offset -= htlc.amount_msat as i64;
12941318
},
1295-
OutboundHTLCState::RemoteRemoved(None) => {
1319+
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(_)) => {
12961320
if !generated_by_local {
12971321
value_to_self_msat_offset -= htlc.amount_msat as i64;
12981322
}
@@ -2393,9 +2417,9 @@ impl<Signer: Sign> Channel<Signer> {
23932417
// transaction).
23942418
let mut removed_outbound_total_msat = 0;
23952419
for ref htlc in self.pending_outbound_htlcs.iter() {
2396-
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(None) = htlc.state {
2420+
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) = htlc.state {
23972421
removed_outbound_total_msat += htlc.amount_msat;
2398-
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(None) = htlc.state {
2422+
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) = htlc.state {
23992423
removed_outbound_total_msat += htlc.amount_msat;
24002424
}
24012425
}
@@ -2494,21 +2518,25 @@ impl<Signer: Sign> Channel<Signer> {
24942518

24952519
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
24962520
#[inline]
2497-
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentHash>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
2521+
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<PaymentPreimage>, fail_reason: Option<HTLCFailReason>) -> Result<&OutboundHTLCOutput, ChannelError> {
2522+
assert!(!(check_preimage.is_some() && fail_reason.is_some()), "cannot fail while we have a preimage");
24982523
for htlc in self.pending_outbound_htlcs.iter_mut() {
24992524
if htlc.htlc_id == htlc_id {
2500-
match check_preimage {
2501-
None => {},
2502-
Some(payment_hash) =>
2525+
let outcome = match check_preimage {
2526+
None => fail_reason.into(),
2527+
Some(payment_preimage) => {
2528+
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
25032529
if payment_hash != htlc.payment_hash {
25042530
return Err(ChannelError::Close(format!("Remote tried to fulfill HTLC ({}) with an incorrect preimage", htlc_id)));
25052531
}
2532+
OutboundHTLCOutcome::Success(Some(payment_preimage))
2533+
}
25062534
};
25072535
match htlc.state {
25082536
OutboundHTLCState::LocalAnnounced(_) =>
25092537
return Err(ChannelError::Close(format!("Remote tried to fulfill/fail HTLC ({}) before it had been committed", htlc_id))),
25102538
OutboundHTLCState::Committed => {
2511-
htlc.state = OutboundHTLCState::RemoteRemoved(fail_reason);
2539+
htlc.state = OutboundHTLCState::RemoteRemoved(outcome);
25122540
},
25132541
OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) | OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) | OutboundHTLCState::RemoteRemoved(_) =>
25142542
return Err(ChannelError::Close(format!("Remote tried to fulfill/fail HTLC ({}) that they'd already fulfilled/failed", htlc_id))),
@@ -2527,8 +2555,7 @@ impl<Signer: Sign> Channel<Signer> {
25272555
return Err(ChannelError::Close("Peer sent update_fulfill_htlc when we needed a channel_reestablish".to_owned()));
25282556
}
25292557

2530-
let payment_hash = PaymentHash(Sha256::hash(&msg.payment_preimage.0[..]).into_inner());
2531-
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|htlc| (htlc.source.clone(), htlc.amount_msat))
2558+
self.mark_outbound_htlc_removed(msg.htlc_id, Some(msg.payment_preimage), None).map(|htlc| (htlc.source.clone(), htlc.amount_msat))
25322559
}
25332560

25342561
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), ChannelError> {
@@ -2689,12 +2716,13 @@ impl<Signer: Sign> Channel<Signer> {
26892716
}
26902717
}
26912718
for htlc in self.pending_outbound_htlcs.iter_mut() {
2692-
if let Some(fail_reason) = if let &mut OutboundHTLCState::RemoteRemoved(ref mut fail_reason) = &mut htlc.state {
2693-
Some(fail_reason.take())
2694-
} else { None } {
2719+
if let &mut OutboundHTLCState::RemoteRemoved(ref mut outcome) = &mut htlc.state {
26952720
log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}.",
26962721
log_bytes!(htlc.payment_hash.0), log_bytes!(self.channel_id));
2697-
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(fail_reason);
2722+
// Grab the preimage, if it exists, instead of cloning
2723+
let mut reason = OutboundHTLCOutcome::Success(None);
2724+
mem::swap(outcome, &mut reason);
2725+
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(reason);
26982726
need_commitment = true;
26992727
}
27002728
}
@@ -2963,9 +2991,9 @@ impl<Signer: Sign> Channel<Signer> {
29632991
} else { true }
29642992
});
29652993
pending_outbound_htlcs.retain(|htlc| {
2966-
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) = &htlc.state {
2994+
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) = &htlc.state {
29672995
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", log_bytes!(htlc.payment_hash.0));
2968-
if let Some(reason) = fail_reason.clone() { // We really want take() here, but, again, non-mut ref :(
2996+
if let OutboundHTLCOutcome::Failure(reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :(
29692997
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
29702998
} else {
29712999
finalized_claimed_htlcs.push(htlc.source.clone());
@@ -3019,11 +3047,12 @@ impl<Signer: Sign> Channel<Signer> {
30193047
log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", log_bytes!(htlc.payment_hash.0));
30203048
htlc.state = OutboundHTLCState::Committed;
30213049
}
3022-
if let Some(fail_reason) = if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut fail_reason) = &mut htlc.state {
3023-
Some(fail_reason.take())
3024-
} else { None } {
3050+
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
30253051
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", log_bytes!(htlc.payment_hash.0));
3026-
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(fail_reason);
3052+
// Grab the preimage, if it exists, instead of cloning
3053+
let mut reason = OutboundHTLCOutcome::Success(None);
3054+
mem::swap(outcome, &mut reason);
3055+
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
30273056
require_commitment = true;
30283057
}
30293058
}
@@ -4891,11 +4920,12 @@ impl<Signer: Sign> Channel<Signer> {
48914920
}
48924921
}
48934922
for htlc in self.pending_outbound_htlcs.iter_mut() {
4894-
if let Some(fail_reason) = if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut fail_reason) = &mut htlc.state {
4895-
Some(fail_reason.take())
4896-
} else { None } {
4923+
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
48974924
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", log_bytes!(htlc.payment_hash.0));
4898-
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(fail_reason);
4925+
// Grab the preimage, if it exists, instead of cloning
4926+
let mut reason = OutboundHTLCOutcome::Success(None);
4927+
mem::swap(outcome, &mut reason);
4928+
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
48994929
}
49004930
}
49014931
if let Some((feerate, update_state)) = self.pending_update_fee {
@@ -5253,6 +5283,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
52535283
}
52545284
}
52555285

5286+
let mut preimages: Vec<&Option<PaymentPreimage>> = vec![];
5287+
52565288
(self.pending_outbound_htlcs.len() as u64).write(writer)?;
52575289
for htlc in self.pending_outbound_htlcs.iter() {
52585290
htlc.htlc_id.write(writer)?;
@@ -5273,14 +5305,22 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
52735305
// resend the claim/fail on reconnect as we all (hopefully) the missing CS.
52745306
1u8.write(writer)?;
52755307
},
5276-
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref fail_reason) => {
5308+
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
52775309
3u8.write(writer)?;
5278-
fail_reason.write(writer)?;
5279-
},
5280-
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) => {
5310+
if let OutboundHTLCOutcome::Success(preimage) = outcome {
5311+
preimages.push(preimage);
5312+
}
5313+
let reason: Option<&HTLCFailReason> = outcome.into();
5314+
reason.write(writer)?;
5315+
}
5316+
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
52815317
4u8.write(writer)?;
5282-
fail_reason.write(writer)?;
5283-
},
5318+
if let OutboundHTLCOutcome::Success(preimage) = outcome {
5319+
preimages.push(preimage);
5320+
}
5321+
let reason: Option<&HTLCFailReason> = outcome.into();
5322+
reason.write(writer)?;
5323+
}
52845324
}
52855325
}
52865326

@@ -5434,6 +5474,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
54345474
(9, self.target_closing_feerate_sats_per_kw, option),
54355475
(11, self.monitor_pending_finalized_fulfills, vec_type),
54365476
(13, self.channel_creation_height, required),
5477+
(15, preimages, vec_type),
54375478
});
54385479

54395480
Ok(())
@@ -5519,9 +5560,18 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
55195560
state: match <u8 as Readable>::read(reader)? {
55205561
0 => OutboundHTLCState::LocalAnnounced(Box::new(Readable::read(reader)?)),
55215562
1 => OutboundHTLCState::Committed,
5522-
2 => OutboundHTLCState::RemoteRemoved(Readable::read(reader)?),
5523-
3 => OutboundHTLCState::AwaitingRemoteRevokeToRemove(Readable::read(reader)?),
5524-
4 => OutboundHTLCState::AwaitingRemovedRemoteRevoke(Readable::read(reader)?),
5563+
2 => {
5564+
let option: Option<HTLCFailReason> = Readable::read(reader)?;
5565+
OutboundHTLCState::RemoteRemoved(option.into())
5566+
},
5567+
3 => {
5568+
let option: Option<HTLCFailReason> = Readable::read(reader)?;
5569+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(option.into())
5570+
},
5571+
4 => {
5572+
let option: Option<HTLCFailReason> = Readable::read(reader)?;
5573+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(option.into())
5574+
},
55255575
_ => return Err(DecodeError::InvalidValue),
55265576
},
55275577
});
@@ -5675,6 +5725,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56755725
// only, so we default to that if none was written.
56765726
let mut channel_type = Some(ChannelTypeFeatures::only_static_remote_key());
56775727
let mut channel_creation_height = Some(serialized_height);
5728+
let mut preimages_opt: Option<Vec<Option<PaymentPreimage>>> = None;
5729+
56785730
read_tlv_fields!(reader, {
56795731
(0, announcement_sigs, option),
56805732
(1, minimum_depth, option),
@@ -5687,8 +5739,28 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
56875739
(9, target_closing_feerate_sats_per_kw, option),
56885740
(11, monitor_pending_finalized_fulfills, vec_type),
56895741
(13, channel_creation_height, option),
5742+
(15, preimages_opt, vec_type),
56905743
});
56915744

5745+
if let Some(preimages) = preimages_opt {
5746+
let mut iter = preimages.into_iter();
5747+
for htlc in pending_outbound_htlcs.iter_mut() {
5748+
match &htlc.state {
5749+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(None)) => {
5750+
htlc.state = OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
5751+
}
5752+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(None)) => {
5753+
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(iter.next().ok_or(DecodeError::InvalidValue)?));
5754+
}
5755+
_ => {}
5756+
}
5757+
}
5758+
// We expect all preimages to be consumed above
5759+
if iter.next().is_some() {
5760+
return Err(DecodeError::InvalidValue);
5761+
}
5762+
}
5763+
56925764
let chan_features = channel_type.as_ref().unwrap();
56935765
if chan_features.supports_unknown_bits() || chan_features.requires_unknown_bits() {
56945766
// If the channel was written by a new version and negotiated with features we don't

0 commit comments

Comments
 (0)