Skip to content

Commit 6bf73ec

Browse files
committed
f Track event emission in channel and emit upon chan resumption
We track whether the event had previously been emitted in `Channel` and remove it from `internal_funding_created` entirely. Hence, we now only emit the event after ChannelMonitorUpdate completion, or upon channel reestablish. This mitigates a race condition where where we wouldn't persist the event *and* wouldn't regenerate it on restart, therefore potentially losing it, if async CMU wouldn't complete before ChannelManager persistence.
1 parent ad81db7 commit 6bf73ec

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,7 +1854,6 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
18541854
let channel_id = OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id();
18551855
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
18561856
check_added_monitors!(nodes[1], 1);
1857-
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
18581857

18591858
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
18601859
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()));
@@ -1887,6 +1886,9 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
18871886
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
18881887
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
18891888
reconnect_nodes(&nodes[0], &nodes[1], (false, confirm_a_first), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
1889+
1890+
// But we want to re-emit ChannelPending
1891+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
18901892
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
18911893
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
18921894

@@ -2901,7 +2903,6 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo
29012903
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
29022904
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
29032905
check_added_monitors!(nodes[1], 1);
2904-
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
29052906

29062907
// nodes[1] happily sends its funding_signed even though its awaiting the persistence of the
29072908
// initial ChannelMonitor, but it will decline to send its channel_ready even if the funding

lightning/src/ln/channel.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,9 @@ pub(super) struct Channel<Signer: ChannelSigner> {
730730
// blinded paths instead of simple scid+node_id aliases.
731731
outbound_scid_alias: u64,
732732

733+
// We track whether we already emitted a `ChannelPending` event.
734+
channel_pending_event_emitted: bool,
735+
733736
// We track whether we already emitted a `ChannelReady` event.
734737
channel_ready_event_emitted: bool,
735738

@@ -1107,6 +1110,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
11071110
latest_inbound_scid_alias: None,
11081111
outbound_scid_alias,
11091112

1113+
channel_pending_event_emitted: false,
11101114
channel_ready_event_emitted: false,
11111115

11121116
#[cfg(any(test, fuzzing))]
@@ -1456,6 +1460,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
14561460
latest_inbound_scid_alias: None,
14571461
outbound_scid_alias,
14581462

1463+
channel_pending_event_emitted: false,
14591464
channel_ready_event_emitted: false,
14601465

14611466
#[cfg(any(test, fuzzing))]
@@ -4706,6 +4711,16 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
47064711
self.prev_config.map(|prev_config| prev_config.0)
47074712
}
47084713

4714+
// Checks whether we should emit a `ChannelPending` event.
4715+
pub(crate) fn should_emit_channel_pending_event(&mut self) -> bool {
4716+
self.is_funding_initiated() && !self.channel_pending_event_emitted
4717+
}
4718+
4719+
// Remembers that we already emitted a `ChannelPending` event.
4720+
pub(crate) fn set_channel_pending_event_emitted(&mut self) {
4721+
self.channel_pending_event_emitted = true;
4722+
}
4723+
47094724
// Checks whether we should emit a `ChannelReady` event.
47104725
pub(crate) fn should_emit_channel_ready_event(&mut self) -> bool {
47114726
self.is_usable() && !self.channel_ready_event_emitted
@@ -6432,6 +6447,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
64326447
if self.holder_max_htlc_value_in_flight_msat != Self::get_holder_max_htlc_value_in_flight_msat(self.channel_value_satoshis, &old_max_in_flight_percent_config)
64336448
{ Some(self.holder_max_htlc_value_in_flight_msat) } else { None };
64346449

6450+
let channel_pending_event_emitted = Some(self.channel_pending_event_emitted);
64356451
let channel_ready_event_emitted = Some(self.channel_ready_event_emitted);
64366452

64376453
// `user_id` used to be a single u64 value. In order to remain backwards compatible with
@@ -6465,6 +6481,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
64656481
(25, user_id_high_opt, option),
64666482
(27, self.channel_keys_id, required),
64676483
(29, self.temporary_channel_id, option),
6484+
(31, channel_pending_event_emitted, option),
64686485
});
64696486

64706487
Ok(())
@@ -6732,6 +6749,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
67326749
let mut announcement_sigs_state = Some(AnnouncementSigsState::NotSent);
67336750
let mut latest_inbound_scid_alias = None;
67346751
let mut outbound_scid_alias = None;
6752+
let mut channel_pending_event_emitted = None;
67356753
let mut channel_ready_event_emitted = None;
67366754

67376755
let mut user_id_high_opt: Option<u64> = None;
@@ -6758,6 +6776,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
67586776
(25, user_id_high_opt, option),
67596777
(27, channel_keys_id, option),
67606778
(29, temporary_channel_id, option),
6779+
(31, channel_pending_event_emitted, option),
67616780
});
67626781

67636782
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
@@ -6915,6 +6934,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
69156934
// Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
69166935
outbound_scid_alias: outbound_scid_alias.unwrap_or(0),
69176936

6937+
channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true),
69186938
channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true),
69196939

69206940
#[cfg(any(test, fuzzing))]

lightning/src/ln/channelmanager.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4249,7 +4249,9 @@ where
42494249
if let Some(tx) = funding_broadcastable {
42504250
log_info!(self.logger, "Broadcasting funding transaction with txid {}", tx.txid());
42514251
self.tx_broadcaster.broadcast_transaction(&tx);
4252+
}
42524253

4254+
if channel.should_emit_channel_pending_event() {
42534255
let mut pending_events = self.pending_events.lock().unwrap();
42544256
pending_events.push(events::Event::ChannelPending {
42554257
channel_id: channel.channel_id(),
@@ -4258,6 +4260,7 @@ where
42584260
user_channel_id: channel.get_user_id(),
42594261
funding_txo: channel.get_funding_txo().unwrap().into_bitcoin_outpoint(),
42604262
});
4263+
channel.set_channel_pending_event_emitted();
42614264
}
42624265

42634266
emit_channel_ready_event!(self, channel);
@@ -4600,10 +4603,7 @@ where
46004603
msg: funding_msg,
46014604
});
46024605

4603-
let funding_txo = monitor.get_funding_txo().0;
4604-
let user_channel_id = chan.get_user_id();
4605-
4606-
let monitor_res = self.chain_monitor.watch_channel(funding_txo, monitor);
4606+
let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
46074607

46084608
let chan = e.insert(chan);
46094609
let mut res = handle_new_monitor_update!(self, monitor_res, 0, peer_state_lock, peer_state,
@@ -4618,15 +4618,6 @@ where
46184618
// with the funding_signed so the channel can never go on chain).
46194619
if let Err(MsgHandleErrInternal { shutdown_finish: Some((res, _)), .. }) = &mut res {
46204620
res.0 = None;
4621-
} else {
4622-
let mut pending_events = self.pending_events.lock().unwrap();
4623-
pending_events.push(events::Event::ChannelPending {
4624-
channel_id: new_channel_id,
4625-
former_temporary_channel_id: Some(msg.temporary_channel_id),
4626-
counterparty_node_id: *counterparty_node_id,
4627-
user_channel_id,
4628-
funding_txo: funding_txo.into_bitcoin_outpoint(),
4629-
});
46304621
}
46314622
res
46324623
}

lightning/src/ln/priv_short_conf_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,12 +597,12 @@ fn test_0conf_channel_with_async_monitor() {
597597

598598
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
599599
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
600-
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
601600
check_added_monitors!(nodes[1], 1);
602601
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
603602

604603
let channel_id = funding_output.to_channel_id();
605604
nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
605+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
606606

607607
let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
608608
assert_eq!(bs_signed_locked.len(), 2);

0 commit comments

Comments
 (0)