Merge pull request #1096 from valentinewallace/2021-09-mpp-retries
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Thu, 30 Sep 2021 01:19:04 +0000 (01:19 +0000)
committerGitHub <noreply@github.com>
Thu, 30 Sep 2021 01:19:04 +0000 (01:19 +0000)
1  2 
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_tests.rs

index 11995c50d7fa0e1314fe3edcfadaca4993b7ec10,4bb549d8f6c59f5b964f5f361ad6f32792082512..4a6e4eb656b6f6fa2f9a5076814853d8ac77f9ea
@@@ -26,7 -26,7 +26,7 @@@ use ln::{PaymentPreimage, PaymentHash}
  use ln::features::{ChannelFeatures, InitFeatures};
  use ln::msgs;
  use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
 -use ln::script::ShutdownScript;
 +use ln::script::{self, ShutdownScript};
  use ln::channelmanager::{CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
  use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
  use ln::chan_utils;
@@@ -44,6 -44,7 +44,6 @@@ use util::scid_utils::scid_from_parts
  use io;
  use prelude::*;
  use core::{cmp,mem,fmt};
 -use core::convert::TryFrom;
  use core::ops::Deref;
  #[cfg(any(test, feature = "fuzztarget", debug_assertions))]
  use sync::Mutex;
@@@ -554,24 -555,21 +554,24 @@@ pub const ANCHOR_OUTPUT_VALUE_SATOSHI: 
  /// it's 2^24.
  pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24;
  
 -/// Maximum counterparty `dust_limit_satoshis` allowed. 2 * standard dust threshold on p2wsh output
 -/// Scales up on Bitcoin Core's proceeding policy with dust outputs. A typical p2wsh output is 43
 -/// bytes to which Core's `GetDustThreshold()` sums up a minimal spend of 67 bytes (even if
 -/// a p2wsh witnessScript might be *effectively* smaller), `dustRelayFee` is set to 3000sat/kb, thus
 -/// 110 * 3000 / 1000 = 330. Per-protocol rules, all time-sensitive outputs are p2wsh, a value of
 -/// 330 sats is the lower bound desired to ensure good propagation of transactions. We give a bit
 -/// of margin to our counterparty and pick up 660 satoshis as an accepted `dust_limit_satoshis`
 -/// upper bound to avoid negotiation conflicts with other implementations.
 -pub const MAX_DUST_LIMIT_SATOSHIS: u64 = 2 * 330;
 -
 -/// A typical p2wsh output is 43 bytes to which Core's `GetDustThreshold()` sums up a minimal
 -/// spend of 67 bytes (even if a p2wsh witnessScript might be *effectively* smaller), `dustRelayFee`
 -/// is set to 3000sat/kb, thus 110 * 3000 / 1000 = 330. Per-protocol rules, all time-sensitive outputs
 -/// are p2wsh, a value of 330 sats is the lower bound desired to ensure good propagation of transactions.
 -pub const MIN_DUST_LIMIT_SATOSHIS: u64 = 330;
 +/// The maximum network dust limit for standard script formats. This currently represents the
 +/// minimum output value for a P2SH output before Bitcoin Core 22 considers the entire
 +/// transaction non-standard and thus refuses to relay it.
 +/// We also use this as the maximum counterparty `dust_limit_satoshis` allowed, given many
 +/// implementations use this value for their dust limit today.
 +pub const MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS: u64 = 546;
 +
 +/// The maximum channel dust limit we will accept from our counterparty.
 +pub const MAX_CHAN_DUST_LIMIT_SATOSHIS: u64 = MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS;
 +
 +/// The dust limit is used for both the commitment transaction outputs as well as the closing
 +/// transactions. For cooperative closing transactions, we require segwit outputs, though accept
 +/// *any* segwit scripts, which are allowed to be up to 42 bytes in length.
 +/// In order to avoid having to concern ourselves with standardness during the closing process, we
 +/// simply require our counterparty to use a dust limit which will leave any segwit output
 +/// standard.
 +/// See https://github.com/lightningnetwork/lightning-rfc/issues/905 for more details.
 +pub const MIN_CHAN_DUST_LIMIT_SATOSHIS: u64 = 354;
  
  /// Used to return a simple Error back to ChannelManager. Will get converted to a
  /// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our
@@@ -638,7 -636,7 +638,7 @@@ impl<Signer: Sign> Channel<Signer> 
                        return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)});
                }
                let holder_selected_channel_reserve_satoshis = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis);
 -              if holder_selected_channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS {
 +              if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
                        return Err(APIError::APIMisuseError { err: format!("Holder selected channel  reserve below implemention limit dust_limit_satoshis {}", holder_selected_channel_reserve_satoshis) });
                }
  
  
                        feerate_per_kw: feerate,
                        counterparty_dust_limit_satoshis: 0,
 -                      holder_dust_limit_satoshis: MIN_DUST_LIMIT_SATOSHIS,
 +                      holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
                        counterparty_max_htlc_value_in_flight_msat: 0,
                        counterparty_selected_channel_reserve_satoshis: None, // Filled in in accept_channel
                        counterparty_htlc_minimum_msat: 0,
                if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs {
                        return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs)));
                }
 -              if msg.dust_limit_satoshis < MIN_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_DUST_LIMIT_SATOSHIS)));
 +              if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
                }
 -              if msg.dust_limit_satoshis >  MAX_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS)));
 +              if msg.dust_limit_satoshis >  MAX_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
                }
  
                // Convert things into internal flags and prep our state:
                let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
  
                let holder_selected_channel_reserve_satoshis = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis);
 -              if holder_selected_channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, MIN_DUST_LIMIT_SATOSHIS)));
 +              if holder_selected_channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
                }
 -              if msg.channel_reserve_satoshis < MIN_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, MIN_DUST_LIMIT_SATOSHIS)));
 +              if msg.channel_reserve_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
                }
                if holder_selected_channel_reserve_satoshis < msg.dust_limit_satoshis {
                        return Err(ChannelError::Close(format!("Dust limit ({}) too high for the channel reserve we require the remote to keep ({})", msg.dust_limit_satoshis, holder_selected_channel_reserve_satoshis)));
                                        if script.len() == 0 {
                                                None
                                        } else {
 -                                              match ShutdownScript::try_from((script.clone(), their_features)) {
 -                                                      Ok(shutdown_script) => Some(shutdown_script.into_inner()),
 -                                                      Err(_) => return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script))),
 +                                              if !script::is_bolt2_compliant(&script, their_features) {
 +                                                      return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script)))
                                                }
 +                                              Some(script.clone())
                                        }
                                },
                                // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
                        feerate_per_kw: msg.feerate_per_kw,
                        channel_value_satoshis: msg.funding_satoshis,
                        counterparty_dust_limit_satoshis: msg.dust_limit_satoshis,
 -                      holder_dust_limit_satoshis: MIN_DUST_LIMIT_SATOSHIS,
 +                      holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
                        counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
                        counterparty_selected_channel_reserve_satoshis: Some(msg.channel_reserve_satoshis),
                        counterparty_htlc_minimum_msat: msg.htlc_minimum_msat,
                if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs {
                        return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs)));
                }
 -              if msg.dust_limit_satoshis < MIN_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_DUST_LIMIT_SATOSHIS)));
 +              if msg.dust_limit_satoshis < MIN_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the implementation limit ({})", msg.dust_limit_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS)));
                }
 -              if msg.dust_limit_satoshis > MAX_DUST_LIMIT_SATOSHIS {
 -                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS)));
 +              if msg.dust_limit_satoshis > MAX_CHAN_DUST_LIMIT_SATOSHIS {
 +                      return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_CHAN_DUST_LIMIT_SATOSHIS)));
                }
                if msg.minimum_depth > config.peer_channel_config_limits.max_minimum_depth {
                        return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", config.peer_channel_config_limits.max_minimum_depth, msg.minimum_depth)));
                                        if script.len() == 0 {
                                                None
                                        } else {
 -                                              match ShutdownScript::try_from((script.clone(), their_features)) {
 -                                                      Ok(shutdown_script) => Some(shutdown_script.into_inner()),
 -                                                      Err(_) => return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script))),
 +                                              if !script::is_bolt2_compliant(&script, their_features) {
 +                                                      return Err(ChannelError::Close(format!("Peer is signaling upfront_shutdown but has provided an unacceptable scriptpubkey format: {}", script)));
                                                }
 +                                              Some(script.clone())
                                        }
                                },
                                // Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
                }
                assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
  
 -              let shutdown_scriptpubkey = match ShutdownScript::try_from((msg.scriptpubkey.clone(), their_features)) {
 -                      Ok(script) => script.into_inner(),
 -                      Err(_) => return Err(ChannelError::Close(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_bytes().to_hex()))),
 -              };
 +              if !script::is_bolt2_compliant(&msg.scriptpubkey, their_features) {
 +                      return Err(ChannelError::Close(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_bytes().to_hex())));
 +              }
  
                if self.counterparty_shutdown_scriptpubkey.is_some() {
 -                      if Some(&shutdown_scriptpubkey) != self.counterparty_shutdown_scriptpubkey.as_ref() {
 -                              return Err(ChannelError::Close(format!("Got shutdown request with a scriptpubkey ({}) which did not match their previous scriptpubkey.", shutdown_scriptpubkey.to_bytes().to_hex())));
 +                      if Some(&msg.scriptpubkey) != self.counterparty_shutdown_scriptpubkey.as_ref() {
 +                              return Err(ChannelError::Close(format!("Got shutdown request with a scriptpubkey ({}) which did not match their previous scriptpubkey.", msg.scriptpubkey.to_bytes().to_hex())));
                        }
                } else {
 -                      self.counterparty_shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
 +                      self.counterparty_shutdown_scriptpubkey = Some(msg.scriptpubkey.clone());
                }
  
                // If we have any LocalAnnounced updates we'll probably just get back an update_fail_htlc
                        },
                };
  
 +              for outp in closing_tx.trust().built_transaction().output.iter() {
 +                      if !outp.script_pubkey.is_witness_program() && outp.value < MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS {
 +                              return Err(ChannelError::Close("Remote sent us a closing_signed with a dust output. Always use segwit closing scripts!".to_owned()));
 +                      }
 +              }
 +
                assert!(self.shutdown_scriptpubkey.is_some());
                if let Some((last_fee, sig)) = self.last_sent_closing_fee {
                        if last_fee == msg.fee_satoshis {
@@@ -5516,7 -5509,7 +5516,7 @@@ mod tests 
        use bitcoin::hashes::hex::FromHex;
        use hex;
        use ln::{PaymentPreimage, PaymentHash};
-       use ln::channelmanager::{HTLCSource, MppId};
+       use ln::channelmanager::{HTLCSource, PaymentId};
        use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys};
        use ln::channel::MAX_FUNDING_SATOSHIS;
        use ln::features::InitFeatures;
                                path: Vec::new(),
                                session_priv: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
                                first_hop_htlc_msat: 548,
-                               mpp_id: MppId([42; 32]),
+                               payment_id: PaymentId([42; 32]),
                        }
                });
  
index f154ab3dc79670186d46c1433462a7d256944e00,e165134e8e37fb1ef551c227a24b1f0a317d732a..b29199e862442109963b8372a7bdc207ead7142a
@@@ -172,20 -172,20 +172,20 @@@ struct ClaimableHTLC 
        onion_payload: OnionPayload,
  }
  
- /// A payment identifier used to correlate an MPP payment's per-path HTLC sources internally.
+ /// A payment identifier used to uniquely identify a payment to LDK.
  #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
- pub(crate) struct MppId(pub [u8; 32]);
+ pub struct PaymentId(pub [u8; 32]);
  
- impl Writeable for MppId {
+ impl Writeable for PaymentId {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.0.write(w)
        }
  }
  
- impl Readable for MppId {
+ impl Readable for PaymentId {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
                let buf: [u8; 32] = Readable::read(r)?;
-               Ok(MppId(buf))
+               Ok(PaymentId(buf))
        }
  }
  /// Tracks the inbound corresponding to an outbound HTLC
@@@ -198,7 -198,7 +198,7 @@@ pub(crate) enum HTLCSource 
                /// Technically we can recalculate this from the route, but we cache it here to avoid
                /// doing a double-pass on route when we get a failure back
                first_hop_htlc_msat: u64,
-               mpp_id: MppId,
+               payment_id: PaymentId,
        },
  }
  #[cfg(test)]
@@@ -208,7 -208,7 +208,7 @@@ impl HTLCSource 
                        path: Vec::new(),
                        session_priv: SecretKey::from_slice(&[1; 32]).unwrap(),
                        first_hop_htlc_msat: 0,
-                       mpp_id: MppId([2; 32]),
+                       payment_id: PaymentId([2; 32]),
                }
        }
  }
@@@ -400,6 -400,65 +400,65 @@@ struct PendingInboundPayment 
        min_value_msat: Option<u64>,
  }
  
+ /// Stores the session_priv for each part of a payment that is still pending. For versions 0.0.102
+ /// and later, also stores information for retrying the payment.
+ enum PendingOutboundPayment {
+       Legacy {
+               session_privs: HashSet<[u8; 32]>,
+       },
+       Retryable {
+               session_privs: HashSet<[u8; 32]>,
+               payment_hash: PaymentHash,
+               payment_secret: Option<PaymentSecret>,
+               pending_amt_msat: u64,
+               /// The total payment amount across all paths, used to verify that a retry is not overpaying.
+               total_msat: u64,
+               /// Our best known block height at the time this payment was initiated.
+               starting_block_height: u32,
+       },
+ }
+ impl PendingOutboundPayment {
+       fn remove(&mut self, session_priv: &[u8; 32], part_amt_msat: u64) -> bool {
+               let remove_res = match self {
+                       PendingOutboundPayment::Legacy { session_privs } |
+                       PendingOutboundPayment::Retryable { session_privs, .. } => {
+                               session_privs.remove(session_priv)
+                       }
+               };
+               if remove_res {
+                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self {
+                               *pending_amt_msat -= part_amt_msat;
+                       }
+               }
+               remove_res
+       }
+       fn insert(&mut self, session_priv: [u8; 32], part_amt_msat: u64) -> bool {
+               let insert_res = match self {
+                       PendingOutboundPayment::Legacy { session_privs } |
+                       PendingOutboundPayment::Retryable { session_privs, .. } => {
+                               session_privs.insert(session_priv)
+                       }
+               };
+               if insert_res {
+                       if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self {
+                               *pending_amt_msat += part_amt_msat;
+                       }
+               }
+               insert_res
+       }
+       fn remaining_parts(&self) -> usize {
+               match self {
+                       PendingOutboundPayment::Legacy { session_privs } |
+                       PendingOutboundPayment::Retryable { session_privs, .. } => {
+                               session_privs.len()
+                       }
+               }
+       }
+ }
  /// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
  /// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
  /// lifetimes). Other times you can afford a reference, which is more efficient, in which case
@@@ -486,7 -545,7 +545,7 @@@ pub struct ChannelManager<Signer: Sign
        /// Locked *after* channel_state.
        pending_inbound_payments: Mutex<HashMap<PaymentHash, PendingInboundPayment>>,
  
-       /// The session_priv bytes of outbound payments which are pending resolution.
+       /// The session_priv bytes and retry metadata of outbound payments which are pending resolution.
        /// The authoritative state of these HTLCs resides either within Channels or ChannelMonitors
        /// (if the channel has been force-closed), however we track them here to prevent duplicative
        /// PaymentSent/PaymentPathFailed events. Specifically, in the case of a duplicative
        /// which may generate a claim event, we may receive similar duplicate claim/fail MonitorEvents
        /// after reloading from disk while replaying blocks against ChannelMonitors.
        ///
-       /// Each payment has each of its MPP part's session_priv bytes in the HashSet of the map (even
-       /// payments over a single path).
+       /// See `PendingOutboundPayment` documentation for more info.
        ///
        /// Locked *after* channel_state.
-       pending_outbound_payments: Mutex<HashMap<MppId, HashSet<[u8; 32]>>>,
+       pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
  
        our_network_key: SecretKey,
        our_network_pubkey: PublicKey,
@@@ -1878,7 -1936,7 +1936,7 @@@ impl<Signer: Sign, M: Deref, T: Deref, 
        }
  
        // Only public for testing, this should otherwise never be called direcly
-       pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, mpp_id: MppId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
+       pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
                log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
                let prng_seed = self.keys_manager.get_secure_random_bytes();
                let session_priv_bytes = self.keys_manager.get_secure_random_bytes();
  
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
                let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
-               let sessions = pending_outbounds.entry(mpp_id).or_insert(HashSet::new());
-               assert!(sessions.insert(session_priv_bytes));
+               let payment = pending_outbounds.entry(payment_id).or_insert_with(|| PendingOutboundPayment::Retryable {
+                       session_privs: HashSet::new(),
+                       pending_amt_msat: 0,
+                       payment_hash: *payment_hash,
+                       payment_secret: *payment_secret,
+                       starting_block_height: self.best_block.read().unwrap().height(),
+                       total_msat: total_value,
+               });
+               assert!(payment.insert(session_priv_bytes, path.last().unwrap().fee_msat));
  
                let err: Result<(), _> = loop {
                        let mut channel_lock = self.channel_state.lock().unwrap();
                                                path: path.clone(),
                                                session_priv: session_priv.clone(),
                                                first_hop_htlc_msat: htlc_msat,
-                                               mpp_id,
+                                               payment_id,
                                        }, onion_packet, &self.logger), channel_state, chan)
                                } {
                                        Some((update_add, commitment_signed, monitor_update)) => {
        /// If a payment_secret *is* provided, we assume that the invoice had the payment_secret feature
        /// bit set (either as required or as available). If multiple paths are present in the Route,
        /// we assume the invoice had the basic_mpp feature set.
-       pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>) -> Result<(), PaymentSendFailure> {
-               self.send_payment_internal(route, payment_hash, payment_secret, None)
+       pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>) -> Result<PaymentId, PaymentSendFailure> {
+               self.send_payment_internal(route, payment_hash, payment_secret, None, None, None)
        }
  
-       fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>) -> Result<(), PaymentSendFailure> {
+       fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>, payment_id: Option<PaymentId>, recv_value_msat: Option<u64>) -> Result<PaymentId, PaymentSendFailure> {
                if route.paths.len() < 1 {
                        return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
                }
                let mut total_value = 0;
                let our_node_id = self.get_our_node_id();
                let mut path_errs = Vec::with_capacity(route.paths.len());
-               let mpp_id = MppId(self.keys_manager.get_secure_random_bytes());
+               let payment_id = if let Some(id) = payment_id { id } else { PaymentId(self.keys_manager.get_secure_random_bytes()) };
                'path_check: for path in route.paths.iter() {
                        if path.len() < 1 || path.len() > 20 {
                                path_errs.push(Err(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"}));
                if path_errs.iter().any(|e| e.is_err()) {
                        return Err(PaymentSendFailure::PathParameterError(path_errs));
                }
+               if let Some(amt_msat) = recv_value_msat {
+                       debug_assert!(amt_msat >= total_value);
+                       total_value = amt_msat;
+               }
  
                let cur_height = self.best_block.read().unwrap().height() + 1;
                let mut results = Vec::new();
                for path in route.paths.iter() {
-                       results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, mpp_id, &keysend_preimage));
+                       results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage));
                }
                let mut has_ok = false;
                let mut has_err = false;
                } else if has_err {
                        Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect()))
                } else {
-                       Ok(())
+                       Ok(payment_id)
                }
        }
  
+       /// Retries a payment along the given [`Route`].
+       ///
+       /// Errors returned are a superset of those returned from [`send_payment`], so see
+       /// [`send_payment`] documentation for more details on errors. This method will also error if the
+       /// retry amount puts the payment more than 10% over the payment's total amount, or if the payment
+       /// for the given `payment_id` cannot be found (likely due to timeout or success).
+       ///
+       /// [`send_payment`]: [`ChannelManager::send_payment`]
+       pub fn retry_payment(&self, route: &Route, payment_id: PaymentId) -> Result<(), PaymentSendFailure> {
+               const RETRY_OVERFLOW_PERCENTAGE: u64 = 10;
+               for path in route.paths.iter() {
+                       if path.len() == 0 {
+                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                                       err: "length-0 path in route".to_string()
+                               }))
+                       }
+               }
+               let (total_msat, payment_hash, payment_secret) = {
+                       let outbounds = self.pending_outbound_payments.lock().unwrap();
+                       if let Some(payment) = outbounds.get(&payment_id) {
+                               match payment {
+                                       PendingOutboundPayment::Retryable {
+                                               total_msat, payment_hash, payment_secret, pending_amt_msat, ..
+                                       } => {
+                                               let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum();
+                                               if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 {
+                                                       return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                                                               err: format!("retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat).to_string()
+                                                       }))
+                                               }
+                                               (*total_msat, *payment_hash, *payment_secret)
+                                       },
+                                       PendingOutboundPayment::Legacy { .. } => {
+                                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                                                       err: "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102".to_string()
+                                               }))
+                                       }
+                               }
+                       } else {
+                               return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
+                                       err: "Payment with ID {} not found".to_string()
+                               }))
+                       }
+               };
+               return self.send_payment_internal(route, payment_hash, &payment_secret, None, Some(payment_id), Some(total_msat)).map(|_| ())
+       }
        /// Send a spontaneous payment, which is a payment that does not require the recipient to have
        /// generated an invoice. Optionally, you may specify the preimage. If you do choose to specify
        /// the preimage, it must be a cryptographically secure random value that no intermediate node
        /// 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>) -> Result<PaymentHash, PaymentSendFailure> {
+       pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option<PaymentPreimage>) -> Result<(PaymentHash, PaymentId), PaymentSendFailure> {
                let preimage = match payment_preimage {
                        Some(p) => p,
                        None => PaymentPreimage(self.keys_manager.get_secure_random_bytes()),
                };
                let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner());
-               match self.send_payment_internal(route, payment_hash, &None, Some(preimage)) {
-                       Ok(()) => Ok(payment_hash),
+               match self.send_payment_internal(route, payment_hash, &None, Some(preimage), None, None) {
+                       Ok(payment_id) => Ok((payment_hash, payment_id)),
                        Err(e) => Err(e)
                }
        }
                                        self.fail_htlc_backwards_internal(channel_state,
                                                htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data});
                                },
-                               HTLCSource::OutboundRoute { session_priv, mpp_id, path, .. } => {
+                               HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
                                        let mut session_priv_bytes = [0; 32];
                                        session_priv_bytes.copy_from_slice(&session_priv[..]);
                                        let mut outbounds = self.pending_outbound_payments.lock().unwrap();
-                                       if let hash_map::Entry::Occupied(mut sessions) = outbounds.entry(mpp_id) {
-                                               if sessions.get_mut().remove(&session_priv_bytes) {
+                                       if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
+                                               if payment.get_mut().remove(&session_priv_bytes, path.last().unwrap().fee_msat) {
                                                        self.pending_events.lock().unwrap().push(
                                                                events::Event::PaymentPathFailed {
                                                                        payment_hash,
                                                                        rejected_by_dest: false,
                                                                        network_update: None,
-                                                                       all_paths_failed: sessions.get().len() == 0,
+                                                                       all_paths_failed: payment.get().remaining_parts() == 0,
                                                                        path: path.clone(),
                                                                        #[cfg(test)]
                                                                        error_code: None,
                                                                        error_data: None,
                                                                }
                                                        );
-                                                       if sessions.get().len() == 0 {
-                                                               sessions.remove();
-                                                       }
                                                }
                                        } else {
                                                log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
                // from block_connected which may run during initialization prior to the chain_monitor
                // being fully configured. See the docs for `ChannelManagerReadArgs` for more.
                match source {
-                       HTLCSource::OutboundRoute { ref path, session_priv, mpp_id, .. } => {
+                       HTLCSource::OutboundRoute { ref path, session_priv, payment_id, .. } => {
                                let mut session_priv_bytes = [0; 32];
                                session_priv_bytes.copy_from_slice(&session_priv[..]);
                                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
                                let mut all_paths_failed = false;
-                               if let hash_map::Entry::Occupied(mut sessions) = outbounds.entry(mpp_id) {
-                                       if !sessions.get_mut().remove(&session_priv_bytes) {
+                               if let hash_map::Entry::Occupied(mut sessions) = outbounds.entry(payment_id) {
+                                       if !sessions.get_mut().remove(&session_priv_bytes, path.last().unwrap().fee_msat) {
                                                log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
                                                return;
                                        }
-                                       if sessions.get().len() == 0 {
+                                       if sessions.get().remaining_parts() == 0 {
                                                all_paths_failed = true;
-                                               sessions.remove();
                                        }
                                } else {
                                        log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
  
        fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard<ChannelHolder<Signer>>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option<u64>, from_onchain: bool) {
                match source {
-                       HTLCSource::OutboundRoute { session_priv, mpp_id, .. } => {
+                       HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
                                mem::drop(channel_state_lock);
                                let mut session_priv_bytes = [0; 32];
                                session_priv_bytes.copy_from_slice(&session_priv[..]);
                                let mut outbounds = self.pending_outbound_payments.lock().unwrap();
-                               let found_payment = if let Some(mut sessions) = outbounds.remove(&mpp_id) {
-                                       sessions.remove(&session_priv_bytes)
+                               let found_payment = if let Some(mut sessions) = outbounds.remove(&payment_id) {
+                                       sessions.remove(&session_priv_bytes, path.last().unwrap().fee_msat)
                                } else { false };
                                if found_payment {
                                        self.pending_events.lock().unwrap().push(
                                                Err(e) => try_chan_entry!(self, Err(e), channel_state, chan),
                                        };
                                        if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
 -                                              return_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
 +                                              let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
 +                                              if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res {
 +                                                      // We weren't able to watch the channel to begin with, so no updates should be made on
 +                                                      // it. Previously, full_stack_target found an (unreachable) panic when the
 +                                                      // monitor update contained within `shutdown_finish` was applied.
 +                                                      if let Some((ref mut shutdown_finish, _)) = shutdown_finish {
 +                                                              shutdown_finish.0.take();
 +                                                      }
 +                                              }
 +                                              return res
                                        }
                                        funding_tx
                                },
@@@ -4445,6 -4549,16 +4558,16 @@@ wher
                payment_secrets.retain(|_, inbound_payment| {
                        inbound_payment.expiry_time > header.time as u64
                });
+               let mut outbounds = self.pending_outbound_payments.lock().unwrap();
+               outbounds.retain(|_, payment| {
+                       const PAYMENT_EXPIRY_BLOCKS: u32 = 3;
+                       if payment.remaining_parts() != 0 { return true }
+                       if let PendingOutboundPayment::Retryable { starting_block_height, .. } = payment {
+                               return *starting_block_height + PAYMENT_EXPIRY_BLOCKS > height
+                       }
+                       true
+               });
        }
  
        fn get_relevant_txids(&self) -> Vec<Txid> {
@@@ -5088,23 -5202,23 +5211,23 @@@ impl Readable for HTLCSource 
                                let mut session_priv: ::util::ser::OptionDeserWrapper<SecretKey> = ::util::ser::OptionDeserWrapper(None);
                                let mut first_hop_htlc_msat: u64 = 0;
                                let mut path = Some(Vec::new());
-                               let mut mpp_id = None;
+                               let mut payment_id = None;
                                read_tlv_fields!(reader, {
                                        (0, session_priv, required),
-                                       (1, mpp_id, option),
+                                       (1, payment_id, option),
                                        (2, first_hop_htlc_msat, required),
                                        (4, path, vec_type),
                                });
-                               if mpp_id.is_none() {
-                                       // For backwards compat, if there was no mpp_id written, use the session_priv bytes
+                               if payment_id.is_none() {
+                                       // For backwards compat, if there was no payment_id written, use the session_priv bytes
                                        // instead.
-                                       mpp_id = Some(MppId(*session_priv.0.unwrap().as_ref()));
+                                       payment_id = Some(PaymentId(*session_priv.0.unwrap().as_ref()));
                                }
                                Ok(HTLCSource::OutboundRoute {
                                        session_priv: session_priv.0.unwrap(),
                                        first_hop_htlc_msat: first_hop_htlc_msat,
                                        path: path.unwrap(),
-                                       mpp_id: mpp_id.unwrap(),
+                                       payment_id: payment_id.unwrap(),
                                })
                        }
                        1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
  impl Writeable for HTLCSource {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::io::Error> {
                match self {
-                       HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, mpp_id } => {
+                       HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id } => {
                                0u8.write(writer)?;
-                               let mpp_id_opt = Some(mpp_id);
+                               let payment_id_opt = Some(payment_id);
                                write_tlv_fields!(writer, {
                                        (0, session_priv, required),
-                                       (1, mpp_id_opt, option),
+                                       (1, payment_id_opt, option),
                                        (2, first_hop_htlc_msat, required),
                                        (4, path, vec_type),
                                 });
@@@ -5166,6 -5280,20 +5289,20 @@@ impl_writeable_tlv_based!(PendingInboun
        (8, min_value_msat, required),
  });
  
+ impl_writeable_tlv_based_enum!(PendingOutboundPayment,
+       (0, Legacy) => {
+               (0, session_privs, required),
+       },
+       (2, Retryable) => {
+               (0, session_privs, required),
+               (2, payment_hash, required),
+               (4, payment_secret, option),
+               (6, total_msat, required),
+               (8, pending_amt_msat, required),
+               (10, starting_block_height, required),
+       },
+ ;);
  impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
        where M::Target: chain::Watch<Signer>,
          T::Target: BroadcasterInterface,
                let pending_outbound_payments = self.pending_outbound_payments.lock().unwrap();
                // For backwards compat, write the session privs and their total length.
                let mut num_pending_outbounds_compat: u64 = 0;
-               for (_, outbounds) in pending_outbound_payments.iter() {
-                       num_pending_outbounds_compat += outbounds.len() as u64;
+               for (_, outbound) in pending_outbound_payments.iter() {
+                       num_pending_outbounds_compat += outbound.remaining_parts() as u64;
                }
                num_pending_outbounds_compat.write(writer)?;
-               for (_, outbounds) in pending_outbound_payments.iter() {
-                       for outbound in outbounds.iter() {
-                               outbound.write(writer)?;
+               for (_, outbound) in pending_outbound_payments.iter() {
+                       match outbound {
+                               PendingOutboundPayment::Legacy { session_privs } |
+                               PendingOutboundPayment::Retryable { session_privs, .. } => {
+                                       for session_priv in session_privs.iter() {
+                                               session_priv.write(writer)?;
+                                       }
+                               }
                        }
                }
  
+               // Encode without retry info for 0.0.101 compatibility.
+               let mut pending_outbound_payments_no_retry: HashMap<PaymentId, HashSet<[u8; 32]>> = HashMap::new();
+               for (id, outbound) in pending_outbound_payments.iter() {
+                       match outbound {
+                               PendingOutboundPayment::Legacy { session_privs } |
+                               PendingOutboundPayment::Retryable { session_privs, .. } => {
+                                       pending_outbound_payments_no_retry.insert(*id, session_privs.clone());
+                               }
+                       }
+               }
                write_tlv_fields!(writer, {
-                       (1, pending_outbound_payments, required),
+                       (1, pending_outbound_payments_no_retry, required),
+                       (3, pending_outbound_payments, required),
                });
  
                Ok(())
@@@ -5505,16 -5649,6 +5658,16 @@@ impl<'a, Signer: Sign, M: Deref, T: Der
                                None => continue,
                        }
                }
 +              if forward_htlcs_count > 0 {
 +                      // If we have pending HTLCs to forward, assume we either dropped a
 +                      // `PendingHTLCsForwardable` or the user received it but never processed it as they
 +                      // shut down before the timer hit. Either way, set the time_forwardable to a small
 +                      // constant as enough time has likely passed that we should simply handle the forwards
 +                      // now, or at least after the user gets a chance to reconnect to our peers.
 +                      pending_events_read.push(events::Event::PendingHTLCsForwardable {
 +                              time_forwardable: Duration::from_secs(2),
 +                      });
 +              }
  
                let background_event_count: u64 = Readable::read(reader)?;
                let mut pending_background_events_read: Vec<BackgroundEvent> = Vec::with_capacity(cmp::min(background_event_count as usize, MAX_ALLOC_SIZE/mem::size_of::<BackgroundEvent>()));
                }
  
                let pending_outbound_payments_count_compat: u64 = Readable::read(reader)?;
-               let mut pending_outbound_payments_compat: HashMap<MppId, HashSet<[u8; 32]>> =
+               let mut pending_outbound_payments_compat: HashMap<PaymentId, PendingOutboundPayment> =
                        HashMap::with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32));
                for _ in 0..pending_outbound_payments_count_compat {
                        let session_priv = Readable::read(reader)?;
-                       if pending_outbound_payments_compat.insert(MppId(session_priv), [session_priv].iter().cloned().collect()).is_some() {
+                       let payment = PendingOutboundPayment::Legacy {
+                               session_privs: [session_priv].iter().cloned().collect()
+                       };
+                       if pending_outbound_payments_compat.insert(PaymentId(session_priv), payment).is_some() {
                                return Err(DecodeError::InvalidValue)
                        };
                }
  
+               // pending_outbound_payments_no_retry is for compatibility with 0.0.101 clients.
+               let mut pending_outbound_payments_no_retry: Option<HashMap<PaymentId, HashSet<[u8; 32]>>> = None;
                let mut pending_outbound_payments = None;
                read_tlv_fields!(reader, {
-                       (1, pending_outbound_payments, option),
+                       (1, pending_outbound_payments_no_retry, option),
+                       (3, pending_outbound_payments, option),
                });
-               if pending_outbound_payments.is_none() {
+               if pending_outbound_payments.is_none() && pending_outbound_payments_no_retry.is_none() {
                        pending_outbound_payments = Some(pending_outbound_payments_compat);
+               } else if pending_outbound_payments.is_none() {
+                       let mut outbounds = HashMap::new();
+                       for (id, session_privs) in pending_outbound_payments_no_retry.unwrap().drain() {
+                               outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs });
+                       }
+                       pending_outbound_payments = Some(outbounds);
                }
  
                let mut secp_ctx = Secp256k1::new();
@@@ -5615,7 -5761,7 +5780,7 @@@ mod tests 
        use bitcoin::hashes::sha256::Hash as Sha256;
        use core::time::Duration;
        use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-       use ln::channelmanager::{MppId, PaymentSendFailure};
+       use ln::channelmanager::{PaymentId, PaymentSendFailure};
        use ln::features::{InitFeatures, InvoiceFeatures};
        use ln::functional_test_utils::*;
        use ln::msgs;
                let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
                let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph, &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger).unwrap();
                let (payment_preimage, our_payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[1]);
-               let mpp_id = MppId([42; 32]);
+               let payment_id = PaymentId([42; 32]);
                // Use the utility function send_payment_along_path to send the payment with MPP data which
                // indicates there are more HTLCs coming.
                let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
-               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, mpp_id, &None).unwrap();
+               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
                expect_payment_failed!(nodes[0], our_payment_hash, true);
  
                // Send the second half of the original MPP payment.
-               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, mpp_id, &None).unwrap();
+               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
                // To start (2), send a keysend payment but don't claim it.
                let payment_preimage = PaymentPreimage([42; 32]);
                let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger).unwrap();
-               let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
+               let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).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 test_preimage = PaymentPreimage([42; 32]);
                let mismatch_payment_hash = PaymentHash([43; 32]);
-               let _ = nodes[0].node.send_payment_internal(&route, mismatch_payment_hash, &None, Some(test_preimage)).unwrap();
+               let _ = nodes[0].node.send_payment_internal(&route, mismatch_payment_hash, &None, Some(test_preimage), None, None).unwrap();
                check_added_monitors!(nodes[0], 1);
  
                let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
                let test_preimage = PaymentPreimage([42; 32]);
                let test_secret = PaymentSecret([43; 32]);
                let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner());
-               let _ = nodes[0].node.send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage)).unwrap();
+               let _ = nodes[0].node.send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage), None, None).unwrap();
                check_added_monitors!(nodes[0], 1);
  
                let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
index 4b0016199de1a453cdd1caf88a7a8c56b5367443,11154405a5f6fbecd29031c930f2e2114f99a528..be6de19463caee51f6552e5cddc7161a38272fdb
@@@ -19,7 -19,7 +19,7 @@@ use chain::transaction::OutPoint
  use chain::keysinterface::BaseSign;
  use ln::{PaymentPreimage, PaymentSecret, PaymentHash};
  use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
- use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, MppId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
+ use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
  use ln::channel::{Channel, ChannelError};
  use ln::{chan_utils, onion_utils};
  use ln::chan_utils::HTLC_SUCCESS_TX_WEIGHT;
@@@ -1497,7 -1497,7 +1497,7 @@@ fn test_chan_reserve_dust_inbound_htlcs
        push_amt -= Channel::<EnforcingSigner>::get_holder_selected_channel_reserve_satoshis(100_000) * 1000;
        create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt, InitFeatures::known(), InitFeatures::known());
  
 -      let dust_amt = crate::ln::channel::MIN_DUST_LIMIT_SATOSHIS * 1000
 +      let dust_amt = crate::ln::channel::MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000
                + feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 * 1000 - 1;
        // In the previous code, routing this dust payment would cause nodes[0] to perceive a channel
        // reserve violation even though it's a dust HTLC and therefore shouldn't count towards the
@@@ -3957,8 -3957,8 +3957,8 @@@ fn do_test_htlc_timeout(send_partial_mp
                // Use the utility function send_payment_along_path to send the payment with MPP data which
                // indicates there are more HTLCs coming.
                let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
-               let mpp_id = MppId([42; 32]);
-               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, mpp_id, &None).unwrap();
+               let payment_id = PaymentId([42; 32]);
+               nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, payment_id, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@@ -4183,6 -4183,204 +4183,204 @@@ fn mpp_failure() 
        fail_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash);
  }
  
+ #[test]
+ fn mpp_retry() {
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+       let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+       let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+       let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+       let chan_4_id = create_announced_chan_between_nodes(&nodes, 3, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id;
+       let logger = test_utils::TestLogger::new();
+       // Rebalance
+       send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000);
+       let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[3]);
+       let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+       let mut route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph, &nodes[3].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &[], 1_000_000, TEST_FINAL_CLTV, &logger).unwrap();
+       let path = route.paths[0].clone();
+       route.paths.push(path);
+       route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
+       route.paths[0][0].short_channel_id = chan_1_id;
+       route.paths[0][1].short_channel_id = chan_3_id;
+       route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
+       route.paths[1][0].short_channel_id = chan_2_id;
+       route.paths[1][1].short_channel_id = chan_4_id;
+       // Initiate the MPP payment.
+       let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
+       check_added_monitors!(nodes[0], 2); // one monitor per path
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 2);
+       // Pass half of the payment along the success path.
+       let success_path_msgs = events.remove(0);
+       pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), success_path_msgs, false, None);
+       // Add the HTLC along the first hop.
+       let fail_path_msgs_1 = events.remove(0);
+       let (update_add, commitment_signed) = match fail_path_msgs_1 {
+               MessageSendEvent::UpdateHTLCs { node_id: _, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
+                       assert_eq!(update_add_htlcs.len(), 1);
+                       assert!(update_fail_htlcs.is_empty());
+                       assert!(update_fulfill_htlcs.is_empty());
+                       assert!(update_fail_malformed_htlcs.is_empty());
+                       assert!(update_fee.is_none());
+                       (update_add_htlcs[0].clone(), commitment_signed.clone())
+               },
+               _ => panic!("Unexpected event"),
+       };
+       nodes[2].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &update_add);
+       commitment_signed_dance!(nodes[2], nodes[0], commitment_signed, false);
+       // Attempt to forward the payment and complete the 2nd path's failure.
+       expect_pending_htlcs_forwardable!(&nodes[2]);
+       expect_pending_htlcs_forwardable!(&nodes[2]);
+       let htlc_updates = get_htlc_update_msgs!(nodes[2], nodes[0].node.get_our_node_id());
+       assert!(htlc_updates.update_add_htlcs.is_empty());
+       assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
+       assert!(htlc_updates.update_fulfill_htlcs.is_empty());
+       assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
+       check_added_monitors!(nodes[2], 1);
+       nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
+       commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false);
+       expect_payment_failed!(nodes[0], payment_hash, false);
+       // Rebalance the channel so the second half of the payment can succeed.
+       send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000);
+       // Make sure it errors as expected given a too-large amount.
+       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, payment_id) {
+               assert!(err.contains("over total_payment_amt_msat"));
+       } else { panic!("Unexpected error"); }
+       // Make sure it errors as expected given the wrong payment_id.
+       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, PaymentId([0; 32])) {
+               assert!(err.contains("not found"));
+       } else { panic!("Unexpected error"); }
+       // Retry the second half of the payment and make sure it succeeds.
+       let mut path = route.clone();
+       path.paths.remove(0);
+       nodes[0].node.retry_payment(&path, payment_id).unwrap();
+       check_added_monitors!(nodes[0], 1);
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
+       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+ }
+ #[test]
+ fn retry_single_path_payment() {
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+       let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       let _chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, InitFeatures::known(), InitFeatures::known());
+       // Rebalance to find a route
+       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
+       let logger = test_utils::TestLogger::new();
+       let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
+       let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+       let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph, &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger).unwrap();
+       // Rebalance so that the first hop fails.
+       send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000);
+       // Make sure the payment fails on the first hop.
+       let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).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 mut payment_event = SendEvent::from_event(events.pop().unwrap());
+       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!(&nodes[1]);
+       let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       assert!(htlc_updates.update_add_htlcs.is_empty());
+       assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
+       assert!(htlc_updates.update_fulfill_htlcs.is_empty());
+       assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
+       check_added_monitors!(nodes[1], 1);
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
+       commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false);
+       expect_payment_failed!(nodes[0], payment_hash, false);
+       // Rebalance the channel so the retry succeeds.
+       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
+       // Mine two blocks (we expire retries after 3, so this will check that we don't expire early)
+       connect_blocks(&nodes[0], 2);
+       // Retry the payment and make sure it succeeds.
+       nodes[0].node.retry_payment(&route, payment_id).unwrap();
+       check_added_monitors!(nodes[0], 1);
+       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 100_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
+       claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ }
+ #[test]
+ fn retry_expired_payment() {
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+       let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       let _chan_0 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       let _chan_1 = create_announced_chan_between_nodes(&nodes, 2, 1, InitFeatures::known(), InitFeatures::known());
+       // Rebalance to find a route
+       send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000);
+       let logger = test_utils::TestLogger::new();
+       let (_payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[2]);
+       let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+       let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph, &nodes[2].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger).unwrap();
+       // Rebalance so that the first hop fails.
+       send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000);
+       // Make sure the payment fails on the first hop.
+       let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).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 mut payment_event = SendEvent::from_event(events.pop().unwrap());
+       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!(&nodes[1]);
+       let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+       assert!(htlc_updates.update_add_htlcs.is_empty());
+       assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
+       assert!(htlc_updates.update_fulfill_htlcs.is_empty());
+       assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
+       check_added_monitors!(nodes[1], 1);
+       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]);
+       commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false);
+       expect_payment_failed!(nodes[0], payment_hash, false);
+       // Mine blocks so the payment will have expired.
+       connect_blocks(&nodes[0], 3);
+       // Retry the payment and make sure it errors as expected.
+       if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, payment_id) {
+               assert!(err.contains("not found"));
+       } else {
+               panic!("Unexpected error");
+       }
+ }
  #[test]
  fn test_dup_htlc_onchain_fails_on_reload() {
        // When a Channel is closed, any outbound HTLCs which were relayed through it are simply
@@@ -5985,7 -6183,7 +6183,7 @@@ fn bolt2_open_channel_sane_dust_limit(
        let push_msat=10001;
        nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).unwrap();
        let mut node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
 -      node0_to_1_send_open_channel.dust_limit_satoshis = 661;
 +      node0_to_1_send_open_channel.dust_limit_satoshis = 547;
        node0_to_1_send_open_channel.channel_reserve_satoshis = 100001;
  
        nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &node0_to_1_send_open_channel);
                },
                _ => panic!("Unexpected event"),
        };
 -      assert_eq!(err_msg.data, "dust_limit_satoshis (661) is greater than the implementation limit (660)");
 +      assert_eq!(err_msg.data, "dust_limit_satoshis (547) is greater than the implementation limit (546)");
  }
  
  // Test that if we fail to send an HTLC that is being freed from the holding cell, and the HTLC
@@@ -9208,125 -9406,6 +9406,125 @@@ fn test_tx_confirmed_skipping_blocks_im
        do_test_tx_confirmed_skipping_blocks_immediate_broadcast(true);
  }
  
 +#[test]
 +fn test_forwardable_regen() {
 +      // Tests that if we reload a ChannelManager while forwards are pending we will regenerate the
 +      // PendingHTLCsForwardable event automatically, ensuring we don't forget to forward/receive
 +      // HTLCs.
 +      // We test it for both payment receipt and payment forwarding.
 +
 +      let chanmon_cfgs = create_chanmon_cfgs(3);
 +      let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
 +      let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
 +      let persister: test_utils::TestPersister;
 +      let new_chain_monitor: test_utils::TestChainMonitor;
 +      let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
 +      let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 +      create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
 +      create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
 +
 +      // First send a payment to nodes[1]
 +      let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
 +      nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).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 payment_event = SendEvent::from_event(events.pop().unwrap());
 +      nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
 +      commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
 +
 +      expect_pending_htlcs_forwardable_ignore!(nodes[1]);
 +
 +      // Next send a payment which is forwarded by nodes[1]
 +      let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], 200_000);
 +      nodes[0].node.send_payment(&route_2, payment_hash_2, &Some(payment_secret_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 payment_event = SendEvent::from_event(events.pop().unwrap());
 +      nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
 +      commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
 +
 +      // There is already a PendingHTLCsForwardable event "pending" so another one will not be
 +      // generated
 +      assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
 +
 +      // Now restart nodes[1] and make sure it regenerates a single PendingHTLCsForwardable
 +      nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
 +      nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
 +
 +      let nodes_1_serialized = nodes[1].node.encode();
 +      let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new());
 +      let mut chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new());
 +      {
 +              let monitors = nodes[1].chain_monitor.chain_monitor.monitors.read().unwrap();
 +              let mut monitor_iter = monitors.iter();
 +              monitor_iter.next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap();
 +              monitor_iter.next().unwrap().1.write(&mut chan_1_monitor_serialized).unwrap();
 +      }
 +
 +      persister = test_utils::TestPersister::new();
 +      let keys_manager = &chanmon_cfgs[1].keys_manager;
 +      new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[1].chain_source), nodes[1].tx_broadcaster.clone(), nodes[1].logger, node_cfgs[1].fee_estimator, &persister, keys_manager);
 +      nodes[1].chain_monitor = &new_chain_monitor;
 +
 +      let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
 +      let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(
 +              &mut chan_0_monitor_read, keys_manager).unwrap();
 +      assert!(chan_0_monitor_read.is_empty());
 +      let mut chan_1_monitor_read = &chan_1_monitor_serialized.0[..];
 +      let (_, mut chan_1_monitor) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(
 +              &mut chan_1_monitor_read, keys_manager).unwrap();
 +      assert!(chan_1_monitor_read.is_empty());
 +
 +      let mut nodes_1_read = &nodes_1_serialized[..];
 +      let (_, nodes_1_deserialized_tmp) = {
 +              let mut channel_monitors = HashMap::new();
 +              channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
 +              channel_monitors.insert(chan_1_monitor.get_funding_txo().0, &mut chan_1_monitor);
 +              <(BlockHash, ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_1_read, ChannelManagerReadArgs {
 +                      default_config: UserConfig::default(),
 +                      keys_manager,
 +                      fee_estimator: node_cfgs[1].fee_estimator,
 +                      chain_monitor: nodes[1].chain_monitor,
 +                      tx_broadcaster: nodes[1].tx_broadcaster.clone(),
 +                      logger: nodes[1].logger,
 +                      channel_monitors,
 +              }).unwrap()
 +      };
 +      nodes_1_deserialized = nodes_1_deserialized_tmp;
 +      assert!(nodes_1_read.is_empty());
 +
 +      assert!(nodes[1].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor).is_ok());
 +      assert!(nodes[1].chain_monitor.watch_channel(chan_1_monitor.get_funding_txo().0, chan_1_monitor).is_ok());
 +      nodes[1].node = &nodes_1_deserialized;
 +      check_added_monitors!(nodes[1], 2);
 +
 +      reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 +      // Note that nodes[1] and nodes[2] resend their funding_locked here since they haven't updated
 +      // the commitment state.
 +      reconnect_nodes(&nodes[1], &nodes[2], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 +
 +      assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 +
 +      expect_pending_htlcs_forwardable!(nodes[1]);
 +      expect_payment_received!(nodes[1], payment_hash, payment_secret, 100_000);
 +      check_added_monitors!(nodes[1], 1);
 +
 +      let mut events = nodes[1].node.get_and_clear_pending_msg_events();
 +      assert_eq!(events.len(), 1);
 +      let payment_event = SendEvent::from_event(events.pop().unwrap());
 +      nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event.msgs[0]);
 +      commitment_signed_dance!(nodes[2], nodes[1], payment_event.commitment_msg, false);
 +      expect_pending_htlcs_forwardable!(nodes[2]);
 +      expect_payment_received!(nodes[2], payment_hash_2, payment_secret_2, 200_000);
 +
 +      claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
 +      claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2);
 +}
 +
  #[test]
  fn test_keysend_payments_to_public_node() {
        let chanmon_cfgs = create_chanmon_cfgs(2);
                          nodes[0].logger).unwrap();
  
        let test_preimage = PaymentPreimage([42; 32]);
-       let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
+       let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
@@@ -9373,7 -9452,7 +9571,7 @@@ fn test_keysend_payments_to_private_nod
                                  nodes[0].logger).unwrap();
  
        let test_preimage = PaymentPreimage([42; 32]);
-       let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
+       let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events.len(), 1);
        pass_along_path(&nodes[0], &path, 10000, payment_hash, None, event, true, Some(test_preimage));
        claim_payment(&nodes[0], &path, test_preimage);
  }
 -
 -fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, at_forward: bool, on_holder_tx: bool) {
 -      // Test that we properly reject dust HTLC violating our `max_dust_htlc_exposure_msat` policy.
 -      //
 -      // At HTLC forward (`send_payment()`), if the sum of the trimmed-to-dust HTLC inbound and
 -      // trimmed-to-dust HTLC outbound balance and this new payment as included on next counterparty
 -      // commitment are above our `max_dust_htlc_exposure_msat`, we'll reject the update.
 -      // At HTLC reception (`update_add_htlc()`), if the sum of the trimmed-to-dust HTLC inbound
 -      // and trimmed-to-dust HTLC outbound balance and this new received HTLC as included on next
 -      // counterparty commitment are above our `max_dust_htlc_exposure_msat`, we'll fail the update.
 -      // Note, we return a `temporary_channel_failure` (0x1000 | 7), as the channel might be
 -      // available again for HTLC processing once the dust bandwidth has cleared up.
 -
 -      let chanmon_cfgs = create_chanmon_cfgs(2);
 -      let mut config = test_default_channel_config();
 -      config.channel_options.max_dust_htlc_exposure_msat = 5_000_000; // default setting value
 -      let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
 -      let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(config)]);
 -      let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
 -
 -      nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
 -      let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
 -      open_channel.max_htlc_value_in_flight_msat = 50_000_000;
 -      open_channel.max_accepted_htlcs = 60;
 -      nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
 -      let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
 -      if on_holder_tx {
 -              accept_channel.dust_limit_satoshis = 660;
 -      }
 -      nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
 -
 -      let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], 1_000_000, 42);
 -
 -      if on_holder_tx {
 -              if let Some(mut chan) = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&temporary_channel_id) {
 -                      chan.holder_dust_limit_satoshis = 660;
 -              }
 -      }
 -
 -      nodes[0].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
 -      nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()));
 -      check_added_monitors!(nodes[1], 1);
 -
 -      nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()));
 -      check_added_monitors!(nodes[0], 1);
 -
 -      let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
 -      let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked);
 -      update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
 -
 -      if on_holder_tx {
 -              if dust_outbound_balance {
 -                      for i in 0..2 {
 -                              let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 2_300_000);
 -                              if let Err(_) = nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)) { panic!("Unexpected event at dust HTLC {}", i); }
 -                      }
 -              } else {
 -                      for _ in 0..2 {
 -                              route_payment(&nodes[0], &[&nodes[1]], 2_300_000);
 -                      }
 -              }
 -      } else {
 -              if dust_outbound_balance {
 -                      for i in 0..25 {
 -                              let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 200_000); // + 177_000 msat of HTLC-success tx at 253 sats/kWU
 -                              if let Err(_) = nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)) { panic!("Unexpected event at dust HTLC {}", i); }
 -                      }
 -              } else {
 -                      for _ in 0..25 {
 -                              route_payment(&nodes[0], &[&nodes[1]], 200_000); // + 167_000 msat of HTLC-timeout tx at 253 sats/kWU
 -                      }
 -              }
 -      }
 -
 -      if at_forward {
 -              let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { 2_300_000 } else { 200_000 });
 -              let mut config = UserConfig::default();
 -              if on_holder_tx {
 -                      unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable { ref err }, assert_eq!(err, &format!("Cannot send value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", 6_900_000, config.channel_options.max_dust_htlc_exposure_msat)));
 -              } else {
 -                      unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash, &Some(payment_secret)), true, APIError::ChannelUnavailable { ref err }, assert_eq!(err, &format!("Cannot send value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", 5_200_000, config.channel_options.max_dust_htlc_exposure_msat)));
 -              }
 -      } else {
 -              let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1 ], if on_holder_tx { 2_300_000 } else { 200_000 });
 -              nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).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 payment_event = SendEvent::from_event(events.remove(0));
 -              nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
 -              if on_holder_tx {
 -                      nodes[1].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", 6_900_000, config.channel_options.max_dust_htlc_exposure_msat), 1);
 -              } else {
 -                      nodes[1].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", 5_200_000, config.channel_options.max_dust_htlc_exposure_msat), 1);
 -              }
 -      }
 -
 -      let _ = nodes[1].node.get_and_clear_pending_msg_events();
 -      let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
 -      added_monitors.clear();
 -}
 -
 -#[test]
 -fn test_max_dust_htlc_exposure() {
 -      do_test_max_dust_htlc_exposure(true, true, true);
 -      do_test_max_dust_htlc_exposure(false, true, true);
 -      do_test_max_dust_htlc_exposure(false, false, true);
 -      do_test_max_dust_htlc_exposure(false, false, false);
 -      do_test_max_dust_htlc_exposure(true, true, false);
 -      do_test_max_dust_htlc_exposure(true, false, false);
 -      do_test_max_dust_htlc_exposure(true, false, true);
 -      do_test_max_dust_htlc_exposure(false, true, false);
 -}