Skip to content

Commit 0266a4c

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 0a32497 commit 0266a4c

File tree

2 files changed

+29
-50
lines changed

2 files changed

+29
-50
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5663,15 +5663,6 @@ impl<Signer: Sign> Channel<Signer> {
56635663
Ok(Some(res))
56645664
}
56655665

5666-
/// Only fails in case of signer rejection.
5667-
fn send_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> Result<(msgs::CommitmentSigned, ChannelMonitorUpdate), ChannelError> where L::Target: Logger {
5668-
let monitor_update = self.build_commitment_no_status_check(logger);
5669-
match self.send_commitment_no_state_update(logger) {
5670-
Ok((commitment_signed, _)) => Ok((commitment_signed, monitor_update)),
5671-
Err(e) => Err(e),
5672-
}
5673-
}
5674-
56755666
fn build_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger {
56765667
log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
56775668
// We can upgrade the status of some HTLCs that are waiting on a commitment, even if we
@@ -5798,16 +5789,20 @@ impl<Signer: Sign> Channel<Signer> {
57985789
}, (counterparty_commitment_txid, commitment_stats.htlcs_included)))
57995790
}
58005791

5801-
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
5802-
/// to send to the remote peer in one go.
5792+
/// Adds a pending outbound HTLC to this channel, and builds a new remote commitment
5793+
/// transaction and generates the corresponding [`ChannelMonitorUpdate`] in one go.
58035794
///
58045795
/// Shorthand for calling [`Self::send_htlc`] followed by a commitment update, see docs on
5805-
/// [`Self::send_htlc`] and [`Self::send_commitment_no_state_update`] for more info.
5806-
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 {
5807-
match self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger)? {
5808-
Some(update_add_htlc) => {
5809-
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check(logger)?;
5810-
Ok(Some((update_add_htlc, commitment_signed, monitor_update)))
5796+
/// [`Self::send_htlc`] and [`Self::build_commitment_no_state_update`] for more info.
5797+
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 {
5798+
let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, false, logger);
5799+
if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } }
5800+
match send_res? {
5801+
Some(_) => {
5802+
let monitor_update = self.build_commitment_no_status_check(logger);
5803+
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
5804+
self.pending_monitor_updates.push(monitor_update);
5805+
Ok(Some(self.pending_monitor_updates.last().unwrap()))
58115806
},
58125807
None => Ok(None)
58135808
}

lightning/src/ln/channelmanager.rs

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,6 +2399,7 @@ where
23992399
if !chan.get().is_live() {
24002400
return Err(APIError::ChannelUnavailable{err: "Peer for first hop currently disconnected/pending monitor update!".to_owned()});
24012401
}
2402+
(chan.get().get_funding_txo().unwrap(),
24022403
break_chan_entry!(self, chan.get_mut().send_htlc_and_commit(
24032404
htlc_msat, payment_hash.clone(), htlc_cltv, HTLCSource::OutboundRoute {
24042405
path: path.clone(),
@@ -2409,42 +2410,25 @@ where
24092410
payment_params: payment_params.clone(),
24102411
}, onion_packet, &self.logger),
24112412
chan)
2413+
)
24122414
} {
2413-
Some((update_add, commitment_signed, monitor_update)) => {
2414-
let update_err = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), &monitor_update);
2415-
let chan_id = chan.get().channel_id();
2416-
match (update_err,
2417-
handle_monitor_update_res!(self, update_err, chan,
2418-
RAACommitmentOrder::CommitmentFirst, false, true))
2419-
{
2420-
(ChannelMonitorUpdateStatus::PermanentFailure, Err(e)) => break Err(e),
2421-
(ChannelMonitorUpdateStatus::Completed, Ok(())) => {},
2422-
(ChannelMonitorUpdateStatus::InProgress, Err(_)) => {
2423-
// Note that MonitorUpdateInProgress here indicates (per function
2424-
// docs) that we will resend the commitment update once monitor
2425-
// updating completes. Therefore, we must return an error
2426-
// indicating that it is unsafe to retry the payment wholesale,
2427-
// which we do in the send_payment check for
2428-
// MonitorUpdateInProgress, below.
2429-
return Err(APIError::MonitorUpdateInProgress);
2430-
},
2431-
_ => unreachable!(),
2415+
(funding_txo, Some(monitor_update)) => {
2416+
let update_id = monitor_update.update_id;
2417+
let update_res = self.chain_monitor.update_channel(funding_txo, monitor_update);
2418+
if let Err(e) = handle_new_monitor_update!(self, update_res, update_id, peer_state_lock, peer_state, chan) {
2419+
break Err(e);
2420+
}
2421+
if update_res == ChannelMonitorUpdateStatus::InProgress {
2422+
// Note that MonitorUpdateInProgress here indicates (per function
2423+
// docs) that we will resend the commitment update once monitor
2424+
// updating completes. Therefore, we must return an error
2425+
// indicating that it is unsafe to retry the payment wholesale,
2426+
// which we do in the send_payment check for
2427+
// MonitorUpdateInProgress, below.
2428+
return Err(APIError::MonitorUpdateInProgress);
24322429
}
2433-
2434-
log_debug!(self.logger, "Sending payment along path resulted in a commitment_signed for channel {}", log_bytes!(chan_id));
2435-
peer_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
2436-
node_id: path.first().unwrap().pubkey,
2437-
updates: msgs::CommitmentUpdate {
2438-
update_add_htlcs: vec![update_add],
2439-
update_fulfill_htlcs: Vec::new(),
2440-
update_fail_htlcs: Vec::new(),
2441-
update_fail_malformed_htlcs: Vec::new(),
2442-
update_fee: None,
2443-
commitment_signed,
2444-
},
2445-
});
24462430
},
2447-
None => { },
2431+
(_, None) => { },
24482432
}
24492433
} else {
24502434
// The channel was likely removed after we fetched the id from the

0 commit comments

Comments
 (0)