Skip to content

Commit c58cba3

Browse files
committed
Clear stale monitor pending resends on reestablish
A stale ChannelManager can be reloaded after a monitor update has already completed in a prior runtime and released its post-update messages to the counterparty. The latest ChannelMonitor is not stale, but the serialized manager may still contain the old in-flight monitor state and `monitor_pending_*` resend flags from before the completion action ran. This becomes observable when startup monitor-completion background events are interleaved with splice promotion. On reload, the completed monitor update is queued as a background event. If a splice confirmation is processed before that background event fully resumes the channel, splice promotion can create a new `RenegotiatedFundingLocked` monitor update. The old completion is then blocked behind the new in-flight splice update. Once the channel reconnects and the splice update completes, `monitor_updating_restored` may consume the stale `monitor_pending_revoke_and_ack` / `monitor_pending_commitment_signed` flags and release a duplicate `revoke_and_ack` or `commitment_signed`. The peer's `channel_reestablish` commitment numbers are authoritative for this case. If `next_remote_commitment_number` says the peer is not waiting for a `revoke_and_ack`, clear `monitor_pending_revoke_and_ack`. Likewise, if `next_local_commitment_number` says the peer already has our latest `commitment_signed`, clear `monitor_pending_commitment_signed`.
1 parent f0c4af9 commit c58cba3

3 files changed

Lines changed: 154 additions & 1 deletion

File tree

lightning/src/ln/channel.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10714,6 +10714,9 @@ where
1071410714
let required_revoke = if msg.next_remote_commitment_number == our_commitment_transaction {
1071510715
// Remote isn't waiting on any RevokeAndACK from us!
1071610716
// Note that if we need to repeat our ChannelReady we'll do that in the next if block.
10717+
// If a stale ChannelManager replayed a completed update, the monitor-pending state may
10718+
// still think we owe one; the reestablish proof is authoritative here.
10719+
self.context.monitor_pending_revoke_and_ack = false;
1071710720
None
1071810721
} else if msg.next_remote_commitment_number + 1 == our_commitment_transaction {
1071910722
if self.context.channel_state.is_monitor_update_in_progress() {
@@ -10800,6 +10803,9 @@ where
1080010803
});
1080110804

1080210805
if msg.next_local_commitment_number == next_counterparty_commitment_number {
10806+
// If a stale ChannelManager replayed a completed update, the monitor-pending state may
10807+
// still think we owe one.
10808+
self.context.monitor_pending_commitment_signed = false;
1080310809
if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack {
1080410810
log_debug!(logger, "Reconnected with only lost outbound RAA");
1080510811
} else {

lightning/src/ln/functional_test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ pub fn get_updates_and_revoke<CM: AChannelManager, H: NodeHolder<CM = CM>>(
10231023
macro_rules! get_event_msg {
10241024
($node: expr, $event_type: path, $node_id: expr) => {{
10251025
let events = $node.node.get_and_clear_pending_msg_events();
1026-
assert_eq!(events.len(), 1);
1026+
assert_eq!(events.len(), 1, "{events:?}");
10271027
match events[0] {
10281028
$event_type { ref node_id, ref msg } => {
10291029
assert_eq!(*node_id, $node_id);

lightning/src/ln/splicing_tests.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,6 +3191,153 @@ fn test_holding_cell_claim_freed_after_inferred_splice_locked() {
31913191
.remove_watched_txn_and_outputs(prev_funding_outpoint, prev_funding_script);
31923192
}
31933193

3194+
#[test]
3195+
fn test_stale_monitor_pending_resends_cleared_by_reestablish() {
3196+
// A stale ChannelManager may be reloaded after a monitor update completed and released its
3197+
// messages to the peer. If a later splice-locked monitor update is in-flight while the channel
3198+
// reestablishes, completing it must not release the stale messages again.
3199+
let chanmon_cfgs = create_chanmon_cfgs(2);
3200+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
3201+
let persister;
3202+
let chain_monitor;
3203+
let node_1_reload;
3204+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
3205+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
3206+
3207+
let node_id_0 = nodes[0].node.get_our_node_id();
3208+
let node_id_1 = nodes[1].node.get_our_node_id();
3209+
3210+
let initial_channel_value_sat = 100_000;
3211+
let (_, _, channel_id, _) =
3212+
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, initial_channel_value_sat, 0);
3213+
let prev_funding_outpoint = get_monitor!(nodes[1], channel_id).get_funding_txo();
3214+
let prev_funding_script = get_monitor!(nodes[1], channel_id).get_funding_script();
3215+
3216+
let outputs = vec![
3217+
TxOut {
3218+
value: Amount::from_sat(initial_channel_value_sat / 4),
3219+
script_pubkey: nodes[0].wallet_source.get_change_script().unwrap(),
3220+
},
3221+
TxOut {
3222+
value: Amount::from_sat(initial_channel_value_sat / 4),
3223+
script_pubkey: nodes[1].wallet_source.get_change_script().unwrap(),
3224+
},
3225+
];
3226+
let funding_contribution =
3227+
initiate_splice_out(&nodes[0], &nodes[1], channel_id, outputs).unwrap();
3228+
let (splice_tx, _) = splice_channel(&nodes[0], &nodes[1], channel_id, funding_contribution);
3229+
3230+
// Only let node 0 see the splice lock for now.
3231+
confirm_transaction(&nodes[0], &splice_tx);
3232+
let splice_locked_0 = get_event_msg!(nodes[0], MessageSendEvent::SendSpliceLocked, node_id_1);
3233+
nodes[1].node.handle_splice_locked(node_id_0, &splice_locked_0);
3234+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3235+
3236+
// Send an HTLC from node 0 to 1 that will get fully committed to.
3237+
let payment_amount = 1_000_000;
3238+
let (route, payment_hash, _payment_preimage, payment_secret) =
3239+
get_route_and_payment_hash!(nodes[0], nodes[1], payment_amount);
3240+
let onion = RecipientOnionFields::secret_only(payment_secret, payment_amount);
3241+
let payment_id = PaymentId(payment_hash.0);
3242+
nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
3243+
let htlc_update = get_htlc_update_msgs(&nodes[0], &node_id_1);
3244+
check_added_monitors(&nodes[0], 1);
3245+
3246+
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
3247+
nodes[1].node.handle_update_add_htlc(node_id_0, &htlc_update.update_add_htlcs[0]);
3248+
nodes[1].node.handle_commitment_signed_batch_test(node_id_0, &htlc_update.commitment_signed);
3249+
check_added_monitors(&nodes[1], 1);
3250+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3251+
3252+
// Persist the `ChannelManager` while node 1 is still pending to send their RAA+CS to node 0.
3253+
let stale_manager_1 = nodes[1].node.encode();
3254+
3255+
// Let node 1 release its RAA+CS to node 0 and process them.
3256+
nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
3257+
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
3258+
let (raa, commitment_signed) = get_revoke_commit_msgs(&nodes[1], &node_id_0);
3259+
nodes[0].node.handle_revoke_and_ack(node_id_1, &raa);
3260+
check_added_monitors(&nodes[0], 1);
3261+
nodes[0].node.handle_commitment_signed_batch_test(node_id_1, &commitment_signed);
3262+
check_added_monitors(&nodes[0], 1);
3263+
let _dropped_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_id_1);
3264+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3265+
3266+
// Reload node 1 with the stale `ChannelManager` and confirm the splice.
3267+
nodes[0].node.peer_disconnected(node_id_1);
3268+
nodes[1].node.peer_disconnected(node_id_0);
3269+
let latest_monitor_1 = get_monitor!(nodes[1], channel_id).encode();
3270+
reload_node!(
3271+
nodes[1],
3272+
&stale_manager_1,
3273+
&[&latest_monitor_1],
3274+
persister,
3275+
chain_monitor,
3276+
node_1_reload
3277+
);
3278+
3279+
mine_transaction_without_consistency_checks(&nodes[1], &splice_tx);
3280+
connect_blocks(&nodes[1], 5);
3281+
persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
3282+
3283+
// Reestablish the channel. While the `ChannelManager` should think it still owes node 0 its
3284+
// RAA+CS, it should determine from node 0's `channel_reestablish` that they were already
3285+
// delivered.
3286+
connect_nodes(&nodes[0], &nodes[1]);
3287+
check_added_monitors(&nodes[1], 1);
3288+
let reestablish_0 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
3289+
let reestablish_1 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
3290+
nodes[1].node.handle_channel_reestablish(node_id_0, reestablish_0.first().unwrap());
3291+
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
3292+
assert!(
3293+
msg_events.iter().all(|event| !matches!(
3294+
event,
3295+
MessageSendEvent::SendRevokeAndACK { .. } | MessageSendEvent::UpdateHTLCs { .. }
3296+
)),
3297+
"stale monitor-pending resend leaked during reestablish: {msg_events:?}"
3298+
);
3299+
3300+
nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
3301+
persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
3302+
3303+
let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
3304+
assert!(
3305+
msg_events.iter().all(|event| !matches!(
3306+
event,
3307+
MessageSendEvent::SendRevokeAndACK { .. } | MessageSendEvent::UpdateHTLCs { .. }
3308+
)),
3309+
"stale monitor-pending resend leaked after reestablish: {msg_events:?}"
3310+
);
3311+
expect_channel_ready_event(&nodes[1], &node_id_0);
3312+
3313+
nodes[0].node.handle_channel_reestablish(node_id_1, reestablish_1.first().unwrap());
3314+
check_added_monitors(&nodes[0], 1);
3315+
expect_channel_ready_event(&nodes[0], &node_id_1);
3316+
3317+
// Finish fully committing the HTLC and make sure we can still send more payments.
3318+
let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
3319+
assert_eq!(msg_events.len(), 3, "{msg_events:?}");
3320+
if let MessageSendEvent::SendRevokeAndACK { msg, .. } = &msg_events[0] {
3321+
nodes[1].node.handle_revoke_and_ack(node_id_0, msg);
3322+
check_added_monitors(&nodes[1], 1);
3323+
nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
3324+
persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
3325+
3326+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
3327+
nodes[1].node.process_pending_htlc_forwards();
3328+
expect_payment_claimable!(&nodes[1], payment_hash, payment_secret, payment_amount);
3329+
} else {
3330+
panic!("Unexpected event {:?}", &msg_events[0]);
3331+
}
3332+
3333+
send_payment(&nodes[0], &[&nodes[1]], payment_amount);
3334+
3335+
for node in &[&nodes[0], &nodes[1]] {
3336+
node.chain_source
3337+
.remove_watched_txn_and_outputs(prev_funding_outpoint, prev_funding_script.clone());
3338+
}
3339+
}
3340+
31943341
#[test]
31953342
fn test_stale_announcement_signatures_ignored_after_splice_lock() {
31963343
// Regression test: a peer may transmit `announcement_signatures` signed over a pre-splice

0 commit comments

Comments
 (0)