More flexible fee rate estimates
[rust-lightning] / lightning / src / ln / channelmanager.rs
index 092ebc2c5001fdcb36a9c719237676dcb8c5e54f..4ed5b63f213f70d80305d5951386875eb129197c 100644 (file)
@@ -840,6 +840,9 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> =
        >;
 
 /// A trivial trait which describes any [`ChannelManager`].
+///
+/// This is not exported to bindings users as general cover traits aren't useful in other
+/// languages.
 pub trait AChannelManager {
        /// A type implementing [`chain::Watch`].
        type Watch: chain::Watch<Self::Signer> + ?Sized;
@@ -2613,6 +2616,8 @@ where
                                        // it does not exist for this peer. Either way, we can attempt to force-close it.
                                        //
                                        // An appropriate error will be returned for non-existence of the channel if that's the case.
+                                       mem::drop(peer_state_lock);
+                                       mem::drop(per_peer_state);
                                        return self.force_close_channel_with_peer(&channel_id, counterparty_node_id, None, false).map(|_| ())
                                },
                        }
@@ -2635,11 +2640,11 @@ where
        /// will be accepted on the given channel, and after additional timeout/the closing of all
        /// pending HTLCs, the channel will be closed on chain.
        ///
-       ///  * If we are the channel initiator, we will pay between our [`Background`] and
-       ///    [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`Normal`] fee
-       ///    estimate.
+       ///  * If we are the channel initiator, we will pay between our [`ChannelCloseMinimum`] and
+       ///    [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`NonAnchorChannelFee`]
+       ///    fee estimate.
        ///  * If our counterparty is the channel initiator, we will require a channel closing
-       ///    transaction feerate of at least our [`Background`] feerate or the feerate which
+       ///    transaction feerate of at least our [`ChannelCloseMinimum`] feerate or the feerate which
        ///    would appear on a force-closure transaction, whichever is lower. We will allow our
        ///    counterparty to pay as much fee as they'd like, however.
        ///
@@ -2651,8 +2656,8 @@ where
        /// channel.
        ///
        /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis
-       /// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background
-       /// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
+       /// [`ChannelCloseMinimum`]: crate::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum
+       /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee
        /// [`SendShutdown`]: crate::events::MessageSendEvent::SendShutdown
        pub fn close_channel(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey) -> Result<(), APIError> {
                self.close_channel_internal(channel_id, counterparty_node_id, None, None)
@@ -2666,8 +2671,8 @@ where
        /// the channel being closed or not:
        ///  * If we are the channel initiator, we will pay at least this feerate on the closing
        ///    transaction. The upper-bound is set by
-       ///    [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`Normal`] fee
-       ///    estimate (or `target_feerate_sat_per_1000_weight`, if it is greater).
+       ///    [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`NonAnchorChannelFee`]
+       ///    fee estimate (or `target_feerate_sat_per_1000_weight`, if it is greater).
        ///  * If our counterparty is the channel initiator, we will refuse to accept a channel closure
        ///    transaction feerate below `target_feerate_sat_per_1000_weight` (or the feerate which
        ///    will appear on a force-closure transaction, whichever is lower).
@@ -2685,8 +2690,7 @@ where
        /// channel.
        ///
        /// [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis
-       /// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background
-       /// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
+       /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee
        /// [`SendShutdown`]: crate::events::MessageSendEvent::SendShutdown
        pub fn close_channel_with_feerate_and_script(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option<u32>, shutdown_script: Option<ShutdownScript>) -> Result<(), APIError> {
                self.close_channel_internal(channel_id, counterparty_node_id, target_feerate_sats_per_1000_weight, shutdown_script)
@@ -2935,7 +2939,7 @@ where
                // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
                // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
                let current_height: u32 = self.best_block.read().unwrap().height();
-               if (outgoing_cltv_value as u64) <= current_height as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
+               if cltv_expiry <= current_height + HTLC_FAIL_BACK_BUFFER + 1 {
                        let mut err_data = Vec::with_capacity(12);
                        err_data.extend_from_slice(&amt_msat.to_be_bytes());
                        err_data.extend_from_slice(&current_height.to_be_bytes());
@@ -3998,7 +4002,7 @@ where
                for channel_id in channel_ids {
                        if !peer_state.has_channel(channel_id) {
                                return Err(APIError::ChannelUnavailable {
-                                       err: format!("Channel with ID {} was not found for the passed counterparty_node_id {}", channel_id, counterparty_node_id),
+                                       err: format!("Channel with id {} not found for the passed counterparty node_id {}", channel_id, counterparty_node_id),
                                });
                        };
                }
@@ -4109,7 +4113,7 @@ where
                                                next_hop_channel_id, next_node_id)
                                }),
                                None => return Err(APIError::ChannelUnavailable {
-                                       err: format!("Channel with id {} not found for the passed counterparty node_id {}.",
+                                       err: format!("Channel with id {} not found for the passed counterparty node_id {}",
                                                next_hop_channel_id, next_node_id)
                                })
                        }
@@ -4722,8 +4726,10 @@ where
                if !chan.context.is_outbound() { return NotifyOption::SkipPersistNoEvents; }
                // If the feerate has decreased by less than half, don't bother
                if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() {
-                       log_trace!(self.logger, "Channel {} does not qualify for a feerate change from {} to {}.",
+                       if new_feerate != chan.context.get_feerate_sat_per_1000_weight() {
+                               log_trace!(self.logger, "Channel {} does not qualify for a feerate change from {} to {}.",
                                chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate);
+                       }
                        return NotifyOption::SkipPersistNoEvents;
                }
                if !chan.context.is_live() {
@@ -4747,8 +4753,8 @@ where
                PersistenceNotifierGuard::optionally_notify(self, || {
                        let mut should_persist = NotifyOption::SkipPersistNoEvents;
 
-                       let normal_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
-                       let min_mempool_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MempoolMinimum);
+                       let non_anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee);
+                       let anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee);
 
                        let per_peer_state = self.per_peer_state.read().unwrap();
                        for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
@@ -4758,9 +4764,9 @@ where
                                        |(chan_id, phase)| if let ChannelPhase::Funded(chan) = phase { Some((chan_id, chan)) } else { None }
                                ) {
                                        let new_feerate = if chan.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
-                                               min_mempool_feerate
+                                               anchor_feerate
                                        } else {
-                                               normal_feerate
+                                               non_anchor_feerate
                                        };
                                        let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate);
                                        if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
@@ -4792,8 +4798,8 @@ where
                PersistenceNotifierGuard::optionally_notify(self, || {
                        let mut should_persist = NotifyOption::SkipPersistNoEvents;
 
-                       let normal_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
-                       let min_mempool_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MempoolMinimum);
+                       let non_anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::NonAnchorChannelFee);
+                       let anchor_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::AnchorChannelFee);
 
                        let mut handle_errors: Vec<(Result<(), _>, _)> = Vec::new();
                        let mut timed_out_mpp_htlcs = Vec::new();
@@ -4840,9 +4846,9 @@ where
                                                match phase {
                                                        ChannelPhase::Funded(chan) => {
                                                                let new_feerate = if chan.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
-                                                                       min_mempool_feerate
+                                                                       anchor_feerate
                                                                } else {
-                                                                       normal_feerate
+                                                                       non_anchor_feerate
                                                                };
                                                                let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate);
                                                                if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
@@ -10745,6 +10751,16 @@ mod tests {
                check_api_error_message(expected_message, res_err)
        }
 
+       fn check_channel_unavailable_error<T>(res_err: Result<T, APIError>, expected_channel_id: ChannelId, peer_node_id: PublicKey) {
+               let expected_message = format!("Channel with id {} not found for the passed counterparty node_id {}", expected_channel_id, peer_node_id);
+               check_api_error_message(expected_message, res_err)
+       }
+
+       fn check_api_misuse_error<T>(res_err: Result<T, APIError>) {
+               let expected_message = "No such channel awaiting to be accepted.".to_string();
+               check_api_error_message(expected_message, res_err)
+       }
+
        fn check_api_error_message<T>(expected_err_message: String, res_err: Result<T, APIError>) {
                match res_err {
                        Err(APIError::APIMisuseError { err }) => {
@@ -10789,6 +10805,36 @@ mod tests {
                check_unkown_peer_error(nodes[0].node.update_channel_config(&unkown_public_key, &[channel_id], &ChannelConfig::default()), unkown_public_key);
        }
 
+       #[test]
+       fn test_api_calls_with_unavailable_channel() {
+               // Tests that our API functions that expects a `counterparty_node_id` and a `channel_id`
+               // as input, behaves as expected if the `counterparty_node_id` is a known peer in the
+               // `ChannelManager::per_peer_state` map, but the peer state doesn't contain a channel with
+               // the given `channel_id`.
+               let chanmon_cfg = create_chanmon_cfgs(2);
+               let node_cfg = create_node_cfgs(2, &chanmon_cfg);
+               let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[None, None]);
+               let nodes = create_network(2, &node_cfg, &node_chanmgr);
+
+               let counterparty_node_id = nodes[1].node.get_our_node_id();
+
+               // Dummy values
+               let channel_id = ChannelId::from_bytes([4; 32]);
+
+               // Test the API functions.
+               check_api_misuse_error(nodes[0].node.accept_inbound_channel(&channel_id, &counterparty_node_id, 42));
+
+               check_channel_unavailable_error(nodes[0].node.close_channel(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
+
+               check_channel_unavailable_error(nodes[0].node.force_close_broadcasting_latest_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
+
+               check_channel_unavailable_error(nodes[0].node.force_close_without_broadcasting_txn(&channel_id, &counterparty_node_id), channel_id, counterparty_node_id);
+
+               check_channel_unavailable_error(nodes[0].node.forward_intercepted_htlc(InterceptId([0; 32]), &channel_id, counterparty_node_id, 1_000_000), channel_id, counterparty_node_id);
+
+               check_channel_unavailable_error(nodes[0].node.update_channel_config(&counterparty_node_id, &[channel_id], &ChannelConfig::default()), channel_id, counterparty_node_id);
+       }
+
        #[test]
        fn test_connection_limiting() {
                // Test that we limit un-channel'd peers and un-funded channels properly.
@@ -11049,6 +11095,30 @@ mod tests {
                        sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat)).is_ok());
        }
 
+       #[test]
+       fn test_final_incorrect_cltv(){
+               let chanmon_cfg = create_chanmon_cfgs(1);
+               let node_cfg = create_node_cfgs(1, &chanmon_cfg);
+               let node_chanmgr = create_node_chanmgrs(1, &node_cfg, &[None]);
+               let node = create_network(1, &node_cfg, &node_chanmgr);
+
+               let result = node[0].node.construct_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive {
+                       amt_msat: 100,
+                       outgoing_cltv_value: 22,
+                       payment_metadata: None,
+                       keysend_preimage: None,
+                       payment_data: Some(msgs::FinalOnionHopData {
+                               payment_secret: PaymentSecret([0; 32]), total_msat: 100,
+                       }),
+                       custom_tlvs: Vec::new(),
+               }, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None);
+
+               // Should not return an error as this condition:
+               // https://github.com/lightning/bolts/blob/4dcc377209509b13cf89a4b91fde7d478f5b46d8/04-onion-routing.md?plain=1#L334
+               // is not satisfied.
+               assert!(result.is_ok());
+       }
+
        #[test]
        fn test_inbound_anchors_manual_acceptance() {
                // Tests that we properly limit inbound channels when we have the manual-channel-acceptance