Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Setup Support for delaying `ChannelMonitorUpdate` flight until an `Event` completes by TheBlueMatt · Pull Request #2111 · lightningdevkit/rust-lightning · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lightning/src/ln/chanmon_update_fail_tests.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,7 @@ fn test_monitor_and_persister_update_fail() {
let mut node_0_per_peer_lock;
let mut node_0_peer_state_lock;
let mut channel = get_channel_ref!(nodes[0], nodes[1], node_0_per_peer_lock, node_0_peer_state_lock, chan.2);
if let Ok(update) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
if let Ok(Some(update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].logger) {
// Check that even though the persister is returning a InProgress,
// because the update is bogus, ultimately the error that's returned
// should be a PermanentFailure.
Expand Down
173 changes: 128 additions & 45 deletions lightning/src/ln/channel.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -479,6 +479,21 @@ pub(crate) const MIN_AFFORDABLE_HTLC_COUNT: usize = 4;
/// * `EXPIRE_PREV_CONFIG_TICKS` = convergence_delay / tick_interval
pub(crate) const EXPIRE_PREV_CONFIG_TICKS: usize = 5;

struct PendingChannelMonitorUpdate {
update: ChannelMonitorUpdate,
/// In some cases we need to delay letting the [`ChannelMonitorUpdate`] go until after an
/// `Event` is processed by the user. This bool indicates the [`ChannelMonitorUpdate`] is
/// blocked on some external event and the [`ChannelManager`] will update us when we're ready.
///
/// [`ChannelManager`]: super::channelmanager::ChannelManager
blocked: bool,
}

impl_writeable_tlv_based!(PendingChannelMonitorUpdate, {
(0, update, required),
(2, blocked, required),
});

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Expand DownExpand Up@@ -744,7 +759,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
/// If we then persist the [`channelmanager::ChannelManager`] and crash before the persistence
/// completes we still need to be able to complete the persistence. Thus, we have to keep a
/// copy of the [`ChannelMonitorUpdate`] here until it is complete.
pending_monitor_updates: Vec<ChannelMonitorUpdate>,
pending_monitor_updates: Vec<PendingChannelMonitorUpdate>,
}

#[cfg(any(test, fuzzing))]
Expand DownExpand Up@@ -1979,28 +1994,52 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}

pub fn get_update_fulfill_htlc_and_commit<L: Deref>(&mut self, htlc_id: u64, payment_preimage: PaymentPreimage, logger: &L) -> UpdateFulfillCommitFetch where L::Target: Logger {
let release_cs_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
Comment thread
valentinewallace marked this conversation as resolved.
Comment thread
wpaulino marked this conversation as resolved.
match self.get_update_fulfill_htlc(htlc_id, payment_preimage, logger) {
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg: Some(_) } => {
let mut additional_update = self.build_commitment_no_status_check(logger);
// build_commitment_no_status_check may bump latest_monitor_id but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillFetch::NewClaim { mut monitor_update, htlc_value_msat, msg } => {
Comment thread
wpaulino marked this conversation as resolved.
// Even if we aren't supposed to let new monitor updates with commitment state
// updates run, we still need to push the preimage ChannelMonitorUpdateStep no
// matter what. Sadly, to push a new monitor update which flies before others
// already queued, we have to insert it into the pending queue and update the
// update_ids of all the following monitors.
let unblocked_update_pos = if release_cs_monitor && msg.is_some() {
let mut additional_update = self.build_commitment_no_status_check(logger);
Comment thread
TheBlueMatt marked this conversation as resolved.
// build_commitment_no_status_check may bump latest_monitor_id but we want them
// to be strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
self.pending_monitor_updates.len() - 1
} else {
let insert_pos = self.pending_monitor_updates.iter().position(|upd| upd.blocked)
.unwrap_or(self.pending_monitor_updates.len());
let new_mon_id = self.pending_monitor_updates.get(insert_pos)
.map(|upd| upd.update.update_id).unwrap_or(monitor_update.update_id);
monitor_update.update_id = new_mon_id;
self.pending_monitor_updates.insert(insert_pos, PendingChannelMonitorUpdate {
update: monitor_update, blocked: false,
});
for held_update in self.pending_monitor_updates.iter_mut().skip(insert_pos + 1) {
held_update.update.update_id += 1;
}
if msg.is_some() {
debug_assert!(false, "If there is a pending blocked monitor we should have MonitorUpdateInProgress set");
let update = self.build_commitment_no_status_check(logger);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
Comment thread
wpaulino marked this conversation as resolved.
update, blocked: true,
});
}
insert_pos
};
self.monitor_updating_paused(false, msg.is_some(), false, Vec::new(), Vec::new(), Vec::new());
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
monitor_update: &self.pending_monitor_updates.get(unblocked_update_pos)
.expect("We just pushed the monitor update").update,
htlc_value_msat,
}
},
UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None } => {
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
UpdateFulfillCommitFetch::NewClaim {
monitor_update: self.pending_monitor_updates.last().unwrap(),
htlc_value_msat,
}
}
UpdateFulfillFetch::DuplicateClaim {} => UpdateFulfillCommitFetch::DuplicateClaim {},
}
}
Expand DownExpand Up@@ -3068,7 +3107,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Ok(())
}

pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<&ChannelMonitorUpdate, ChannelError>
pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
where L::Target: Logger
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3268,8 +3307,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}
log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updated HTLC state but awaiting a monitor update resolution to reply.",
log_bytes!(self.channel_id));
self.pending_monitor_updates.push(monitor_update);
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

let need_commitment_signed = if need_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
Expand All@@ -3286,9 +3324,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {

log_debug!(logger, "Received valid commitment_signed from peer in channel {}, updating HTLC state and responding with{} a revoke_and_ack.",
log_bytes!(self.channel_id()), if need_commitment_signed { " our own commitment_signed and" } else { "" });
self.pending_monitor_updates.push(monitor_update);
self.monitor_updating_paused(true, need_commitment_signed, false, Vec::new(), Vec::new(), Vec::new());
return Ok(self.pending_monitor_updates.last().unwrap());
return Ok(self.push_ret_blockable_mon_update(monitor_update));
}

/// Public version of the below, checking relevant preconditions first.
Expand DownExpand Up@@ -3403,8 +3440,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
update_add_htlcs.len(), update_fulfill_htlcs.len(), update_fail_htlcs.len());

self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
(Some(self.pending_monitor_updates.last().unwrap()), htlcs_to_fail)
(self.push_ret_blockable_mon_update(monitor_update), htlcs_to_fail)
} else {
(None, Vec::new())
}
Expand All@@ -3415,7 +3451,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, &ChannelMonitorUpdate), ChannelError>
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
where L::Target: Logger,
{
if (self.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
Expand DownExpand Up@@ -3612,21 +3648,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
self.monitor_pending_failures.append(&mut revoked_htlcs);
self.monitor_pending_finalized_fulfills.append(&mut finalized_claimed_htlcs);
log_debug!(logger, "Received a valid revoke_and_ack for channel {} but awaiting a monitor update resolution to reply.", log_bytes!(self.channel_id()));
self.pending_monitor_updates.push(monitor_update);
return Ok((Vec::new(), self.pending_monitor_updates.last().unwrap()));
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
}

match self.free_holding_cell_htlcs(logger) {
(Some(_), htlcs_to_fail) => {
let mut additional_update = self.pending_monitor_updates.pop().unwrap();
let mut additional_update = self.pending_monitor_updates.pop().unwrap().update;
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
// strictly increasing by one, so decrement it here.
self.latest_monitor_update_id = monitor_update.update_id;
monitor_update.updates.append(&mut additional_update.updates);

self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
},
(None, htlcs_to_fail) => {
if require_commitment {
Expand All@@ -3640,13 +3674,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
log_debug!(logger, "Received a valid revoke_and_ack for channel {}. Responding with a commitment update with {} HTLCs failed.",
log_bytes!(self.channel_id()), update_fail_htlcs.len() + update_fail_malformed_htlcs.len());
self.monitor_updating_paused(false, true, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
} else {
log_debug!(logger, "Received a valid revoke_and_ack for channel {} with no reply necessary.", log_bytes!(self.channel_id()));
self.monitor_updating_paused(false, false, false, to_forward_infos, revoked_htlcs, finalized_claimed_htlcs);
self.pending_monitor_updates.push(monitor_update);
Ok((htlcs_to_fail, self.pending_monitor_updates.last().unwrap()))
Ok((htlcs_to_fail, self.push_ret_blockable_mon_update(monitor_update)))
}
}
}
Expand DownExpand Up@@ -3835,7 +3867,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
{
assert_eq!(self.channel_state & ChannelState::MonitorUpdateInProgress as u32, ChannelState::MonitorUpdateInProgress as u32);
self.channel_state &= !(ChannelState::MonitorUpdateInProgress as u32);
self.pending_monitor_updates.clear();
let mut found_blocked = false;
self.pending_monitor_updates.retain(|upd| {
if found_blocked { debug_assert!(upd.blocked, "No mons may be unblocked after a blocked one"); }
if upd.blocked { found_blocked = true; }
upd.blocked
});

// If we're past (or at) the FundingSent stage on an outbound channel, try to
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
Expand DownExpand Up@@ -4378,8 +4415,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
Comment thread
wpaulino marked this conversation as resolved.
} else { None };
let shutdown = if send_shutdown {
Some(msgs::Shutdown {
Expand DownExpand Up@@ -4951,8 +4989,49 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
(self.channel_state & ChannelState::MonitorUpdateInProgress as u32) != 0
}

pub fn get_next_monitor_update(&self) -> Option<&ChannelMonitorUpdate> {
self.pending_monitor_updates.first()
pub fn get_latest_complete_monitor_update_id(&self) -> u64 {
if self.pending_monitor_updates.is_empty() { return self.get_latest_monitor_update_id(); }
self.pending_monitor_updates[0].update.update_id - 1
Comment thread
wpaulino marked this conversation as resolved.
}

/// Returns the next blocked monitor update, if one exists, and a bool which indicates a
/// further blocked monitor update exists after the next.
pub fn unblock_next_blocked_monitor_update(&mut self) -> Option<(&ChannelMonitorUpdate, bool)> {
for i in 0..self.pending_monitor_updates.len() {
if self.pending_monitor_updates[i].blocked {
self.pending_monitor_updates[i].blocked = false;
return Some((&self.pending_monitor_updates[i].update,
self.pending_monitor_updates.len() > i + 1));
}
}
None
}

/// Pushes a new monitor update into our monitor update queue, returning whether it should be
/// immediately given to the user for persisting or if it should be held as blocked.
fn push_blockable_mon_update(&mut self, update: ChannelMonitorUpdate) -> bool {
let release_monitor = self.pending_monitor_updates.iter().all(|upd| !upd.blocked);
self.pending_monitor_updates.push(PendingChannelMonitorUpdate {
update, blocked: !release_monitor
});
release_monitor
}

/// Pushes a new monitor update into our monitor update queue, returning a reference to it if
/// it should be immediately given to the user for persisting or `None` if it should be held as
/// blocked.
fn push_ret_blockable_mon_update(&mut self, update: ChannelMonitorUpdate)
-> Option<&ChannelMonitorUpdate> {
let release_monitor = self.push_blockable_mon_update(update);
if release_monitor { self.pending_monitor_updates.last().map(|upd| &upd.update) } else { None }
}

pub fn no_monitor_updates_pending(&self) -> bool {
self.pending_monitor_updates.is_empty()
}

pub fn complete_one_mon_update(&mut self, update_id: u64) {
self.pending_monitor_updates.retain(|upd| upd.update.update_id != update_id);
}

/// Returns true if funding_created was sent/received.
Expand DownExpand Up@@ -6000,8 +6079,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
Some(_) => {
let monitor_update = self.build_commitment_no_status_check(logger);
self.monitor_updating_paused(false, true, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Ok(Some(self.pending_monitor_updates.last().unwrap()))
Ok(self.push_ret_blockable_mon_update(monitor_update))
},
None => Ok(None)
}
Expand DownExpand Up@@ -6090,8 +6168,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
}],
};
self.monitor_updating_paused(false, false, false, Vec::new(), Vec::new(), Vec::new());
self.pending_monitor_updates.push(monitor_update);
Some(self.pending_monitor_updates.last().unwrap())
if self.push_blockable_mon_update(monitor_update) {
self.pending_monitor_updates.last().map(|upd| &upd.update)
} else { None }
} else { None };
let shutdown = msgs::Shutdown {
channel_id: self.channel_id,
Expand DownExpand Up@@ -6528,6 +6607,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
(28, holder_max_accepted_htlcs, option),
(29, self.temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, self.pending_monitor_updates, vec_type),
});

Ok(())
Expand DownExpand Up@@ -6804,6 +6884,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut temporary_channel_id: Option<[u8; 32]> = None;
let mut holder_max_accepted_htlcs: Option<u16> = None;

let mut pending_monitor_updates = Some(Vec::new());

read_tlv_fields!(reader, {
(0, announcement_sigs, option),
(1, minimum_depth, option),
Expand All@@ -6826,6 +6908,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
(28, holder_max_accepted_htlcs, option),
(29, temporary_channel_id, option),
(31, channel_pending_event_emitted, option),
(33, pending_monitor_updates, vec_type),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand DownExpand Up@@ -6995,7 +7078,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
channel_type: channel_type.unwrap(),
channel_keys_id,

pending_monitor_updates: Vec::new(),
pending_monitor_updates: pending_monitor_updates.unwrap(),
})
}
}
Expand Down
Loading