Skip to content

Commit e751993

Browse files
committed
Always process payment send ChannelMonitorUpdates asynchronously
We currently have two codepaths on most channel update functions - most methods return a set of messages to send a peer iff the `ChannelMonitorUpdate` succeeds, but if it does not we push the messages back into the `Channel` and then pull them back out when the `ChannelMonitorUpdate` completes and send them then. This adds a substantial amount of complexity in very critical codepaths. Instead, here we swap all our channel update codepaths to immediately set the channel-update-required flag and only return a `ChannelMonitorUpdate` to the `ChannelManager`. Internally in the `Channel` we store a queue of `ChannelMonitorUpdate`s, which will become critical in future work to surface pending `ChannelMonitorUpdate`s to users at startup so they can complete. This leaves some redundant work in `Channel` to be cleaned up later. Specifically, we still generate the messages which we will now ignore and regenerate later. This commit updates the `ChannelMonitorUpdate` pipeline for HTLC sends originating from an outbound payment.
1 parent c110a48 commit e751993

File tree

2 files changed

+37
-61
lines changed

2 files changed

+37
-61
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5769,15 +5769,6 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
57695769
Ok(Some(res))
57705770
}
57715771

5772-
/// Only fails in case of signer rejection.
5773-
fn send_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> Result<(msgs::CommitmentSigned, ChannelMonitorUpdate), ChannelError> where L::Target: Logger {
5774-
let monitor_update = self.build_commitment_no_status_check(logger);
5775-
match self.send_commitment_no_state_update(logger) {
5776-
Ok((commitment_signed, _)) => Ok((commitment_signed, monitor_update)),
5777-
Err(e) => Err(e),
5778-
}
5779-
}
5780-
57815772
fn build_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger {
57825773
log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
57835774
// We can upgrade the status of some HTLCs that are waiting on a commitment, even if we
@@ -5903,16 +5894,20 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
59035894
}, (counterparty_commitment_txid, commitment_stats.htlcs_included)))
59045895
}
59055896

5906-
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
5907-
/// to send to the remote peer in one go.
5897+
/// Adds a pending outbound HTLC to this channel, and builds a new remote commitment
5898+
/// transaction and generates the corresponding [`ChannelMonitorUpdate`] in one go.
59085899
///
59095900
/// Shorthand for calling [`Self::send_htlc`] followed by a commitment update, see docs on
5910-
/// [`Self::send_htlc`] and [`Self::send_commitment_no_state_update`] for more info.
5911-
pub fn send_htlc_and_commit<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned, ChannelMonitorUpdate)>, ChannelError> where L::Target: Logger {
5912-
match self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger)? {
5913-
Some(update_add_htlc) => {
5914-
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check(logger)?;
5915-
Ok(Some((update_add_htlc, commitment_signed, monitor_update)))
5901+
/// [`Self::send_htlc`] and [`Self::build_commitment_no_state_update`] for more info.
5902+
pub fn send_htlc_and_commit<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError> where L::Target: Logger {
5903+
let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger);
5904+
if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } }
5905+
match send_res? {
5906+
Some(_) => {
5907+
let monitor_update = self.build_commitment_no_status_check(logger);
5908+
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
5909+
self.pending_monitor_updates.push(monitor_update);
5910+
Ok(Some(self.pending_monitor_updates.last().unwrap()))
59165911
},
59175912
None => Ok(None)
59185913
}

lightning/src/ln/channelmanager.rs

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,51 +2485,32 @@ where
24852485
if !chan.get().is_live() {
24862486
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected".to_owned()});
24872487
}
2488-
match {
2489-
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
2490-
htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
2491-
path: path.clone(),
2492-
session_priv: session_priv.clone(),
2493-
first_hop_htlc_msat: htlc_msat,
2494-
payment_id,
2495-
payment_secret: payment_secret.clone(),
2496-
payment_params: payment_params.clone(),
2497-
}, onion_packet, &self.logger),
2498-
chan)
2499-
} {
2500-
Some((update_add, commitment_signed, monitor_update)) => {
2501-
let update_err = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update);
2502-
let chan_id = chan.get().channel_id();
2503-
match (update_err,
2504-
handle_monitor_update_res!(self, update_err, chan,
2505-
RAACommitmentOrder::CommitmentFirst, false, true))
2506-
{
2507-
(ChannelMonitorUpdateStatus::PermanentFailure, Err(e)) => break Err(e),
2508-
(ChannelMonitorUpdateStatus::Completed, Ok(())) => {},
2509-
(ChannelMonitorUpdateStatus::InProgress, Err(_)) => {
2510-
// Note that MonitorUpdateInProgress here indicates (per function
2511-
// docs) that we will resend the commitment update once monitor
2512-
// updating completes. Therefore, we must return an error
2513-
// indicating that it is unsafe to retry the payment wholesale,
2514-
// which we do in the send_payment check for
2515-
// MonitorUpdateInProgress, below.
2516-
return Err(APIError::MonitorUpdateInProgress);
2517-
},
2518-
_ => unreachable!(),
2488+
let funding_txo = chan.get().get_funding_txo().unwrap();
2489+
let send_res = chan.get_mut().send_htlc_and_commit(htlc_msat, payment_hash.clone(),
2490+
htlc_cltv, HTLCSource::OutboundRoute {
2491+
path: path.clone(),
2492+
session_priv: session_priv.clone(),
2493+
first_hop_htlc_msat: htlc_msat,
2494+
payment_id,
2495+
payment_secret: payment_secret.clone(),
2496+
payment_params: payment_params.clone(),
2497+
}, onion_packet, &self.logger);
2498+
match break_chan_entry!(self, send_res, chan) {
2499+
Some(monitor_update) => {
2500+
let update_id = monitor_update.update_id;
2501+
let update_res = self.chain_monitor.update_channel(funding_txo, monitor_update);
2502+
if let Err(e) = handle_new_monitor_update!(self, update_res, update_id, peer_state_lock, peer_state, chan) {
2503+
break Err(e);
2504+
}
2505+
if update_res == ChannelMonitorUpdateStatus::InProgress {
2506+
// Note that MonitorUpdateInProgress here indicates (per function
2507+
// docs) that we will resend the commitment update once monitor
2508+
// updating completes. Therefore, we must return an error
2509+
// indicating that it is unsafe to retry the payment wholesale,
2510+
// which we do in the send_payment check for
2511+
// MonitorUpdateInProgress, below.
2512+
return Err(APIError::MonitorUpdateInProgress);
25192513
}
2520-
2521-
log_debug!(self.logger, "Sending payment along path resulted in a commitment_signed for channel {}", log_bytes!(chan_id));
2522-
peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
2523-
node_id: path.first().unwrap().pubkey,
2524-
updates: msgs::CommitmentUpdate {
2525-
update_add_htlcs: vec![update_add],
2526-
update_fulfill_htlcs: Vec::new(),
2527-
update_fail_htlcs: Vec::new(),
2528-
update_fail_malformed_htlcs: Vec::new(),
2529-
update_fee: None,
2530-
commitment_signed,
2531-
},
2532-
});
25332514
},
25342515
None => { },
25352516
}

0 commit comments

Comments
 (0)