Send funding_locked immediately for inbound channels with 0conf
authorMatt Corallo <git@bluematt.me>
Thu, 10 Feb 2022 00:09:42 +0000 (00:09 +0000)
committerMatt Corallo <git@bluematt.me>
Fri, 27 May 2022 22:40:07 +0000 (22:40 +0000)
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/priv_short_conf_tests.rs

index a49444f09d0abd0d195eb19b31a75c48ae062bea..70a13f9ebe173ee9ce8ed7d941c356683cd6a59d 100644 (file)
@@ -2093,7 +2093,7 @@ impl<Signer: Sign> Channel<Signer> {
                &self.get_counterparty_pubkeys().funding_pubkey
        }
 
-       pub fn funding_created<L: Deref>(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>), ChannelError> where L::Target: Logger {
+       pub fn funding_created<L: Deref>(&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor<Signer>, Option<msgs::FundingLocked>), ChannelError> where L::Target: Logger {
                if self.is_outbound() {
                        return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned()));
                }
@@ -2168,7 +2168,7 @@ impl<Signer: Sign> Channel<Signer> {
                Ok((msgs::FundingSigned {
                        channel_id: self.channel_id,
                        signature
-               }, channel_monitor))
+               }, channel_monitor, self.check_get_funding_locked(0)))
        }
 
        /// Handles a funding_signed message from the remote end.
@@ -6692,7 +6692,7 @@ mod tests {
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap();
-               let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap();
+               let (funding_signed_msg, _, _) = node_b_chan.funding_created(&funding_created_msg, best_block, &&logger).unwrap();
 
                // Node B --> Node A: funding signed
                let _ = node_a_chan.funding_signed(&funding_signed_msg, best_block, &&logger);
index acc1310fa7117806f2e40878c9cd76e6d4b373c5..8193ba443c2da58cd75a5ad79e7c098b4e2ecace 100644 (file)
@@ -2293,6 +2293,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                action: msgs::ErrorAction::IgnoreError
                        });
                }
+               if chan.get_short_channel_id().is_none() {
+                       return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError});
+               }
                log_trace!(self.logger, "Attempting to generate broadcast channel update for channel {}", log_bytes!(chan.channel_id()));
                self.get_channel_update_for_unicast(chan)
        }
@@ -2304,7 +2307,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        /// May be called with channel_state already locked!
        fn get_channel_update_for_unicast(&self, chan: &Channel<Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
                log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.channel_id()));
-               let short_channel_id = match chan.get_short_channel_id() {
+               let short_channel_id = match chan.get_short_channel_id().or(chan.latest_inbound_scid_alias()) {
                        None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}),
                        Some(id) => id,
                };
@@ -4262,7 +4265,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        }
 
        fn internal_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
-               let ((funding_msg, monitor), mut chan) = {
+               let ((funding_msg, monitor, mut funding_locked), mut chan) = {
                        let best_block = *self.best_block.read().unwrap();
                        let mut channel_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_lock;
@@ -4297,7 +4300,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
                                        // accepted payment from yet. We do, however, need to wait to send our funding_locked
                                        // until we have persisted our monitor.
-                                       chan.monitor_update_failed(false, false, false, Vec::new(), Vec::new(), Vec::new());
+                                       chan.monitor_update_failed(false, false, funding_locked.is_some(), Vec::new(), Vec::new(), Vec::new());
+                                       funding_locked = None; // Don't send the funding_locked now
                                },
                        }
                }
@@ -4312,6 +4316,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        node_id: counterparty_node_id.clone(),
                                        msg: funding_msg,
                                });
+                               if let Some(msg) = funding_locked {
+                                       send_funding_locked!(channel_state.short_to_id, channel_state.pending_msg_events, chan, msg);
+                               }
                                e.insert(chan);
                        }
                }
index a7bc3e5656df59c22f8f31d351c234bbed3153fe..ed11b993fc75f7535bf8716b926448e0cfda1c83 100644 (file)
@@ -570,6 +570,9 @@ fn test_simple_0conf_channel() {
        // If our peer tells us they will accept our channel with 0 confs, and we funded the channel,
        // we should trust the funding won't be double-spent (assuming `trust_own_funding_0conf` is
        // set)!
+       // Further, if we `accept_inbound_channel_from_trusted_peer_0conf`, funding locked messages
+       // should fly immediately and the channel should be available for use as soon as they are
+       // received.
 
        let chanmon_cfgs = create_chanmon_cfgs(2);
        let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
@@ -602,11 +605,38 @@ fn test_simple_0conf_channel() {
 
        nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
        check_added_monitors!(nodes[1], 1);
-       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);
+       let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(bs_signed_locked.len(), 2);
+       let as_funding_locked;
+       match &bs_signed_locked[0] {
+               MessageSendEvent::SendFundingSigned { node_id, msg } => {
+                       assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+                       nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &msg);
+                       check_added_monitors!(nodes[0], 1);
+
+                       assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
+                       assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx);
+
+                       as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id());
+               }
+               _ => panic!("Unexpected event"),
+       }
+       match &bs_signed_locked[1] {
+               MessageSendEvent::SendFundingLocked { node_id, msg } => {
+                       assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+                       nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &msg);
+               }
+               _ => panic!("Unexpected event"),
+       }
 
-       let as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id());
        nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked);
+
+       let as_channel_update = get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
+       let bs_channel_update = get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &bs_channel_update);
+       nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &as_channel_update);
+
+       assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
+       assert_eq!(nodes[1].node.list_usable_channels().len(), 1);
 }