Makes ChannelManager::force_close_channel fail for unknown chan_ids
authorSergi Delgado Segura <sergi.delgado.s@gmail.com>
Thu, 14 Jan 2021 16:05:38 +0000 (17:05 +0100)
committerSergi Delgado Segura <sergi.delgado.s@gmail.com>
Thu, 21 Jan 2021 15:12:57 +0000 (16:12 +0100)
ChannelManager::force_close_channel does not fail if a non-existing channel id is being passed, making it hard to catch from an API point of view.

Makes force_close_channel return in the same way close_channel does so the user calling the method with an unknown id can be warned.

fuzz/src/full_stack.rs
lightning-persister/src/lib.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_tests.rs

index 915a6cba1ea618fa576bed1d59fcff705c7516c4..901c9ef1e25e43850e1fa2dd090fd591d69b116c 100644 (file)
@@ -548,7 +548,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                let channel_id = get_slice!(1)[0] as usize;
                                if channel_id >= channels.len() { return; }
                                channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
-                               channelmanager.force_close_channel(&channels[channel_id].channel_id);
+                               channelmanager.force_close_channel(&channels[channel_id].channel_id).unwrap();
                        },
                        // 15 is above
                        _ => return,
index bb6eb54c9af0ef58700fa954c9a5641f92d5e968..c6b0ea6416f10e30929c39d60ceccd82bf1b9d30 100644 (file)
@@ -240,7 +240,7 @@ mod tests {
 
                // Force close because cooperative close doesn't result in any persisted
                // updates.
-               nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id);
+               nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id).unwrap();
                check_closed_broadcast!(nodes[0], false);
                check_added_monitors!(nodes[0], 1);
 
@@ -354,7 +354,7 @@ mod tests {
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
-               nodes[1].node.force_close_channel(&chan.2);
+               nodes[1].node.force_close_channel(&chan.2).unwrap();
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
 
                // Set the persister's directory to read-only, which should result in
@@ -390,7 +390,7 @@ mod tests {
                let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
-               nodes[1].node.force_close_channel(&chan.2);
+               nodes[1].node.force_close_channel(&chan.2).unwrap();
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
 
                // Create the persister with an invalid directory name and test that the
index b9376029eb0dd8f7ea8981833ddaf04e89218ae9..98bf905f1b50e95fb7ffa08834e0fa1fa2ee789a 100644 (file)
@@ -239,7 +239,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool, persister_fail
        }
 
        // ...and make sure we can force-close a frozen channel
-       nodes[0].node.force_close_channel(&channel_id);
+       nodes[0].node.force_close_channel(&channel_id).unwrap();
        check_added_monitors!(nodes[0], 1);
        check_closed_broadcast!(nodes[0], false);
 
index 49c14a04345cb1b011aa8f10857b111045279be3..e353700be16f5bff37627e53b06cd45a8a585114 100644 (file)
@@ -917,8 +917,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
        }
 
        /// Force closes a channel, immediately broadcasting the latest local commitment transaction to
-       /// the chain and rejecting new HTLCs on the given channel.
-       pub fn force_close_channel(&self, channel_id: &[u8; 32]) {
+       /// the chain and rejecting new HTLCs on the given channel. Fails if channel_id is unknown to the manager.
+       pub fn force_close_channel(&self, channel_id: &[u8; 32]) -> Result<(), APIError>{
                let _consistency_lock = self.total_consistency_lock.read().unwrap();
 
                let mut chan = {
@@ -930,7 +930,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                }
                                chan
                        } else {
-                               return;
+                               return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()});
                        }
                };
                log_trace!(self.logger, "Force-closing channel {}", log_bytes!(channel_id[..]));
@@ -941,13 +941,15 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                msg: update
                        });
                }
+
+               Ok(())
        }
 
        /// Force close all channels, immediately broadcasting the latest local commitment transaction
        /// for each to the chain and rejecting new HTLCs on each.
        pub fn force_close_all_channels(&self) {
                for chan in self.list_channels() {
-                       self.force_close_channel(&chan.channel_id);
+                       let _ = self.force_close_channel(&chan.channel_id);
                }
        }
 
@@ -3471,11 +3473,13 @@ impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send, T: Deref + Sync + Send, K:
                if msg.channel_id == [0; 32] {
                        for chan in self.list_channels() {
                                if chan.remote_network_id == *counterparty_node_id {
-                                       self.force_close_channel(&chan.channel_id);
+                                       // Untrusted messages from peer, we throw away the error if id points to a non-existent channel
+                                       let _ = self.force_close_channel(&msg.channel_id);
                                }
                        }
                } else {
-                       self.force_close_channel(&msg.channel_id);
+                       // Untrusted messages from peer, we throw away the error if id points to a non-existent channel
+                       let _ = self.force_close_channel(&msg.channel_id);
                }
        }
 }
index a9367d9c3f214217eb94a50f07af0da84f9d89fd..0268602c9f353bb96485331fba63fd571ac77b5c 100644 (file)
@@ -3396,7 +3396,7 @@ fn test_htlc_ignore_latest_remote_commitment() {
        create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
 
        route_payment(&nodes[0], &[&nodes[1]], 10000000);
-       nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id);
+       nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id).unwrap();
        check_closed_broadcast!(nodes[0], false);
        check_added_monitors!(nodes[0], 1);
 
@@ -3457,7 +3457,7 @@ fn test_force_close_fail_back() {
        // state or updated nodes[1]' state. Now force-close and broadcast that commitment/HTLC
        // transaction and ensure nodes[1] doesn't fail-backwards (this was originally a bug!).
 
-       nodes[2].node.force_close_channel(&payment_event.commitment_msg.channel_id);
+       nodes[2].node.force_close_channel(&payment_event.commitment_msg.channel_id).unwrap();
        check_closed_broadcast!(nodes[2], false);
        check_added_monitors!(nodes[2], 1);
        let tx = {
@@ -4783,7 +4783,7 @@ fn test_claim_sizeable_push_msat() {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000, InitFeatures::known(), InitFeatures::known());
-       nodes[1].node.force_close_channel(&chan.2);
+       nodes[1].node.force_close_channel(&chan.2).unwrap();
        check_closed_broadcast!(nodes[1], false);
        check_added_monitors!(nodes[1], 1);
        let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -4810,7 +4810,7 @@ fn test_claim_on_remote_sizeable_push_msat() {
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000, InitFeatures::known(), InitFeatures::known());
-       nodes[0].node.force_close_channel(&chan.2);
+       nodes[0].node.force_close_channel(&chan.2).unwrap();
        check_closed_broadcast!(nodes[0], false);
        check_added_monitors!(nodes[0], 1);
 
@@ -8544,7 +8544,7 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain
        // responds by (1) broadcasting a channel update and (2) adding a new ChannelMonitor.
        let mut force_closing_node = 0; // Alice force-closes
        if !broadcast_alice { force_closing_node = 1; } // Bob force-closes
-       nodes[force_closing_node].node.force_close_channel(&chan_ab.2);
+       nodes[force_closing_node].node.force_close_channel(&chan_ab.2).unwrap();
        check_closed_broadcast!(nodes[force_closing_node], false);
        check_added_monitors!(nodes[force_closing_node], 1);
        if go_onchain_before_fulfill {