Merge pull request #2156 from alecchendev/2023-04-mpp-keysend
[rust-lightning] / lightning / src / ln / channelmanager.rs
index 0aa2a85529e7f5b75560e77aee099e0db3f7463e..7c065f1ba44c4d956f68d791f52ad75c8135c74e 100644 (file)
@@ -19,7 +19,7 @@
 
 use bitcoin::blockdata::block::BlockHeader;
 use bitcoin::blockdata::transaction::Transaction;
-use bitcoin::blockdata::constants::genesis_block;
+use bitcoin::blockdata::constants::{genesis_block, ChainHash};
 use bitcoin::network::constants::Network;
 
 use bitcoin::hashes::Hash;
@@ -56,7 +56,7 @@ use crate::ln::outbound_payment;
 use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment};
 use crate::ln::wire::Encode;
 use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, ChannelSigner, WriteableEcdsaChannelSigner};
-use crate::util::config::{UserConfig, ChannelConfig};
+use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
 use crate::util::wakers::{Future, Notifier};
 use crate::util::scid_utils::fake_scid;
 use crate::util::string::UntrustedString;
@@ -112,6 +112,8 @@ pub(super) enum PendingHTLCRouting {
                phantom_shared_secret: Option<[u8; 32]>,
        },
        ReceiveKeysend {
+               /// This was added in 0.0.116 and will break deserialization on downgrades.
+               payment_data: Option<msgs::FinalOnionHopData>,
                payment_preimage: PaymentPreimage,
                payment_metadata: Option<Vec<u8>>,
                incoming_cltv_expiry: u32, // Used to track when we should expire pending HTLCs that go unclaimed
@@ -1373,8 +1375,14 @@ pub struct ChannelDetails {
        /// the current state and per-HTLC limit(s). This is intended for use when routing, allowing us
        /// to use a limit as close as possible to the HTLC limit we can currently send.
        ///
-       /// See also [`ChannelDetails::balance_msat`] and [`ChannelDetails::outbound_capacity_msat`].
+       /// See also [`ChannelDetails::next_outbound_htlc_minimum_msat`],
+       /// [`ChannelDetails::balance_msat`], and [`ChannelDetails::outbound_capacity_msat`].
        pub next_outbound_htlc_limit_msat: u64,
+       /// The minimum value for sending a single HTLC to the remote peer. This is the equivalent of
+       /// [`ChannelDetails::next_outbound_htlc_limit_msat`] but represents a lower-bound, rather than
+       /// an upper-bound. This is intended for use when routing, allowing us to ensure we pick a
+       /// route which is valid.
+       pub next_outbound_htlc_minimum_msat: u64,
        /// The available inbound capacity for the remote peer to send HTLCs to us. This does not
        /// include any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
        /// available for inclusion in new inbound HTLCs).
@@ -1494,6 +1502,7 @@ impl ChannelDetails {
                        inbound_capacity_msat: balance.inbound_capacity_msat,
                        outbound_capacity_msat: balance.outbound_capacity_msat,
                        next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
+                       next_outbound_htlc_minimum_msat: balance.next_outbound_htlc_minimum_msat,
                        user_channel_id: channel.get_user_id(),
                        confirmations_required: channel.minimum_depth(),
                        confirmations: Some(channel.get_funding_tx_confirmations(best_block_height)),
@@ -2450,20 +2459,7 @@ where
                                });
                        },
                        msgs::OnionHopDataFormat::FinalNode { payment_data, keysend_preimage, payment_metadata } => {
-                               if payment_data.is_some() && keysend_preimage.is_some() {
-                                       return Err(ReceiveError {
-                                               err_code: 0x4000|22,
-                                               err_data: Vec::new(),
-                                               msg: "We don't support MPP keysend payments",
-                                       });
-                               } else if let Some(data) = payment_data {
-                                       PendingHTLCRouting::Receive {
-                                               payment_data: data,
-                                               payment_metadata,
-                                               incoming_cltv_expiry: hop_data.outgoing_cltv_value,
-                                               phantom_shared_secret,
-                                       }
-                               } else if let Some(payment_preimage) = keysend_preimage {
+                               if let Some(payment_preimage) = keysend_preimage {
                                        // We need to check that the sender knows the keysend preimage before processing this
                                        // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
                                        // could discover the final destination of X, by probing the adjacent nodes on the route
@@ -2477,12 +2473,26 @@ where
                                                        msg: "Payment preimage didn't match payment hash",
                                                });
                                        }
-
+                                       if !self.default_configuration.accept_mpp_keysend && payment_data.is_some() {
+                                               return Err(ReceiveError {
+                                                       err_code: 0x4000|22,
+                                                       err_data: Vec::new(),
+                                                       msg: "We don't support MPP keysend payments",
+                                               });
+                                       }
                                        PendingHTLCRouting::ReceiveKeysend {
+                                               payment_data,
                                                payment_preimage,
                                                payment_metadata,
                                                incoming_cltv_expiry: hop_data.outgoing_cltv_value,
                                        }
+                               } else if let Some(data) = payment_data {
+                                       PendingHTLCRouting::Receive {
+                                               payment_data: data,
+                                               payment_metadata,
+                                               incoming_cltv_expiry: hop_data.outgoing_cltv_value,
+                                               phantom_shared_secret,
+                                       }
                                } else {
                                        return Err(ReceiveError {
                                                err_code: 0x4000|0x2000|3,
@@ -2964,7 +2974,7 @@ where
                                self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv))
        }
 
-       /// Similar to [`ChannelManager::send_payment`], but will automatically find a route based on
+       /// Similar to [`ChannelManager::send_payment_with_route`], but will automatically find a route based on
        /// `route_params` and retry failed payment paths based on `retry_strategy`.
        pub fn send_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<(), RetryableSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
@@ -3032,8 +3042,6 @@ where
        /// Similar to regular payments, you MUST NOT reuse a `payment_preimage` value. See
        /// [`send_payment`] for more information about the risks of duplicate preimage usage.
        ///
-       /// Note that `route` must have exactly one path.
-       ///
        /// [`send_payment`]: Self::send_payment
        pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option<PaymentPreimage>, recipient_onion: RecipientOnionFields, payment_id: PaymentId) -> Result<PaymentHash, PaymentSendFailure> {
                let best_block_height = self.best_block.read().unwrap().height();
@@ -3228,7 +3236,7 @@ where
                })
        }
 
-       /// Atomically updates the [`ChannelConfig`] for the given channels.
+       /// Atomically applies partial updates to the [`ChannelConfig`] of the given channels.
        ///
        /// Once the updates are applied, each eligible channel (advertised with a known short channel
        /// ID and a change in [`forwarding_fee_proportional_millionths`], [`forwarding_fee_base_msat`],
@@ -3250,10 +3258,10 @@ where
        /// [`ChannelUpdate`]: msgs::ChannelUpdate
        /// [`ChannelUnavailable`]: APIError::ChannelUnavailable
        /// [`APIMisuseError`]: APIError::APIMisuseError
-       pub fn update_channel_config(
-               &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config: &ChannelConfig,
+       pub fn update_partial_channel_config(
+               &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config_update: &ChannelConfigUpdate,
        ) -> Result<(), APIError> {
-               if config.cltv_expiry_delta < MIN_CLTV_EXPIRY_DELTA {
+               if config_update.cltv_expiry_delta.map(|delta| delta < MIN_CLTV_EXPIRY_DELTA).unwrap_or(false) {
                        return Err(APIError::APIMisuseError {
                                err: format!("The chosen CLTV expiry delta is below the minimum of {}", MIN_CLTV_EXPIRY_DELTA),
                        });
@@ -3274,7 +3282,9 @@ where
                }
                for channel_id in channel_ids {
                        let channel = peer_state.channel_by_id.get_mut(channel_id).unwrap();
-                       if !channel.update_config(config) {
+                       let mut config = channel.config();
+                       config.apply(config_update);
+                       if !channel.update_config(&config) {
                                continue;
                        }
                        if let Ok(msg) = self.get_channel_update_for_broadcast(channel) {
@@ -3289,6 +3299,34 @@ where
                Ok(())
        }
 
+       /// Atomically updates the [`ChannelConfig`] for the given channels.
+       ///
+       /// Once the updates are applied, each eligible channel (advertised with a known short channel
+       /// ID and a change in [`forwarding_fee_proportional_millionths`], [`forwarding_fee_base_msat`],
+       /// or [`cltv_expiry_delta`]) has a [`BroadcastChannelUpdate`] event message generated
+       /// containing the new [`ChannelUpdate`] message which should be broadcast to the network.
+       ///
+       /// Returns [`ChannelUnavailable`] when a channel is not found or an incorrect
+       /// `counterparty_node_id` is provided.
+       ///
+       /// Returns [`APIMisuseError`] when a [`cltv_expiry_delta`] update is to be applied with a value
+       /// below [`MIN_CLTV_EXPIRY_DELTA`].
+       ///
+       /// If an error is returned, none of the updates should be considered applied.
+       ///
+       /// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
+       /// [`forwarding_fee_base_msat`]: ChannelConfig::forwarding_fee_base_msat
+       /// [`cltv_expiry_delta`]: ChannelConfig::cltv_expiry_delta
+       /// [`BroadcastChannelUpdate`]: events::MessageSendEvent::BroadcastChannelUpdate
+       /// [`ChannelUpdate`]: msgs::ChannelUpdate
+       /// [`ChannelUnavailable`]: APIError::ChannelUnavailable
+       /// [`APIMisuseError`]: APIError::APIMisuseError
+       pub fn update_channel_config(
+               &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config: &ChannelConfig,
+       ) -> Result<(), APIError> {
+               return self.update_partial_channel_config(counterparty_node_id, channel_ids, &(*config).into());
+       }
+
        /// Attempts to forward an intercepted HTLC over the provided channel id and with the provided
        /// amount to forward. Should only be called in response to an [`HTLCIntercepted`] event.
        ///
@@ -3598,16 +3636,19 @@ where
                                                                                (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
                                                                                        Some(payment_data), phantom_shared_secret, onion_fields)
                                                                        },
-                                                                       PendingHTLCRouting::ReceiveKeysend { payment_preimage, payment_metadata, incoming_cltv_expiry } => {
-                                                                               let onion_fields = RecipientOnionFields { payment_secret: None, payment_metadata };
+                                                                       PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, payment_metadata, incoming_cltv_expiry } => {
+                                                                               let onion_fields = RecipientOnionFields {
+                                                                                       payment_secret: payment_data.as_ref().map(|data| data.payment_secret),
+                                                                                       payment_metadata
+                                                                               };
                                                                                (incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
-                                                                                       None, None, onion_fields)
+                                                                                       payment_data, None, onion_fields)
                                                                        },
                                                                        _ => {
                                                                                panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
                                                                        }
                                                                };
-                                                               let mut claimable_htlc = ClaimableHTLC {
+                                                               let claimable_htlc = ClaimableHTLC {
                                                                        prev_hop: HTLCPreviousHopData {
                                                                                short_channel_id: prev_short_channel_id,
                                                                                outpoint: prev_funding_outpoint,
@@ -3657,13 +3698,11 @@ where
                                                                }
 
                                                                macro_rules! check_total_value {
-                                                                       ($payment_data: expr, $payment_preimage: expr) => {{
+                                                                       ($purpose: expr) => {{
                                                                                let mut payment_claimable_generated = false;
-                                                                               let purpose = || {
-                                                                                       events::PaymentPurpose::InvoicePayment {
-                                                                                               payment_preimage: $payment_preimage,
-                                                                                               payment_secret: $payment_data.payment_secret,
-                                                                                       }
+                                                                               let is_keysend = match $purpose {
+                                                                                       events::PaymentPurpose::SpontaneousPayment(_) => true,
+                                                                                       events::PaymentPurpose::InvoicePayment { .. } => false,
                                                                                };
                                                                                let mut claimable_payments = self.claimable_payments.lock().unwrap();
                                                                                if claimable_payments.pending_claiming_payments.contains_key(&payment_hash) {
@@ -3675,9 +3714,18 @@ where
                                                                                        .or_insert_with(|| {
                                                                                                committed_to_claimable = true;
                                                                                                ClaimablePayment {
-                                                                                                       purpose: purpose(), htlcs: Vec::new(), onion_fields: None,
+                                                                                                       purpose: $purpose.clone(), htlcs: Vec::new(), onion_fields: None,
                                                                                                }
                                                                                        });
+                                                                               if $purpose != claimable_payment.purpose {
+                                                                                       let log_keysend = |keysend| if keysend { "keysend" } else { "non-keysend" };
+                                                                                       log_trace!(self.logger, "Failing new {} HTLC with payment_hash {} as we already had an existing {} HTLC with the same payment hash", log_keysend(is_keysend), log_bytes!(payment_hash.0), log_keysend(!is_keysend));
+                                                                                       fail_htlc!(claimable_htlc, payment_hash);
+                                                                               }
+                                                                               if !self.default_configuration.accept_mpp_keysend && is_keysend && !claimable_payment.htlcs.is_empty() {
+                                                                                       log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash and our config states we don't accept MPP keysend", log_bytes!(payment_hash.0));
+                                                                                       fail_htlc!(claimable_htlc, payment_hash);
+                                                                               }
                                                                                if let Some(earlier_fields) = &mut claimable_payment.onion_fields {
                                                                                        if earlier_fields.check_merge(&mut onion_fields).is_err() {
                                                                                                fail_htlc!(claimable_htlc, payment_hash);
@@ -3686,38 +3734,27 @@ where
                                                                                        claimable_payment.onion_fields = Some(onion_fields);
                                                                                }
                                                                                let ref mut htlcs = &mut claimable_payment.htlcs;
-                                                                               if htlcs.len() == 1 {
-                                                                                       if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
-                                                                                               log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash", log_bytes!(payment_hash.0));
-                                                                                               fail_htlc!(claimable_htlc, payment_hash);
-                                                                                       }
-                                                                               }
                                                                                let mut total_value = claimable_htlc.sender_intended_value;
                                                                                let mut earliest_expiry = claimable_htlc.cltv_expiry;
                                                                                for htlc in htlcs.iter() {
                                                                                        total_value += htlc.sender_intended_value;
                                                                                        earliest_expiry = cmp::min(earliest_expiry, htlc.cltv_expiry);
-                                                                                       match &htlc.onion_payload {
-                                                                                               OnionPayload::Invoice { .. } => {
-                                                                                                       if htlc.total_msat != $payment_data.total_msat {
-                                                                                                               log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
-                                                                                                                       log_bytes!(payment_hash.0), $payment_data.total_msat, htlc.total_msat);
-                                                                                                               total_value = msgs::MAX_VALUE_MSAT;
-                                                                                                       }
-                                                                                                       if total_value >= msgs::MAX_VALUE_MSAT { break; }
-                                                                                               },
-                                                                                               _ => unreachable!(),
+                                                                                       if htlc.total_msat != claimable_htlc.total_msat {
+                                                                                               log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
+                                                                                                       log_bytes!(payment_hash.0), claimable_htlc.total_msat, htlc.total_msat);
+                                                                                               total_value = msgs::MAX_VALUE_MSAT;
                                                                                        }
+                                                                                       if total_value >= msgs::MAX_VALUE_MSAT { break; }
                                                                                }
                                                                                // The condition determining whether an MPP is complete must
                                                                                // match exactly the condition used in `timer_tick_occurred`
                                                                                if total_value >= msgs::MAX_VALUE_MSAT {
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
-                                                                               } else if total_value - claimable_htlc.sender_intended_value >= $payment_data.total_msat {
+                                                                               } else if total_value - claimable_htlc.sender_intended_value >= claimable_htlc.total_msat {
                                                                                        log_trace!(self.logger, "Failing HTLC with payment_hash {} as payment is already claimable",
                                                                                                log_bytes!(payment_hash.0));
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
-                                                                               } else if total_value >= $payment_data.total_msat {
+                                                                               } else if total_value >= claimable_htlc.total_msat {
                                                                                        #[allow(unused_assignments)] {
                                                                                                committed_to_claimable = true;
                                                                                        }
@@ -3728,7 +3765,7 @@ where
                                                                                        new_events.push_back((events::Event::PaymentClaimable {
                                                                                                receiver_node_id: Some(receiver_node_id),
                                                                                                payment_hash,
-                                                                                               purpose: purpose(),
+                                                                                               purpose: $purpose,
                                                                                                amount_msat,
                                                                                                via_channel_id: Some(prev_channel_id),
                                                                                                via_user_channel_id: Some(prev_user_channel_id),
@@ -3776,49 +3813,23 @@ where
                                                                                                                fail_htlc!(claimable_htlc, payment_hash);
                                                                                                        }
                                                                                                }
-                                                                                               check_total_value!(payment_data, payment_preimage);
+                                                                                               let purpose = events::PaymentPurpose::InvoicePayment {
+                                                                                                       payment_preimage: payment_preimage.clone(),
+                                                                                                       payment_secret: payment_data.payment_secret,
+                                                                                               };
+                                                                                               check_total_value!(purpose);
                                                                                        },
                                                                                        OnionPayload::Spontaneous(preimage) => {
-                                                                                               let mut claimable_payments = self.claimable_payments.lock().unwrap();
-                                                                                               if claimable_payments.pending_claiming_payments.contains_key(&payment_hash) {
-                                                                                                       fail_htlc!(claimable_htlc, payment_hash);
-                                                                                               }
-                                                                                               match claimable_payments.claimable_payments.entry(payment_hash) {
-                                                                                                       hash_map::Entry::Vacant(e) => {
-                                                                                                               let amount_msat = claimable_htlc.value;
-                                                                                                               claimable_htlc.total_value_received = Some(amount_msat);
-                                                                                                               let claim_deadline = Some(claimable_htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER);
-                                                                                                               let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
-                                                                                                               e.insert(ClaimablePayment {
-                                                                                                                       purpose: purpose.clone(),
-                                                                                                                       onion_fields: Some(onion_fields.clone()),
-                                                                                                                       htlcs: vec![claimable_htlc],
-                                                                                                               });
-                                                                                                               let prev_channel_id = prev_funding_outpoint.to_channel_id();
-                                                                                                               new_events.push_back((events::Event::PaymentClaimable {
-                                                                                                                       receiver_node_id: Some(receiver_node_id),
-                                                                                                                       payment_hash,
-                                                                                                                       amount_msat,
-                                                                                                                       purpose,
-                                                                                                                       via_channel_id: Some(prev_channel_id),
-                                                                                                                       via_user_channel_id: Some(prev_user_channel_id),
-                                                                                                                       claim_deadline,
-                                                                                                                       onion_fields: Some(onion_fields),
-                                                                                                               }, None));
-                                                                                                       },
-                                                                                                       hash_map::Entry::Occupied(_) => {
-                                                                                                               log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} for a duplicative payment hash", log_bytes!(payment_hash.0));
-                                                                                                               fail_htlc!(claimable_htlc, payment_hash);
-                                                                                                       }
-                                                                                               }
+                                                                                               let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
+                                                                                               check_total_value!(purpose);
                                                                                        }
                                                                                }
                                                                        },
                                                                        hash_map::Entry::Occupied(inbound_payment) => {
-                                                                               if payment_data.is_none() {
+                                                                               if let OnionPayload::Spontaneous(_) = claimable_htlc.onion_payload {
                                                                                        log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} because we already have an inbound payment with the same payment hash", log_bytes!(payment_hash.0));
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
-                                                                               };
+                                                                               }
                                                                                let payment_data = payment_data.unwrap();
                                                                                if inbound_payment.get().payment_secret != payment_data.payment_secret {
                                                                                        log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our expected payment secret.", log_bytes!(payment_hash.0));
@@ -3828,7 +3839,11 @@ where
                                                                                                log_bytes!(payment_hash.0), payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
                                                                                } else {
-                                                                                       let payment_claimable_generated = check_total_value!(payment_data, inbound_payment.get().payment_preimage);
+                                                                                       let purpose = events::PaymentPurpose::InvoicePayment {
+                                                                                               payment_preimage: inbound_payment.get().payment_preimage,
+                                                                                               payment_secret: payment_data.payment_secret,
+                                                                                       };
+                                                                                       let payment_claimable_generated = check_total_value!(purpose);
                                                                                        if payment_claimable_generated {
                                                                                                inbound_payment.remove_entry();
                                                                                        }
@@ -4408,18 +4423,6 @@ where
                                break;
                        }
                        expected_amt_msat = htlc.total_value_received;
-
-                       if let OnionPayload::Spontaneous(_) = &htlc.onion_payload {
-                               // We don't currently support MPP for spontaneous payments, so just check
-                               // that there's one payment here and move on.
-                               if sources.len() != 1 {
-                                       log_error!(self.logger, "Somehow ended up with an MPP spontaneous payment - this should not be reachable!");
-                                       debug_assert!(false);
-                                       valid_mpp = false;
-                                       break;
-                               }
-                       }
-
                        claimable_amt_msat += htlc.value;
                }
                mem::drop(per_peer_state);
@@ -6987,6 +6990,10 @@ where
                provided_init_features(&self.default_configuration)
        }
 
+       fn get_genesis_hashes(&self) -> Option<Vec<ChainHash>> {
+               Some(vec![ChainHash::from(&self.genesis_hash[..])])
+       }
+
        fn handle_tx_add_input(&self, counterparty_node_id: &PublicKey, msg: &msgs::TxAddInput) {
                let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
                        "Dual-funded channels not supported".to_owned(),
@@ -7136,10 +7143,9 @@ impl Writeable for ChannelDetails {
                        (14, user_channel_id_low, required),
                        (16, self.balance_msat, required),
                        (18, self.outbound_capacity_msat, required),
-                       // Note that by the time we get past the required read above, outbound_capacity_msat will be
-                       // filled in, so we can safely unwrap it here.
-                       (19, self.next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap() as u64)),
+                       (19, self.next_outbound_htlc_limit_msat, required),
                        (20, self.inbound_capacity_msat, required),
+                       (21, self.next_outbound_htlc_minimum_msat, required),
                        (22, self.confirmations_required, option),
                        (24, self.force_close_spend_delay, option),
                        (26, self.is_outbound, required),
@@ -7176,6 +7182,7 @@ impl Readable for ChannelDetails {
                        // filled in, so we can safely unwrap it here.
                        (19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap() as u64)),
                        (20, inbound_capacity_msat, required),
+                       (21, next_outbound_htlc_minimum_msat, (default_value, 0)),
                        (22, confirmations_required, option),
                        (24, force_close_spend_delay, option),
                        (26, is_outbound, required),
@@ -7209,6 +7216,7 @@ impl Readable for ChannelDetails {
                        balance_msat: balance_msat.0.unwrap(),
                        outbound_capacity_msat: outbound_capacity_msat.0.unwrap(),
                        next_outbound_htlc_limit_msat: next_outbound_htlc_limit_msat.0.unwrap(),
+                       next_outbound_htlc_minimum_msat: next_outbound_htlc_minimum_msat.0.unwrap(),
                        inbound_capacity_msat: inbound_capacity_msat.0.unwrap(),
                        confirmations_required,
                        confirmations,
@@ -7245,6 +7253,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
                (0, payment_preimage, required),
                (2, incoming_cltv_expiry, required),
                (3, payment_metadata, option),
+               (4, payment_data, option), // Added in 0.0.116
        },
 ;);
 
@@ -8578,7 +8587,7 @@ mod tests {
        use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
        use crate::util::errors::APIError;
        use crate::util::test_utils;
-       use crate::util::config::ChannelConfig;
+       use crate::util::config::{ChannelConfig, ChannelConfigUpdate};
        use crate::sign::EntropySource;
 
        #[test]
@@ -8787,13 +8796,26 @@ mod tests {
 
        #[test]
        fn test_keysend_dup_payment_hash() {
+               do_test_keysend_dup_payment_hash(false);
+               do_test_keysend_dup_payment_hash(true);
+       }
+
+       fn do_test_keysend_dup_payment_hash(accept_mpp_keysend: bool) {
                // (1): Test that a keysend payment with a duplicate payment hash to an existing pending
                //      outbound regular payment fails as expected.
                // (2): Test that a regular payment with a duplicate payment hash to an existing keysend payment
                //      fails as expected.
+               // (3): Test that a keysend payment with a duplicate payment hash to an existing keysend
+               //      payment fails as expected. When `accept_mpp_keysend` is false, this tests that we
+               //      reject MPP keysend payments, since in this case where the payment has no payment
+               //      secret, a keysend payment with a duplicate hash is basically an MPP keysend. If
+               //      `accept_mpp_keysend` is true, this tests that we only accept MPP keysends with
+               //      payment secrets and reject otherwise.
                let chanmon_cfgs = create_chanmon_cfgs(2);
                let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
-               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+               let mut mpp_keysend_cfg = test_default_channel_config();
+               mpp_keysend_cfg.accept_mpp_keysend = accept_mpp_keysend;
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(mpp_keysend_cfg)]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                create_announced_chan_between_nodes(&nodes, 0, 1);
                let scorer = test_utils::TestScorer::new();
@@ -8805,7 +8827,7 @@ mod tests {
 
                // Next, attempt a keysend payment and make sure it fails.
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV),
+                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false),
                        final_value_msat: 100_000,
                };
                let route = find_route(
@@ -8882,6 +8904,53 @@ mod tests {
 
                // Finally, succeed the keysend payment.
                claim_payment(&nodes[0], &expected_route, payment_preimage);
+
+               // To start (3), send a keysend payment but don't claim it.
+               let payment_id_1 = PaymentId([44; 32]);
+               let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage),
+                       RecipientOnionFields::spontaneous_empty(), payment_id_1).unwrap();
+               check_added_monitors!(nodes[0], 1);
+               let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 1);
+               let event = events.pop().unwrap();
+               let path = vec![&nodes[1]];
+               pass_along_path(&nodes[0], &path, 100_000, payment_hash, None, event, true, Some(payment_preimage));
+
+               // Next, attempt a keysend payment and make sure it fails.
+               let route_params = RouteParameters {
+                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false),
+                       final_value_msat: 100_000,
+               };
+               let route = find_route(
+                       &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
+                       None, nodes[0].logger, &scorer, &(), &random_seed_bytes
+               ).unwrap();
+               let payment_id_2 = PaymentId([45; 32]);
+               nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage),
+                       RecipientOnionFields::spontaneous_empty(), payment_id_2).unwrap();
+               check_added_monitors!(nodes[0], 1);
+               let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 1);
+               let ev = events.drain(..).next().unwrap();
+               let payment_event = SendEvent::from_event(ev);
+               nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+               check_added_monitors!(nodes[1], 0);
+               commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+               expect_pending_htlcs_forwardable!(nodes[1]);
+               expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::FailedPayment { payment_hash }]);
+               check_added_monitors!(nodes[1], 1);
+               let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+               assert!(updates.update_add_htlcs.is_empty());
+               assert!(updates.update_fulfill_htlcs.is_empty());
+               assert_eq!(updates.update_fail_htlcs.len(), 1);
+               assert!(updates.update_fail_malformed_htlcs.is_empty());
+               assert!(updates.update_fee.is_none());
+               nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+               commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, true, true);
+               expect_payment_failed!(nodes[0], payment_hash, true);
+
+               // Finally, claim the original payment.
+               claim_payment(&nodes[0], &expected_route, payment_preimage);
        }
 
        #[test]
@@ -8898,7 +8967,7 @@ mod tests {
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
+                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
                        final_value_msat: 10_000,
                };
                let network_graph = nodes[0].network_graph.clone();
@@ -8931,10 +9000,13 @@ mod tests {
 
        #[test]
        fn test_keysend_msg_with_secret_err() {
-               // Test that we error as expected if we receive a keysend payment that includes a payment secret.
+               // Test that we error as expected if we receive a keysend payment that includes a payment
+               // secret when we don't support MPP keysend.
+               let mut reject_mpp_keysend_cfg = test_default_channel_config();
+               reject_mpp_keysend_cfg.accept_mpp_keysend = false;
                let chanmon_cfgs = create_chanmon_cfgs(2);
                let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
-               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+               let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(reject_mpp_keysend_cfg)]);
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 
                let payer_pubkey = nodes[0].node.get_our_node_id();
@@ -8942,7 +9014,7 @@ mod tests {
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
                let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40),
+                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
                        final_value_msat: 10_000,
                };
                let network_graph = nodes[0].network_graph.clone();
@@ -9297,12 +9369,14 @@ mod tests {
                                &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
                        peer_pks.push(random_pk);
                        nodes[1].node.peer_connected(&random_pk, &msgs::Init {
-                               features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+                               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+                       }, true).unwrap();
                }
                let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
                        &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
                nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap_err();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap_err();
 
                // Also importantly, because nodes[0] isn't "protected", we will refuse a reconnection from
                // them if we have too many un-channel'd peers.
@@ -9313,13 +9387,16 @@ mod tests {
                        if let Event::ChannelClosed { .. } = ev { } else { panic!(); }
                }
                nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap();
                nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap_err();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap_err();
 
                // but of course if the connection is outbound its allowed...
                nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, false).unwrap();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, false).unwrap();
                nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
 
                // Now nodes[0] is disconnected but still has a pending, un-funded channel lying around.
@@ -9343,7 +9420,8 @@ mod tests {
                // "protected" and can connect again.
                mine_transaction(&nodes[1], funding_tx.as_ref().unwrap());
                nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap();
                get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
 
                // Further, because the first channel was funded, we can open another channel with
@@ -9408,7 +9486,8 @@ mod tests {
                        let random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
                                &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
                        nodes[1].node.peer_connected(&random_pk, &msgs::Init {
-                               features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+                               features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+                       }, true).unwrap();
 
                        nodes[1].node.handle_open_channel(&random_pk, &open_channel_msg);
                        let events = nodes[1].node.get_and_clear_pending_events();
@@ -9426,7 +9505,8 @@ mod tests {
                let last_random_pk = PublicKey::from_secret_key(&nodes[0].node.secp_ctx,
                        &SecretKey::from_slice(&nodes[1].keys_manager.get_secure_random_bytes()).unwrap());
                nodes[1].node.peer_connected(&last_random_pk, &msgs::Init {
-                       features: nodes[0].node.init_features(), remote_network_address: None }, true).unwrap();
+                       features: nodes[0].node.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap();
                nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg);
                let events = nodes[1].node.get_and_clear_pending_events();
                match events[0] {
@@ -9489,6 +9569,62 @@ mod tests {
 
                check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed);
        }
+
+       #[test]
+       fn test_update_channel_config() {
+               let chanmon_cfg = create_chanmon_cfgs(2);
+               let node_cfg = create_node_cfgs(2, &chanmon_cfg);
+               let mut user_config = test_default_channel_config();
+               let node_chanmgr = create_node_chanmgrs(2, &node_cfg, &[Some(user_config), Some(user_config)]);
+               let nodes = create_network(2, &node_cfg, &node_chanmgr);
+               let _ = create_announced_chan_between_nodes(&nodes, 0, 1);
+               let channel = &nodes[0].node.list_channels()[0];
+
+               nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap();
+               let events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 0);
+
+               user_config.channel_config.forwarding_fee_base_msat += 10;
+               nodes[0].node.update_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &user_config.channel_config).unwrap();
+               assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_base_msat, user_config.channel_config.forwarding_fee_base_msat);
+               let events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 1);
+               match &events[0] {
+                       MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+                       _ => panic!("expected BroadcastChannelUpdate event"),
+               }
+
+               nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate::default()).unwrap();
+               let events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 0);
+
+               let new_cltv_expiry_delta = user_config.channel_config.cltv_expiry_delta + 6;
+               nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate {
+                       cltv_expiry_delta: Some(new_cltv_expiry_delta),
+                       ..Default::default()
+               }).unwrap();
+               assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, new_cltv_expiry_delta);
+               let events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 1);
+               match &events[0] {
+                       MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+                       _ => panic!("expected BroadcastChannelUpdate event"),
+               }
+
+               let new_fee = user_config.channel_config.forwarding_fee_proportional_millionths + 100;
+               nodes[0].node.update_partial_channel_config(&channel.counterparty.node_id, &[channel.channel_id], &ChannelConfigUpdate {
+                       forwarding_fee_proportional_millionths: Some(new_fee),
+                       ..Default::default()
+               }).unwrap();
+               assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().cltv_expiry_delta, new_cltv_expiry_delta);
+               assert_eq!(nodes[0].node.list_channels()[0].config.unwrap().forwarding_fee_proportional_millionths, new_fee);
+               let events = nodes[0].node.get_and_clear_pending_msg_events();
+               assert_eq!(events.len(), 1);
+               match &events[0] {
+                       MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+                       _ => panic!("expected BroadcastChannelUpdate event"),
+               }
+       }
 }
 
 #[cfg(ldk_bench)]
@@ -9570,8 +9706,12 @@ pub mod bench {
                });
                let node_b_holder = ANodeHolder { node: &node_b };
 
-               node_a.peer_connected(&node_b.get_our_node_id(), &Init { features: node_b.init_features(), remote_network_address: None }, true).unwrap();
-               node_b.peer_connected(&node_a.get_our_node_id(), &Init { features: node_a.init_features(), remote_network_address: None }, false).unwrap();
+               node_a.peer_connected(&node_b.get_our_node_id(), &Init {
+                       features: node_b.init_features(), networks: None, remote_network_address: None
+               }, true).unwrap();
+               node_b.peer_connected(&node_a.get_our_node_id(), &Init {
+                       features: node_a.init_features(), networks: None, remote_network_address: None
+               }, false).unwrap();
                node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap();
                node_b.handle_open_channel(&node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id()));
                node_a.handle_accept_channel(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));