]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Add `ChannelPending` event emitted upon `funding_signed`
authorElias Rohrer <ero@tnull.de>
Fri, 10 Mar 2023 15:30:37 +0000 (16:30 +0100)
committerElias Rohrer <ero@tnull.de>
Mon, 3 Apr 2023 17:04:32 +0000 (19:04 +0200)
Currently, users don't have good way of being notified when channel open
negotiations have succeeded and new channels are pending confirmation on
chain. To this end, we add a new `ChannelPending` event that is emitted
when send or receive a `funding_signed` message, i.e., at the last
moment before waiting for the confirmation period.

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.

fuzz/src/chanmon_consistency.rs
lightning-background-processor/src/lib.rs
lightning/src/events/mod.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/priv_short_conf_tests.rs
lightning/src/ln/reload_tests.rs

index f6be6cdafb147b2837caaa7b4ec9f4d616123c34..56bd685d191eaaa4cf9260e5cc07186d22efe892 100644 (file)
@@ -526,7 +526,18 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
                                        msg.clone()
                                } else { panic!("Wrong event type"); }
                        };
+                       let events = $dest.get_and_clear_pending_events();
+                       assert_eq!(events.len(), 1);
+                       if let events::Event::ChannelPending{ ref counterparty_node_id, .. } = events[0] {
+                               assert_eq!(counterparty_node_id, &$source.get_our_node_id());
+                       } else { panic!("Wrong event type"); }
+
                        $source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed);
+                       let events = $source.get_and_clear_pending_events();
+                       assert_eq!(events.len(), 1);
+                       if let events::Event::ChannelPending{ ref counterparty_node_id, .. } = events[0] {
+                               assert_eq!(counterparty_node_id, &$dest.get_our_node_id());
+                       } else { panic!("Wrong event type"); }
 
                        funding_output
                } }
index 884a7c2266420eb17f568f5da4cb65d513f6cae1..541813c7e42c72f68568ec1c397fc531156d158c 100644 (file)
@@ -710,7 +710,7 @@ mod tests {
        use lightning::chain::keysinterface::{InMemorySigner, KeysManager};
        use lightning::chain::transaction::OutPoint;
        use lightning::events::{Event, PathFailure, MessageSendEventsProvider, MessageSendEvent};
-       use lightning::get_event_msg;
+       use lightning::{get_event_msg, get_event};
        use lightning::ln::PaymentHash;
        use lightning::ln::channelmanager;
        use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, MIN_CLTV_EXPIRY_DELTA, PaymentId};
@@ -1058,7 +1058,10 @@ mod tests {
                ($node_a: expr, $node_b: expr, $temporary_channel_id: expr, $tx: expr) => {{
                        $node_a.node.funding_transaction_generated(&$temporary_channel_id, &$node_b.node.get_our_node_id(), $tx.clone()).unwrap();
                        $node_b.node.handle_funding_created(&$node_a.node.get_our_node_id(), &get_event_msg!($node_a, MessageSendEvent::SendFundingCreated, $node_b.node.get_our_node_id()));
+                       get_event!($node_b, Event::ChannelPending);
+
                        $node_a.node.handle_funding_signed(&$node_b.node.get_our_node_id(), &get_event_msg!($node_b, MessageSendEvent::SendFundingSigned, $node_a.node.get_our_node_id()));
+                       get_event!($node_a, Event::ChannelPending);
                }}
        }
 
index a96d36b645312e6efe854a8ddb4f272db3b94532..2d576d33a0581404baf686b64587e65a6d0b3ab6 100644 (file)
@@ -32,7 +32,9 @@ use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReada
 use crate::util::string::UntrustedString;
 use crate::routing::router::{RouteHop, RouteParameters};
 
-use bitcoin::{PackedLockTime, Transaction};
+use bitcoin::{PackedLockTime, Transaction, OutPoint};
+#[cfg(anchors)]
+use bitcoin::{Txid, TxIn, TxOut, Witness};
 use bitcoin::blockdata::script::Script;
 use bitcoin::hashes::Hash;
 use bitcoin::hashes::sha256::Hash as Sha256;
@@ -608,12 +610,39 @@ pub enum Event {
                /// The caveat described above the `fee_earned_msat` field applies here as well.
                outbound_amount_forwarded_msat: Option<u64>,
        },
+       /// Used to indicate that a channel with the given `channel_id` is being opened and pending
+       /// confirmation on-chain.
+       ///
+       /// This event is emitted when the funding transaction has been signed and is broadcast to the
+       /// network. For 0conf channels it will be immediately followed by the corresponding
+       /// [`Event::ChannelReady`] event.
+       ChannelPending {
+               /// The `channel_id` of the channel that is pending confirmation.
+               channel_id: [u8; 32],
+               /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
+               /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
+               /// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
+               /// `user_channel_id` will be randomized for an inbound channel.
+               ///
+               /// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
+               /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
+               /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
+               user_channel_id: u128,
+               /// The `temporary_channel_id` this channel used to be known by during channel establishment.
+               ///
+               /// Will be `None` for channels created prior to LDK version 0.0.115.
+               former_temporary_channel_id: Option<[u8; 32]>,
+               /// The `node_id` of the channel counterparty.
+               counterparty_node_id: PublicKey,
+               /// The outpoint of the channel's funding transaction.
+               funding_txo: OutPoint,
+       },
        /// Used to indicate that a channel with the given `channel_id` is ready to
        /// be used. This event is emitted either when the funding transaction has been confirmed
        /// on-chain, or, in case of a 0conf channel, when both parties have confirmed the channel
        /// establishment.
        ChannelReady {
-               /// The channel_id of the channel that is ready.
+               /// The `channel_id` of the channel that is ready.
                channel_id: [u8; 32],
                /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
                /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
@@ -624,7 +653,7 @@ pub enum Event {
                /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
                /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
                user_channel_id: u128,
-               /// The node_id of the channel counterparty.
+               /// The `node_id` of the channel counterparty.
                counterparty_node_id: PublicKey,
                /// The features that this channel will operate with.
                channel_type: ChannelTypeFeatures,
@@ -632,7 +661,7 @@ pub enum Event {
        /// Used to indicate that a previously opened channel with the given `channel_id` is in the
        /// process of closure.
        ChannelClosed  {
-               /// The channel_id of the channel which has been closed. Note that on-chain transactions
+               /// The `channel_id` of the channel which has been closed. Note that on-chain transactions
                /// resolving the channel are likely still awaiting confirmation.
                channel_id: [u8; 32],
                /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
@@ -931,6 +960,16 @@ impl Writeable for Event {
                                        (6, channel_type, required),
                                });
                        },
+                       &Event::ChannelPending { ref channel_id, ref user_channel_id, ref former_temporary_channel_id, ref counterparty_node_id, ref funding_txo } => {
+                               31u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, channel_id, required),
+                                       (2, user_channel_id, required),
+                                       (4, former_temporary_channel_id, required),
+                                       (6, counterparty_node_id, required),
+                                       (8, funding_txo, required),
+                               });
+                       },
                        // Note that, going forward, all new events must only write data inside of
                        // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
                        // data via `write_tlv_fields`.
@@ -1271,6 +1310,31 @@ impl MaybeReadable for Event {
                                };
                                f()
                        },
+                       31u8 => {
+                               let f = || {
+                                       let mut channel_id = [0; 32];
+                                       let mut user_channel_id: u128 = 0;
+                                       let mut former_temporary_channel_id = None;
+                                       let mut counterparty_node_id = RequiredWrapper(None);
+                                       let mut funding_txo = RequiredWrapper(None);
+                                       read_tlv_fields!(reader, {
+                                               (0, channel_id, required),
+                                               (2, user_channel_id, required),
+                                               (4, former_temporary_channel_id, required),
+                                               (6, counterparty_node_id, required),
+                                               (8, funding_txo, required),
+                                       });
+
+                                       Ok(Some(Event::ChannelPending {
+                                               channel_id,
+                                               user_channel_id,
+                                               former_temporary_channel_id,
+                                               counterparty_node_id: counterparty_node_id.0.unwrap(),
+                                               funding_txo: funding_txo.0.unwrap()
+                                       }))
+                               };
+                               f()
+                       },
                        // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
                        // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
                        // reads.
index b57f70d7901d21aa57c5ebe954ad21ca92a276a8..94df7371a27b55205091a5900b6a87c06872975a 100644 (file)
@@ -1864,6 +1864,7 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
        let (outpoint, latest_update, _) = nodes[0].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone();
        nodes[0].chain_monitor.chain_monitor.force_channel_monitor_updated(outpoint, latest_update);
        check_added_monitors!(nodes[0], 0);
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
 
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 0);
@@ -1885,6 +1886,9 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
        reconnect_nodes(&nodes[0], &nodes[1], (false, confirm_a_first), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+       // But we want to re-emit ChannelPending
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 
@@ -2808,6 +2812,7 @@ fn do_test_outbound_reload_without_init_mon(use_0conf: bool) {
        let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
        check_added_monitors!(nodes[1], 1);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
        let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(bs_signed_locked.len(), if use_0conf { 2 } else { 1 });
@@ -2906,6 +2911,7 @@ fn do_test_inbound_reload_without_init_mon(use_0conf: bool, lock_commitment: boo
 
        nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
        check_added_monitors!(nodes[0], 1);
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
 
        let as_funding_tx = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
        if lock_commitment {
index f1c5cae25ae8bbfbc84b85640c3367de18aa56c1..666c48442668e2992e16585fb8d6d7f796fcd9e1 100644 (file)
@@ -499,6 +499,7 @@ pub(super) struct Channel<Signer: ChannelSigner> {
        user_id: u128,
 
        channel_id: [u8; 32],
+       temporary_channel_id: Option<[u8; 32]>, // Will be `None` for channels created prior to 0.0.115.
        channel_state: u32,
 
        // When we reach max(6 blocks, minimum_depth), we need to send an AnnouncementSigs message to
@@ -729,6 +730,9 @@ pub(super) struct Channel<Signer: ChannelSigner> {
        // blinded paths instead of simple scid+node_id aliases.
        outbound_scid_alias: u64,
 
+       // We track whether we already emitted a `ChannelPending` event.
+       channel_pending_event_emitted: bool,
+
        // We track whether we already emitted a `ChannelReady` event.
        channel_ready_event_emitted: bool,
 
@@ -991,6 +995,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        }
                }
 
+               let temporary_channel_id = entropy_source.get_secure_random_bytes();
+
                Ok(Channel {
                        user_id,
 
@@ -1004,7 +1010,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
 
                        inbound_handshake_limits_override: Some(config.channel_handshake_limits.clone()),
 
-                       channel_id: entropy_source.get_secure_random_bytes(),
+                       channel_id: temporary_channel_id,
+                       temporary_channel_id: Some(temporary_channel_id),
                        channel_state: ChannelState::OurInitSent as u32,
                        announcement_sigs_state: AnnouncementSigsState::NotSent,
                        secp_ctx,
@@ -1103,6 +1110,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        latest_inbound_scid_alias: None,
                        outbound_scid_alias,
 
+                       channel_pending_event_emitted: false,
                        channel_ready_event_emitted: false,
 
                        #[cfg(any(test, fuzzing))]
@@ -1350,6 +1358,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        inbound_handshake_limits_override: None,
 
                        channel_id: msg.temporary_channel_id,
+                       temporary_channel_id: Some(msg.temporary_channel_id),
                        channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32),
                        announcement_sigs_state: AnnouncementSigsState::NotSent,
                        secp_ctx,
@@ -1451,6 +1460,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                        latest_inbound_scid_alias: None,
                        outbound_scid_alias,
 
+                       channel_pending_event_emitted: false,
                        channel_ready_event_emitted: false,
 
                        #[cfg(any(test, fuzzing))]
@@ -4550,6 +4560,13 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                self.channel_id
        }
 
+       // Return the `temporary_channel_id` used during channel establishment.
+       //
+       // Will return `None` for channels created prior to LDK version 0.0.115.
+       pub fn temporary_channel_id(&self) -> Option<[u8; 32]> {
+               self.temporary_channel_id
+       }
+
        pub fn minimum_depth(&self) -> Option<u32> {
                self.minimum_depth
        }
@@ -4694,6 +4711,21 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
                self.prev_config.map(|prev_config| prev_config.0)
        }
 
+       // Checks whether we should emit a `ChannelPending` event.
+       pub(crate) fn should_emit_channel_pending_event(&mut self) -> bool {
+               self.is_funding_initiated() && !self.channel_pending_event_emitted
+       }
+
+       // Returns whether we already emitted a `ChannelPending` event.
+       pub(crate) fn channel_pending_event_emitted(&self) -> bool {
+               self.channel_pending_event_emitted
+       }
+
+       // Remembers that we already emitted a `ChannelPending` event.
+       pub(crate) fn set_channel_pending_event_emitted(&mut self) {
+               self.channel_pending_event_emitted = true;
+       }
+
        // Checks whether we should emit a `ChannelReady` event.
        pub(crate) fn should_emit_channel_ready_event(&mut self) -> bool {
                self.is_usable() && !self.channel_ready_event_emitted
@@ -6420,6 +6452,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
                        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)
                        { Some(self.holder_max_htlc_value_in_flight_msat) } else { None };
 
+               let channel_pending_event_emitted = Some(self.channel_pending_event_emitted);
                let channel_ready_event_emitted = Some(self.channel_ready_event_emitted);
 
                // `user_id` used to be a single u64 value. In order to remain backwards compatible with
@@ -6452,6 +6485,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for Channel<Signer> {
                        (23, channel_ready_event_emitted, option),
                        (25, user_id_high_opt, option),
                        (27, self.channel_keys_id, required),
+                       (29, self.temporary_channel_id, option),
+                       (31, channel_pending_event_emitted, option),
                });
 
                Ok(())
@@ -6719,10 +6754,12 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                let mut announcement_sigs_state = Some(AnnouncementSigsState::NotSent);
                let mut latest_inbound_scid_alias = None;
                let mut outbound_scid_alias = None;
+               let mut channel_pending_event_emitted = None;
                let mut channel_ready_event_emitted = None;
 
                let mut user_id_high_opt: Option<u64> = None;
                let mut channel_keys_id: Option<[u8; 32]> = None;
+               let mut temporary_channel_id: Option<[u8; 32]> = None;
 
                read_tlv_fields!(reader, {
                        (0, announcement_sigs, option),
@@ -6743,6 +6780,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                        (23, channel_ready_event_emitted, option),
                        (25, user_id_high_opt, option),
                        (27, channel_keys_id, option),
+                       (29, temporary_channel_id, option),
+                       (31, channel_pending_event_emitted, option),
                });
 
                let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
@@ -6807,6 +6846,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                        inbound_handshake_limits_override: None,
 
                        channel_id,
+                       temporary_channel_id,
                        channel_state,
                        announcement_sigs_state: announcement_sigs_state.unwrap(),
                        secp_ctx,
@@ -6899,6 +6939,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                        // Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
                        outbound_scid_alias: outbound_scid_alias.unwrap_or(0),
 
+                       channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true),
                        channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true),
 
                        #[cfg(any(test, fuzzing))]
index d591788f64a68209349b2d7b86c269997a63fbab..e18c133636deaff14f30eada01e6865d2a49dbfb 100644 (file)
@@ -1496,18 +1496,31 @@ macro_rules! send_channel_ready {
        }}
 }
 
+macro_rules! emit_channel_pending_event {
+       ($locked_events: expr, $channel: expr) => {
+               if $channel.should_emit_channel_pending_event() {
+                       $locked_events.push(events::Event::ChannelPending {
+                               channel_id: $channel.channel_id(),
+                               former_temporary_channel_id: $channel.temporary_channel_id(),
+                               counterparty_node_id: $channel.get_counterparty_node_id(),
+                               user_channel_id: $channel.get_user_id(),
+                               funding_txo: $channel.get_funding_txo().unwrap().into_bitcoin_outpoint(),
+                       });
+                       $channel.set_channel_pending_event_emitted();
+               }
+       }
+}
+
 macro_rules! emit_channel_ready_event {
-       ($self: expr, $channel: expr) => {
+       ($locked_events: expr, $channel: expr) => {
                if $channel.should_emit_channel_ready_event() {
-                       {
-                               let mut pending_events = $self.pending_events.lock().unwrap();
-                               pending_events.push(events::Event::ChannelReady {
-                                       channel_id: $channel.channel_id(),
-                                       user_channel_id: $channel.get_user_id(),
-                                       counterparty_node_id: $channel.get_counterparty_node_id(),
-                                       channel_type: $channel.get_channel_type().clone(),
-                               });
-                       }
+                       debug_assert!($channel.channel_pending_event_emitted());
+                       $locked_events.push(events::Event::ChannelReady {
+                               channel_id: $channel.channel_id(),
+                               user_channel_id: $channel.get_user_id(),
+                               counterparty_node_id: $channel.get_counterparty_node_id(),
+                               channel_type: $channel.get_channel_type().clone(),
+                       });
                        $channel.set_channel_ready_event_emitted();
                }
        }
@@ -4253,8 +4266,6 @@ where
                        });
                }
 
-               emit_channel_ready_event!(self, channel);
-
                macro_rules! handle_cs { () => {
                        if let Some(update) = commitment_update {
                                pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
@@ -4287,6 +4298,12 @@ where
                        self.tx_broadcaster.broadcast_transaction(&tx);
                }
 
+               {
+                       let mut pending_events = self.pending_events.lock().unwrap();
+                       emit_channel_pending_event!(pending_events, channel);
+                       emit_channel_ready_event!(pending_events, channel);
+               }
+
                htlc_forwards
        }
 
@@ -4711,7 +4728,10 @@ where
                                        }
                                }
 
-                               emit_channel_ready_event!(self, chan.get_mut());
+                               {
+                                       let mut pending_events = self.pending_events.lock().unwrap();
+                                       emit_channel_ready_event!(pending_events, chan.get_mut());
+                               }
 
                                Ok(())
                        },
@@ -6036,7 +6056,10 @@ where
                                                        }
                                                }
 
-                                               emit_channel_ready_event!(self, channel);
+                                               {
+                                                       let mut pending_events = self.pending_events.lock().unwrap();
+                                                       emit_channel_ready_event!(pending_events, channel);
+                                               }
 
                                                if let Some(announcement_sigs) = announcement_sigs {
                                                        log_trace!(self.logger, "Sending announcement_signatures for channel {}", log_bytes!(channel.channel_id()));
@@ -8463,6 +8486,7 @@ mod tests {
                        assert_eq!(nodes_0_lock.len(), 1);
                        assert!(nodes_0_lock.contains_key(channel_id));
                }
+               expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
                {
                        // Assert that `nodes[1]`'s `id_to_peer` map is populated with the channel as soon as
@@ -8475,6 +8499,7 @@ mod tests {
                let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
                nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
                check_added_monitors!(nodes[0], 1);
+               expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
                let (channel_ready, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
                let (announcement, nodes_0_update, nodes_1_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
                update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &nodes_0_update, &nodes_1_update);
@@ -8617,10 +8642,13 @@ mod tests {
 
                                nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
                                check_added_monitors!(nodes[1], 1);
+                               expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
+
                                let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
 
                                nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
                                check_added_monitors!(nodes[0], 1);
+                               expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
                        }
                        open_channel_msg.temporary_channel_id = nodes[0].keys_manager.get_secure_random_bytes();
                }
@@ -8840,7 +8868,7 @@ pub mod bench {
        use crate::chain::chainmonitor::{ChainMonitor, Persist};
        use crate::chain::keysinterface::{EntropySource, KeysManager, InMemorySigner};
        use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider};
-       use crate::ln::channelmanager::{self, BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentId};
+       use crate::ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentId};
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs::{ChannelMessageHandler, Init};
        use crate::routing::gossip::NetworkGraph;
@@ -8921,7 +8949,24 @@ pub mod bench {
                } else { panic!(); }
 
                node_b.handle_funding_created(&node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendFundingCreated, node_b.get_our_node_id()));
+               let events_b = node_b.get_and_clear_pending_events();
+               assert_eq!(events_b.len(), 1);
+               match events_b[0] {
+                       Event::ChannelPending{ ref counterparty_node_id, .. } => {
+                               assert_eq!(*counterparty_node_id, node_a.get_our_node_id());
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+
                node_a.handle_funding_signed(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendFundingSigned, node_a.get_our_node_id()));
+               let events_a = node_a.get_and_clear_pending_events();
+               assert_eq!(events_a.len(), 1);
+               match events_a[0] {
+                       Event::ChannelPending{ ref counterparty_node_id, .. } => {
+                               assert_eq!(*counterparty_node_id, node_b.get_our_node_id());
+                       },
+                       _ => panic!("Unexpected event"),
+               }
 
                assert_eq!(&tx_broadcaster.txn_broadcasted.lock().unwrap()[..], &[tx.clone()]);
 
index 61b927c536fd1603957b9a5d51842e5abe6b7e84..d7fd9c8e99393220192514ee9ed29e19ab31196e 100644 (file)
@@ -883,6 +883,7 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &
                assert_eq!(added_monitors[0].0, funding_output);
                added_monitors.clear();
        }
+       expect_channel_pending_event(&node_b, &node_a.node.get_our_node_id());
 
        node_a.node.handle_funding_signed(&node_b.node.get_our_node_id(), &get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a.node.get_our_node_id()));
        {
@@ -891,6 +892,7 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &
                assert_eq!(added_monitors[0].0, funding_output);
                added_monitors.clear();
        }
+       expect_channel_pending_event(&node_a, &node_b.node.get_our_node_id());
 
        let events_4 = node_a.node.get_and_clear_pending_events();
        assert_eq!(events_4.len(), 0);
@@ -942,6 +944,8 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r
                MessageSendEvent::SendFundingSigned { node_id, msg } => {
                        assert_eq!(*node_id, initiator.node.get_our_node_id());
                        initiator.node.handle_funding_signed(&receiver.node.get_our_node_id(), &msg);
+                       expect_channel_pending_event(&initiator, &receiver.node.get_our_node_id());
+                       expect_channel_pending_event(&receiver, &initiator.node.get_our_node_id());
                        check_added_monitors!(initiator, 1);
 
                        assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
@@ -955,11 +959,13 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r
                MessageSendEvent::SendChannelReady { node_id, msg } => {
                        assert_eq!(*node_id, initiator.node.get_our_node_id());
                        initiator.node.handle_channel_ready(&receiver.node.get_our_node_id(), &msg);
+                       expect_channel_ready_event(&initiator, &receiver.node.get_our_node_id());
                }
                _ => panic!("Unexpected event"),
        }
 
        receiver.node.handle_channel_ready(&initiator.node.get_our_node_id(), &as_channel_ready);
+       expect_channel_ready_event(&receiver, &initiator.node.get_our_node_id());
 
        let as_channel_update = get_event_msg!(initiator, MessageSendEvent::SendChannelUpdate, receiver.node.get_our_node_id());
        let bs_channel_update = get_event_msg!(receiver, MessageSendEvent::SendChannelUpdate, initiator.node.get_our_node_id());
@@ -970,9 +976,6 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r
        assert_eq!(initiator.node.list_usable_channels().len(), initiator_channels + 1);
        assert_eq!(receiver.node.list_usable_channels().len(), receiver_channels + 1);
 
-       expect_channel_ready_event(&initiator, &receiver.node.get_our_node_id());
-       expect_channel_ready_event(&receiver, &initiator.node.get_our_node_id());
-
        (tx, as_channel_ready.channel_id)
 }
 
@@ -1097,7 +1100,10 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &
        check_added_monitors!(nodes[b], 1);
 
        let cs_funding_signed = get_event_msg!(nodes[b], MessageSendEvent::SendFundingSigned, nodes[a].node.get_our_node_id());
+       expect_channel_pending_event(&nodes[b], &nodes[a].node.get_our_node_id());
+
        nodes[a].node.handle_funding_signed(&nodes[b].node.get_our_node_id(), &cs_funding_signed);
+       expect_channel_pending_event(&nodes[a], &nodes[b].node.get_our_node_id());
        check_added_monitors!(nodes[a], 1);
 
        assert_eq!(nodes[a].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
@@ -1801,6 +1807,18 @@ macro_rules! expect_payment_forwarded {
        }
 }
 
+#[cfg(any(test, feature = "_bench_unstable", feature = "_test_utils"))]
+pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
+       let events = node.node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events[0] {
+               crate::events::Event::ChannelPending { ref counterparty_node_id, .. } => {
+                       assert_eq!(*expected_counterparty_node_id, *counterparty_node_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
+}
+
 #[cfg(any(test, feature = "_bench_unstable", feature = "_test_utils"))]
 pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
        let events = node.node.get_and_clear_pending_events();
@@ -1813,7 +1831,6 @@ pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, ex
        }
 }
 
-
 pub struct PaymentFailedConditions<'a> {
        pub(crate) expected_htlc_error_data: Option<(u16, &'a [u8])>,
        pub(crate) expected_blamed_scid: Option<u64>,
index 56586b0a29c569be57700a316e109e1bb76edb24..4f73627f4b4d24ef6ab414311f09b95d64d82208 100644 (file)
@@ -541,6 +541,8 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) {
                assert_eq!(added_monitors[0].0, funding_output);
                added_monitors.clear();
        }
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
+
        let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
 
        if steps & 0x0f == 5 { return; }
@@ -552,6 +554,7 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) {
                added_monitors.clear();
        }
 
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
        let events_4 = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events_4.len(), 0);
 
@@ -8854,6 +8857,8 @@ fn test_duplicate_chan_id() {
                assert_eq!(added_monitors[0].0, funding_output);
                added_monitors.clear();
        }
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
+
        let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
 
        let funding_outpoint = crate::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index };
@@ -8929,6 +8934,7 @@ fn test_duplicate_chan_id() {
                assert_eq!(added_monitors[0].0, funding_output);
                added_monitors.clear();
        }
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
 
        let events_4 = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events_4.len(), 0);
@@ -9043,9 +9049,11 @@ fn test_invalid_funding_tx() {
        nodes[0].node.funding_transaction_generated_unchecked(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone(), 0).unwrap();
        nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()));
        check_added_monitors!(nodes[1], 1);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
        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()));
        check_added_monitors!(nodes[0], 1);
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
 
        let events_1 = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events_1.len(), 0);
@@ -9575,9 +9583,11 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
        nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
        nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()));
        check_added_monitors!(nodes[1], 1);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
        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()));
        check_added_monitors!(nodes[0], 1);
+       expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id());
 
        let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
        let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
index 6d1df42d18e20e3bb0c7eaf1223b8343ea06a1d3..313d84c53f86f40e0c6ae28bf0a54826a297ddf7 100644 (file)
@@ -362,7 +362,10 @@ fn test_inbound_scid_privacy() {
        check_added_monitors!(nodes[2], 1);
 
        let cs_funding_signed = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[1].node.get_our_node_id());
+       expect_channel_pending_event(&nodes[2], &nodes[1].node.get_our_node_id());
+
        nodes[1].node.handle_funding_signed(&nodes[2].node.get_our_node_id(), &cs_funding_signed);
+       expect_channel_pending_event(&nodes[1], &nodes[2].node.get_our_node_id());
        check_added_monitors!(nodes[1], 1);
 
        let conf_height = core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[2].best_block_info().1 + 1);
@@ -599,6 +602,7 @@ fn test_0conf_channel_with_async_monitor() {
 
        let channel_id = funding_output.to_channel_id();
        nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
        let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(bs_signed_locked.len(), 2);
@@ -624,6 +628,22 @@ fn test_0conf_channel_with_async_monitor() {
 
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        nodes[0].chain_monitor.complete_sole_pending_chan_update(&channel_id);
+
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 2);
+       match events[0] {
+               crate::events::Event::ChannelPending { ref counterparty_node_id, .. } => {
+                       assert_eq!(nodes[1].node.get_our_node_id(), *counterparty_node_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
+       match events[1] {
+               crate::events::Event::ChannelReady { ref counterparty_node_id, .. } => {
+                       assert_eq!(nodes[1].node.get_our_node_id(), *counterparty_node_id);
+               },
+               _ => panic!("Unexpected event"),
+       }
+
        let as_locked_update = nodes[0].node.get_and_clear_pending_msg_events();
 
        // Note that the funding transaction is actually released when
@@ -638,7 +658,6 @@ fn test_0conf_channel_with_async_monitor() {
                }
                _ => panic!("Unexpected event"),
        }
-       expect_channel_ready_event(&nodes[0], &nodes[1].node.get_our_node_id());
        expect_channel_ready_event(&nodes[1], &nodes[0].node.get_our_node_id());
 
        let bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
index ffb6ba0e85a1340da52bc88d28168e05f0f5dfe1..202ecce65de8d97503cb29d1ac60f3d4af239e83 100644 (file)
@@ -261,6 +261,9 @@ fn test_manager_serialize_deserialize_events() {
        }
        // Normally, this is where node_a would broadcast the funding transaction, but the test de/serializes first instead
 
+       expect_channel_pending_event(&node_a, &node_b.node.get_our_node_id());
+       expect_channel_pending_event(&node_b, &node_a.node.get_our_node_id());
+
        nodes.push(node_a);
        nodes.push(node_b);