Skip to content

Commit 4ad00f4

Browse files
committed
Track incoming UpdateAddHTLC until HTLC resolution
This commit serves as a stepping stone to moving towards resolving HTLCs once the HTLC has been fully committed to by both sides. Currently, we decode HTLC onions immediately upon receiving an `update_add_htlc`. Doing so determines what we should do with the HTLC: forward it, or immediately fail it back if it cannot be accepted. This action is tracked until the HTLC is fully committed to by both sides, and a new commitment in the latter case is proposed to fully remove the HTLC. While this has worked so far, it has some minor privacy implications, as forwarding/failing back do not go through the usual `PendingHTLCsForwardable` flow. It also presents issues with the quiescence handshake, as failures through this path do not go through the holding cell abstraction, leading to a potential violation of the handshake by sending an `update_fail_*` after already having sent `stfu`. Since `pending_inbound_htlcs` are written pre-TLVs, we introduce a new serialization version in which we change the `PendingHTLCStatus` serialization of `InboundHTLC::AwaitingRemoteRevokeToRemove/AwaitingRemovedRemoteRevoke` to be an option instead. We'll still write it as the current version (`MIN_SERIALIZATION_VERSION`), but we'll support reading the new version to allow users to downgrade back to this commit.
1 parent c096a24 commit 4ad00f4

File tree

2 files changed

+130
-34
lines changed

2 files changed

+130
-34
lines changed

lightning/src/ln/channel.rs

Lines changed: 128 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,38 @@ enum InboundHTLCRemovalReason {
104104
Fulfill(PaymentPreimage),
105105
}
106106

107+
/// Represents the resolution status of an inbound HTLC.
108+
#[derive(Clone)]
109+
enum InboundHTLCResolution {
110+
/// Resolved implies the action we must take with the inbound HTLC has already been determined,
111+
/// i.e., we already know whether it must be failed back or forwarded.
112+
//
113+
// TODO: Once this variant is removed, we should also clean up
114+
// [`MonitorRestoreUpdates::accepted_htlcs`] as the path will be unreachable.
115+
Resolved {
116+
pending_htlc_status: PendingHTLCStatus,
117+
},
118+
/// Pending implies we will attempt to resolve the inbound HTLC once it has been fully committed
119+
/// to by both sides of the channel, i.e., once a `revoke_and_ack` has been processed by both
120+
/// nodes for the state update in which it was proposed.
121+
Pending {
122+
update_add_htlc: msgs::UpdateAddHTLC,
123+
},
124+
}
125+
126+
impl_writeable_tlv_based_enum!(InboundHTLCResolution,
127+
(0, Resolved) => {
128+
(0, pending_htlc_status, required),
129+
},
130+
(2, Pending) => {
131+
(0, update_add_htlc, required),
132+
};
133+
);
134+
107135
enum InboundHTLCState {
108136
/// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an
109137
/// update_add_htlc message for this HTLC.
110-
RemoteAnnounced(PendingHTLCStatus),
138+
RemoteAnnounced(InboundHTLCResolution),
111139
/// Included in a received commitment_signed message (implying we've
112140
/// revoke_and_ack'd it), but the remote hasn't yet revoked their previous
113141
/// state (see the example below). We have not yet included this HTLC in a
@@ -137,13 +165,13 @@ enum InboundHTLCState {
137165
/// Implies AwaitingRemoteRevoke.
138166
///
139167
/// [BOLT #2]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md
140-
AwaitingRemoteRevokeToAnnounce(PendingHTLCStatus),
168+
AwaitingRemoteRevokeToAnnounce(InboundHTLCResolution),
141169
/// Included in a received commitment_signed message (implying we've revoke_and_ack'd it).
142170
/// We have also included this HTLC in our latest commitment_signed and are now just waiting
143171
/// on the remote's revoke_and_ack to make this HTLC an irrevocable part of the state of the
144172
/// channel (before it can then get forwarded and/or removed).
145173
/// Implies AwaitingRemoteRevoke.
146-
AwaitingAnnouncedRemoteRevoke(PendingHTLCStatus),
174+
AwaitingAnnouncedRemoteRevoke(InboundHTLCResolution),
147175
Committed,
148176
/// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
149177
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
@@ -1291,6 +1319,7 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
12911319
monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>,
12921320
monitor_pending_failures: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
12931321
monitor_pending_finalized_fulfills: Vec<HTLCSource>,
1322+
monitor_pending_update_adds: Vec<msgs::UpdateAddHTLC>,
12941323

12951324
/// If we went to send a commitment update (ie some messages then [`msgs::CommitmentSigned`])
12961325
/// but our signer (initially) refused to give us a signature, we should retry at some point in
@@ -1755,6 +1784,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
17551784
monitor_pending_forwards: Vec::new(),
17561785
monitor_pending_failures: Vec::new(),
17571786
monitor_pending_finalized_fulfills: Vec::new(),
1787+
monitor_pending_update_adds: Vec::new(),
17581788

17591789
signer_pending_commitment_update: false,
17601790
signer_pending_funding: false,
@@ -1976,6 +2006,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
19762006
monitor_pending_forwards: Vec::new(),
19772007
monitor_pending_failures: Vec::new(),
19782008
monitor_pending_finalized_fulfills: Vec::new(),
2009+
monitor_pending_update_adds: Vec::new(),
19792010

19802011
signer_pending_commitment_update: false,
19812012
signer_pending_funding: false,
@@ -4255,7 +4286,9 @@ impl<SP: Deref> Channel<SP> where
42554286
amount_msat: msg.amount_msat,
42564287
payment_hash: msg.payment_hash,
42574288
cltv_expiry: msg.cltv_expiry,
4258-
state: InboundHTLCState::RemoteAnnounced(pending_forward_status),
4289+
state: InboundHTLCState::RemoteAnnounced(InboundHTLCResolution::Resolved {
4290+
pending_htlc_status: pending_forward_status
4291+
}),
42594292
});
42604293
Ok(())
42614294
}
@@ -4461,13 +4494,13 @@ impl<SP: Deref> Channel<SP> where
44614494
}
44624495

44634496
for htlc in self.context.pending_inbound_htlcs.iter_mut() {
4464-
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
4465-
Some(forward_info.clone())
4497+
let htlc_resolution = if let &InboundHTLCState::RemoteAnnounced(ref resolution) = &htlc.state {
4498+
Some(resolution.clone())
44664499
} else { None };
4467-
if let Some(forward_info) = new_forward {
4500+
if let Some(htlc_resolution) = htlc_resolution {
44684501
log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToAnnounce due to commitment_signed in channel {}.",
44694502
&htlc.payment_hash, &self.context.channel_id);
4470-
htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info);
4503+
htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce(htlc_resolution);
44714504
need_commitment = true;
44724505
}
44734506
}
@@ -4777,6 +4810,7 @@ impl<SP: Deref> Channel<SP> where
47774810

47784811
log_trace!(logger, "Updating HTLCs on receipt of RAA in channel {}...", &self.context.channel_id());
47794812
let mut to_forward_infos = Vec::new();
4813+
let mut pending_update_adds = Vec::new();
47804814
let mut revoked_htlcs = Vec::new();
47814815
let mut finalized_claimed_htlcs = Vec::new();
47824816
let mut update_fail_htlcs = Vec::new();
@@ -4824,29 +4858,37 @@ impl<SP: Deref> Channel<SP> where
48244858
let mut state = InboundHTLCState::Committed;
48254859
mem::swap(&mut state, &mut htlc.state);
48264860

4827-
if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(forward_info) = state {
4861+
if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(resolution) = state {
48284862
log_trace!(logger, " ...promoting inbound AwaitingRemoteRevokeToAnnounce {} to AwaitingAnnouncedRemoteRevoke", &htlc.payment_hash);
4829-
htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info);
4863+
htlc.state = InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution);
48304864
require_commitment = true;
4831-
} else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(forward_info) = state {
4832-
match forward_info {
4833-
PendingHTLCStatus::Fail(fail_msg) => {
4834-
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to LocalRemoved due to PendingHTLCStatus indicating failure", &htlc.payment_hash);
4835-
require_commitment = true;
4836-
match fail_msg {
4837-
HTLCFailureMsg::Relay(msg) => {
4838-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
4839-
update_fail_htlcs.push(msg)
4840-
},
4841-
HTLCFailureMsg::Malformed(msg) => {
4842-
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
4843-
update_fail_malformed_htlcs.push(msg)
4865+
} else if let InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution) = state {
4866+
match resolution {
4867+
InboundHTLCResolution::Resolved { pending_htlc_status } =>
4868+
match pending_htlc_status {
4869+
PendingHTLCStatus::Fail(fail_msg) => {
4870+
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to LocalRemoved due to PendingHTLCStatus indicating failure", &htlc.payment_hash);
4871+
require_commitment = true;
4872+
match fail_msg {
4873+
HTLCFailureMsg::Relay(msg) => {
4874+
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(msg.reason.clone()));
4875+
update_fail_htlcs.push(msg)
4876+
},
4877+
HTLCFailureMsg::Malformed(msg) => {
4878+
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed((msg.sha256_of_onion, msg.failure_code)));
4879+
update_fail_malformed_htlcs.push(msg)
4880+
},
4881+
}
48444882
},
4883+
PendingHTLCStatus::Forward(forward_info) => {
4884+
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed, attempting to forward", &htlc.payment_hash);
4885+
to_forward_infos.push((forward_info, htlc.htlc_id));
4886+
htlc.state = InboundHTLCState::Committed;
4887+
}
48454888
}
4846-
},
4847-
PendingHTLCStatus::Forward(forward_info) => {
4889+
InboundHTLCResolution::Pending { update_add_htlc } => {
48484890
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash);
4849-
to_forward_infos.push((forward_info, htlc.htlc_id));
4891+
pending_update_adds.push(update_add_htlc);
48504892
htlc.state = InboundHTLCState::Committed;
48514893
}
48524894
}
@@ -4907,6 +4949,8 @@ impl<SP: Deref> Channel<SP> where
49074949
}
49084950
}
49094951

4952+
self.context.monitor_pending_update_adds.append(&mut pending_update_adds);
4953+
49104954
if self.context.channel_state.is_monitor_update_in_progress() {
49114955
// We can't actually generate a new commitment transaction (incl by freeing holding
49124956
// cells) while we can't update the monitor, so we just return what we have.
@@ -8232,7 +8276,7 @@ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures)
82328276
ret
82338277
}
82348278

8235-
const SERIALIZATION_VERSION: u8 = 3;
8279+
const SERIALIZATION_VERSION: u8 = 4;
82368280
const MIN_SERIALIZATION_VERSION: u8 = 3;
82378281

82388282
impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,;
@@ -8294,7 +8338,18 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
82948338
// Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been
82958339
// called.
82968340

8297-
write_ver_prefix!(writer, MIN_SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
8341+
let version_to_write = if self.context.pending_inbound_htlcs.iter().any(|htlc| match htlc.state {
8342+
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref htlc_resolution)|
8343+
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(ref htlc_resolution) => {
8344+
matches!(htlc_resolution, InboundHTLCResolution::Pending { .. })
8345+
},
8346+
_ => false,
8347+
}) {
8348+
SERIALIZATION_VERSION
8349+
} else {
8350+
MIN_SERIALIZATION_VERSION
8351+
};
8352+
write_ver_prefix!(writer, version_to_write, MIN_SERIALIZATION_VERSION);
82988353

82998354
// `user_id` used to be a single u64 value. In order to remain backwards compatible with
83008355
// versions prior to 0.0.113, the u128 is serialized as two separate u64 values. We write
@@ -8350,13 +8405,29 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
83508405
htlc.payment_hash.write(writer)?;
83518406
match &htlc.state {
83528407
&InboundHTLCState::RemoteAnnounced(_) => unreachable!(),
8353-
&InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref htlc_state) => {
8408+
&InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref htlc_resolution) => {
83548409
1u8.write(writer)?;
8355-
htlc_state.write(writer)?;
8410+
if version_to_write <= 3 {
8411+
if let InboundHTLCResolution::Resolved { pending_htlc_status } = htlc_resolution {
8412+
pending_htlc_status.write(writer)?;
8413+
} else {
8414+
panic!();
8415+
}
8416+
} else {
8417+
htlc_resolution.write(writer)?;
8418+
}
83568419
},
8357-
&InboundHTLCState::AwaitingAnnouncedRemoteRevoke(ref htlc_state) => {
8420+
&InboundHTLCState::AwaitingAnnouncedRemoteRevoke(ref htlc_resolution) => {
83588421
2u8.write(writer)?;
8359-
htlc_state.write(writer)?;
8422+
if version_to_write <= 3 {
8423+
if let InboundHTLCResolution::Resolved { pending_htlc_status } = htlc_resolution {
8424+
pending_htlc_status.write(writer)?;
8425+
} else {
8426+
panic!();
8427+
}
8428+
} else {
8429+
htlc_resolution.write(writer)?;
8430+
}
83608431
},
83618432
&InboundHTLCState::Committed => {
83628433
3u8.write(writer)?;
@@ -8582,6 +8653,11 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
85828653

85838654
let holder_max_accepted_htlcs = if self.context.holder_max_accepted_htlcs == DEFAULT_MAX_HTLCS { None } else { Some(self.context.holder_max_accepted_htlcs) };
85848655

8656+
let mut monitor_pending_update_adds = None;
8657+
if !self.context.monitor_pending_update_adds.is_empty() {
8658+
monitor_pending_update_adds = Some(&self.context.monitor_pending_update_adds);
8659+
}
8660+
85858661
write_tlv_fields!(writer, {
85868662
(0, self.context.announcement_sigs, option),
85878663
// minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -8599,6 +8675,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
85998675
(7, self.context.shutdown_scriptpubkey, option),
86008676
(8, self.context.blocked_monitor_updates, optional_vec),
86018677
(9, self.context.target_closing_feerate_sats_per_kw, option),
8678+
(10, monitor_pending_update_adds, option), // Added in 0.0.122
86028679
(11, self.context.monitor_pending_finalized_fulfills, required_vec),
86038680
(13, self.context.channel_creation_height, required),
86048681
(15, preimages, required_vec),
@@ -8693,8 +8770,22 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
86938770
cltv_expiry: Readable::read(reader)?,
86948771
payment_hash: Readable::read(reader)?,
86958772
state: match <u8 as Readable>::read(reader)? {
8696-
1 => InboundHTLCState::AwaitingRemoteRevokeToAnnounce(Readable::read(reader)?),
8697-
2 => InboundHTLCState::AwaitingAnnouncedRemoteRevoke(Readable::read(reader)?),
8773+
1 => {
8774+
let resolution = if ver <= 3 {
8775+
InboundHTLCResolution::Resolved { pending_htlc_status: Readable::read(reader)? }
8776+
} else {
8777+
Readable::read(reader)?
8778+
};
8779+
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(resolution)
8780+
},
8781+
2 => {
8782+
let resolution = if ver <= 3 {
8783+
InboundHTLCResolution::Resolved { pending_htlc_status: Readable::read(reader)? }
8784+
} else {
8785+
Readable::read(reader)?
8786+
};
8787+
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution)
8788+
},
86988789
3 => InboundHTLCState::Committed,
86998790
4 => InboundHTLCState::LocalRemoved(Readable::read(reader)?),
87008791
_ => return Err(DecodeError::InvalidValue),
@@ -8911,6 +9002,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
89119002
let mut holding_cell_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
89129003

89139004
let mut malformed_htlcs: Option<Vec<(u64, u16, [u8; 32])>> = None;
9005+
let mut monitor_pending_update_adds: Option<Vec<msgs::UpdateAddHTLC>> = None;
89149006

89159007
read_tlv_fields!(reader, {
89169008
(0, announcement_sigs, option),
@@ -8923,6 +9015,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
89239015
(7, shutdown_scriptpubkey, option),
89249016
(8, blocked_monitor_updates, optional_vec),
89259017
(9, target_closing_feerate_sats_per_kw, option),
9018+
(10, monitor_pending_update_adds, option), // Added in 0.0.122
89269019
(11, monitor_pending_finalized_fulfills, optional_vec),
89279020
(13, channel_creation_height, option),
89289021
(15, preimages_opt, optional_vec),
@@ -9094,6 +9187,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
90949187
monitor_pending_forwards,
90959188
monitor_pending_failures,
90969189
monitor_pending_finalized_fulfills: monitor_pending_finalized_fulfills.unwrap(),
9190+
monitor_pending_update_adds: monitor_pending_update_adds.unwrap_or(Vec::new()),
90979191

90989192
signer_pending_commitment_update: false,
90999193
signer_pending_funding: false,

lightning/src/util/ser.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,8 @@ impl_for_vec!(crate::ln::msgs::SocketAddress);
894894
impl_for_vec!((A, B), A, B);
895895
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
896896
impl_readable_for_vec!(crate::routing::router::BlindedTail);
897+
impl_for_vec_with_element_length_prefix!(crate::ln::msgs::UpdateAddHTLC);
898+
impl_writeable_for_vec_with_element_length_prefix!(&crate::ln::msgs::UpdateAddHTLC);
897899

898900
impl Writeable for Vec<Witness> {
899901
#[inline]

0 commit comments

Comments
 (0)