Merge pull request #2795 from TheBlueMatt/2023-11-robuster-chan-to-peer
authorWilmer Paulino <9447167+wpaulino@users.noreply.github.com>
Fri, 15 Dec 2023 23:36:52 +0000 (15:36 -0800)
committerGitHub <noreply@github.com>
Fri, 15 Dec 2023 23:36:52 +0000 (15:36 -0800)
 Move channel -> peer tracking to OutPoints from Channel IDs

1  2 
lightning/src/chain/channelmonitor.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs

index 244384faa224f68bafd5df1b02cda326ec722493,9961b822ecb6089978dd45e8a7b622f18b424b4e..bcc324a5582af9d0f6c399034d7cf4e0b2327161
@@@ -71,6 -71,15 +71,15 @@@ use crate::sync::{Mutex, LockTestExt}
  #[must_use]
  pub struct ChannelMonitorUpdate {
        pub(crate) updates: Vec<ChannelMonitorUpdateStep>,
+       /// Historically, [`ChannelMonitor`]s didn't know their counterparty node id. However,
+       /// `ChannelManager` really wants to know it so that it can easily look up the corresponding
+       /// channel. For now, this results in a temporary map in `ChannelManager` to look up channels
+       /// by only the funding outpoint.
+       ///
+       /// To eventually remove that, we repeat the counterparty node id here so that we can upgrade
+       /// `ChannelMonitor`s to become aware of the counterparty node id if they were generated prior
+       /// to when it was stored directly in them.
+       pub(crate) counterparty_node_id: Option<PublicKey>,
        /// The sequence number of this update. Updates *must* be replayed in-order according to this
        /// sequence number (and updates may panic if they are not). The update_id values are strictly
        /// increasing and increase by one for each new update, with two exceptions specified below.
@@@ -107,7 -116,9 +116,9 @@@ impl Writeable for ChannelMonitorUpdat
                for update_step in self.updates.iter() {
                        update_step.write(w)?;
                }
-               write_tlv_fields!(w, {});
+               write_tlv_fields!(w, {
+                       (1, self.counterparty_node_id, option),
+               });
                Ok(())
        }
  }
@@@ -122,8 -133,11 +133,11 @@@ impl Readable for ChannelMonitorUpdate 
                                updates.push(upd);
                        }
                }
-               read_tlv_fields!(r, {});
-               Ok(Self { update_id, updates })
+               let mut counterparty_node_id = None;
+               read_tlv_fields!(r, {
+                       (1, counterparty_node_id, option),
+               });
+               Ok(Self { update_id, counterparty_node_id, updates })
        }
  }
  
@@@ -2666,59 -2680,18 +2680,59 @@@ impl<Signer: WriteableEcdsaChannelSigne
                }
        }
  
 -      fn broadcast_latest_holder_commitment_txn<B: Deref, L: Deref>(&mut self, broadcaster: &B, logger: &WithChannelMonitor<L>)
 -              where B::Target: BroadcasterInterface,
 -                      L::Target: Logger,
 -      {
 -              let commit_txs = self.get_latest_holder_commitment_txn(logger);
 -              let mut txs = vec![];
 -              for tx in commit_txs.iter() {
 -                      log_info!(logger, "Broadcasting local {}", log_tx!(tx));
 -                      txs.push(tx);
 -              }
 -              broadcaster.broadcast_transactions(&txs);
 +      fn generate_claimable_outpoints_and_watch_outputs(&mut self) -> (Vec<PackageTemplate>, Vec<TransactionOutputs>) {
 +              let funding_outp = HolderFundingOutput::build(
 +                      self.funding_redeemscript.clone(),
 +                      self.channel_value_satoshis,
 +                      self.onchain_tx_handler.channel_type_features().clone()
 +              );
 +              let commitment_package = PackageTemplate::build_package(
 +                      self.funding_info.0.txid.clone(), self.funding_info.0.index as u32,
 +                      PackageSolvingData::HolderFundingOutput(funding_outp),
 +                      self.best_block.height(), self.best_block.height()
 +              );
 +              let mut claimable_outpoints = vec![commitment_package];
                self.pending_monitor_events.push(MonitorEvent::HolderForceClosed(self.funding_info.0));
 +              // Although we aren't signing the transaction directly here, the transaction will be signed
 +              // in the claim that is queued to OnchainTxHandler. We set holder_tx_signed here to reject
 +              // new channel updates.
 +              self.holder_tx_signed = true;
 +              let mut watch_outputs = Vec::new();
 +              // We can't broadcast our HTLC transactions while the commitment transaction is
 +              // unconfirmed. We'll delay doing so until we detect the confirmed commitment in
 +              // `transactions_confirmed`.
 +              if !self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
 +                      // Because we're broadcasting a commitment transaction, we should construct the package
 +                      // assuming it gets confirmed in the next block. Sadly, we have code which considers
 +                      // "not yet confirmed" things as discardable, so we cannot do that here.
 +                      let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(
 +                              &self.current_holder_commitment_tx, self.best_block.height()
 +                      );
 +                      let unsigned_commitment_tx = self.onchain_tx_handler.get_unsigned_holder_commitment_tx();
 +                      let new_outputs = self.get_broadcasted_holder_watch_outputs(
 +                              &self.current_holder_commitment_tx, &unsigned_commitment_tx
 +                      );
 +                      if !new_outputs.is_empty() {
 +                              watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
 +                      }
 +                      claimable_outpoints.append(&mut new_outpoints);
 +              }
 +              (claimable_outpoints, watch_outputs)
 +      }
 +
 +      pub(crate) fn queue_latest_holder_commitment_txn_for_broadcast<B: Deref, F: Deref, L: Deref>(
 +              &mut self, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &WithChannelMonitor<L>
 +      )
 +      where
 +              B::Target: BroadcasterInterface,
 +              F::Target: FeeEstimator,
 +              L::Target: Logger,
 +      {
 +              let (claimable_outpoints, _) = self.generate_claimable_outpoints_and_watch_outputs();
 +              self.onchain_tx_handler.update_claims_view_from_requests(
 +                      claimable_outpoints, self.best_block.height(), self.best_block.height(), broadcaster,
 +                      fee_estimator, logger
 +              );
        }
  
        fn update_monitor<B: Deref, F: Deref, L: Deref>(
                        log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).",
                                log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len());
                }
+               if updates.counterparty_node_id.is_some() {
+                       if self.counterparty_node_id.is_none() {
+                               self.counterparty_node_id = updates.counterparty_node_id;
+                       } else {
+                               debug_assert_eq!(self.counterparty_node_id, updates.counterparty_node_id);
+                       }
+               }
                // ChannelMonitor updates may be applied after force close if we receive a preimage for a
                // broadcasted commitment transaction HTLC output that we'd like to claim on-chain. If this
                // is the case, we no longer have guaranteed access to the monitor's update ID, so we use a
                                                        log_trace!(logger, "Avoiding commitment broadcast, already detected confirmed spend onchain");
                                                        continue;
                                                }
 -                                              self.broadcast_latest_holder_commitment_txn(broadcaster, logger);
 -                                              // If the channel supports anchor outputs, we'll need to emit an external
 -                                              // event to be consumed such that a child transaction is broadcast with a
 -                                              // high enough feerate for the parent commitment transaction to confirm.
 -                                              if self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
 -                                                      let funding_output = HolderFundingOutput::build(
 -                                                              self.funding_redeemscript.clone(), self.channel_value_satoshis,
 -                                                              self.onchain_tx_handler.channel_type_features().clone(),
 -                                                      );
 -                                                      let best_block_height = self.best_block.height();
 -                                                      let commitment_package = PackageTemplate::build_package(
 -                                                              self.funding_info.0.txid.clone(), self.funding_info.0.index as u32,
 -                                                              PackageSolvingData::HolderFundingOutput(funding_output),
 -                                                              best_block_height, best_block_height
 -                                                      );
 -                                                      self.onchain_tx_handler.update_claims_view_from_requests(
 -                                                              vec![commitment_package], best_block_height, best_block_height,
 -                                                              broadcaster, &bounded_fee_estimator, logger,
 -                                                      );
 -                                              }
 +                                              self.queue_latest_holder_commitment_txn_for_broadcast(broadcaster, &bounded_fee_estimator, logger);
                                        } else if !self.holder_tx_signed {
                                                log_error!(logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast");
                                                log_error!(logger, "    in channel monitor for channel {}!", &self.funding_info.0.to_channel_id());
                }
        }
  
 +      /// Cancels any existing pending claims for a commitment that previously confirmed and has now
 +      /// been replaced by another.
 +      pub fn cancel_prev_commitment_claims<L: Deref>(
 +              &mut self, logger: &L, confirmed_commitment_txid: &Txid
 +      ) where L::Target: Logger {
 +              for (counterparty_commitment_txid, _) in &self.counterparty_commitment_txn_on_chain {
 +                      // Cancel any pending claims for counterparty commitments we've seen confirm.
 +                      if counterparty_commitment_txid == confirmed_commitment_txid {
 +                              continue;
 +                      }
 +                      for (htlc, _) in self.counterparty_claimable_outpoints.get(counterparty_commitment_txid).unwrap_or(&vec![]) {
 +                              log_trace!(logger, "Canceling claims for previously confirmed counterparty commitment {}",
 +                                      counterparty_commitment_txid);
 +                              let mut outpoint = BitcoinOutPoint { txid: *counterparty_commitment_txid, vout: 0 };
 +                              if let Some(vout) = htlc.transaction_output_index {
 +                                      outpoint.vout = vout;
 +                                      self.onchain_tx_handler.abandon_claim(&outpoint);
 +                              }
 +                      }
 +              }
 +              if self.holder_tx_signed {
 +                      // If we've signed, we may have broadcast either commitment (prev or current), and
 +                      // attempted to claim from it immediately without waiting for a confirmation.
 +                      if self.current_holder_commitment_tx.txid != *confirmed_commitment_txid {
 +                              log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}",
 +                                      self.current_holder_commitment_tx.txid);
 +                              let mut outpoint = BitcoinOutPoint { txid: self.current_holder_commitment_tx.txid, vout: 0 };
 +                              for (htlc, _, _) in &self.current_holder_commitment_tx.htlc_outputs {
 +                                      if let Some(vout) = htlc.transaction_output_index {
 +                                              outpoint.vout = vout;
 +                                              self.onchain_tx_handler.abandon_claim(&outpoint);
 +                                      }
 +                              }
 +                      }
 +                      if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx {
 +                              if prev_holder_commitment_tx.txid != *confirmed_commitment_txid {
 +                                      log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}",
 +                                              prev_holder_commitment_tx.txid);
 +                                      let mut outpoint = BitcoinOutPoint { txid: prev_holder_commitment_tx.txid, vout: 0 };
 +                                      for (htlc, _, _) in &prev_holder_commitment_tx.htlc_outputs {
 +                                              if let Some(vout) = htlc.transaction_output_index {
 +                                                      outpoint.vout = vout;
 +                                                      self.onchain_tx_handler.abandon_claim(&outpoint);
 +                                              }
 +                                      }
 +                              }
 +                      }
 +              } else {
 +                      // No previous claim.
 +              }
 +      }
 +
        fn get_latest_holder_commitment_txn<L: Deref>(
                &mut self, logger: &WithChannelMonitor<L>,
        ) -> Vec<Transaction> where L::Target: Logger {
                                                        commitment_tx_to_counterparty_output,
                                                },
                                        });
 +                                      // Now that we've detected a confirmed commitment transaction, attempt to cancel
 +                                      // pending claims for any commitments that were previously confirmed such that
 +                                      // we don't continue claiming inputs that no longer exist.
 +                                      self.cancel_prev_commitment_claims(&logger, &txid);
                                }
                        }
                        if tx.input.len() >= 1 {
  
                let should_broadcast = self.should_broadcast_holder_commitment_txn(logger);
                if should_broadcast {
 -                      let funding_outp = HolderFundingOutput::build(self.funding_redeemscript.clone(), self.channel_value_satoshis, self.onchain_tx_handler.channel_type_features().clone());
 -                      let commitment_package = PackageTemplate::build_package(self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), self.best_block.height(), self.best_block.height());
 -                      claimable_outpoints.push(commitment_package);
 -                      self.pending_monitor_events.push(MonitorEvent::HolderForceClosed(self.funding_info.0));
 -                      // Although we aren't signing the transaction directly here, the transaction will be signed
 -                      // in the claim that is queued to OnchainTxHandler. We set holder_tx_signed here to reject
 -                      // new channel updates.
 -                      self.holder_tx_signed = true;
 -                      // We can't broadcast our HTLC transactions while the commitment transaction is
 -                      // unconfirmed. We'll delay doing so until we detect the confirmed commitment in
 -                      // `transactions_confirmed`.
 -                      if !self.onchain_tx_handler.channel_type_features().supports_anchors_zero_fee_htlc_tx() {
 -                              // Because we're broadcasting a commitment transaction, we should construct the package
 -                              // assuming it gets confirmed in the next block. Sadly, we have code which considers
 -                              // "not yet confirmed" things as discardable, so we cannot do that here.
 -                              let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height());
 -                              let unsigned_commitment_tx = self.onchain_tx_handler.get_unsigned_holder_commitment_tx();
 -                              let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &unsigned_commitment_tx);
 -                              if !new_outputs.is_empty() {
 -                                      watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
 -                              }
 -                              claimable_outpoints.append(&mut new_outpoints);
 -                      }
 +                      let (mut new_outpoints, mut new_outputs) = self.generate_claimable_outpoints_and_watch_outputs();
 +                      claimable_outpoints.append(&mut new_outpoints);
 +                      watch_outputs.append(&mut new_outputs);
                }
  
                // Find which on-chain events have reached their confirmation threshold.
index 050585ef2673f81a6f9caf8484de05d2fa2bf258,28842b1bf79d2b0f21d2367291338c898c76226f..588995656ec4790cedd6bcb5ac7edc6bc190ae23
@@@ -259,11 -259,6 +259,11 @@@ enum HTLCUpdateAwaitingACK 
                htlc_id: u64,
                err_packet: msgs::OnionErrorPacket,
        },
 +      FailMalformedHTLC {
 +              htlc_id: u64,
 +              failure_code: u16,
 +              sha256_of_onion: [u8; 32],
 +      },
  }
  
  macro_rules! define_state_flags {
@@@ -2394,6 -2389,7 +2394,7 @@@ impl<SP: Deref> ChannelContext<SP> wher
                                self.latest_monitor_update_id = CLOSED_CHANNEL_UPDATE_ID;
                                Some((self.get_counterparty_node_id(), funding_txo, ChannelMonitorUpdate {
                                        update_id: self.latest_monitor_update_id,
+                                       counterparty_node_id: Some(self.counterparty_node_id),
                                        updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast }],
                                }))
                        } else { None }
                                        .ok();
  
                                if funding_signed.is_none() {
 -                                      log_trace!(logger, "Counterparty commitment signature not available for funding_signed message; setting signer_pending_funding");
 -                                      self.signer_pending_funding = true;
 +                                      #[cfg(not(async_signing))] {
 +                                              panic!("Failed to get signature for funding_signed");
 +                                      }
 +                                      #[cfg(async_signing)] {
 +                                              log_trace!(logger, "Counterparty commitment signature not available for funding_signed message; setting signer_pending_funding");
 +                                              self.signer_pending_funding = true;
 +                                      }
                                } else if self.signer_pending_funding {
                                        log_trace!(logger, "Counterparty commitment signature available for funding_signed message; clearing signer_pending_funding");
                                        self.signer_pending_funding = false;
@@@ -2528,64 -2519,6 +2529,64 @@@ struct CommitmentTxInfoCached 
        feerate: u32,
  }
  
 +/// Contents of a wire message that fails an HTLC backwards. Useful for [`Channel::fail_htlc`] to
 +/// fail with either [`msgs::UpdateFailMalformedHTLC`] or [`msgs::UpdateFailHTLC`] as needed.
 +trait FailHTLCContents {
 +      type Message: FailHTLCMessageName;
 +      fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message;
 +      fn to_inbound_htlc_state(self) -> InboundHTLCState;
 +      fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK;
 +}
 +impl FailHTLCContents for msgs::OnionErrorPacket {
 +      type Message = msgs::UpdateFailHTLC;
 +      fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message {
 +              msgs::UpdateFailHTLC { htlc_id, channel_id, reason: self }
 +      }
 +      fn to_inbound_htlc_state(self) -> InboundHTLCState {
 +              InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(self))
 +      }
 +      fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
 +              HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self }
 +      }
 +}
 +impl FailHTLCContents for (u16, [u8; 32]) {
 +      type Message = msgs::UpdateFailMalformedHTLC; // (failure_code, sha256_of_onion)
 +      fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message {
 +              msgs::UpdateFailMalformedHTLC {
 +                      htlc_id,
 +                      channel_id,
 +                      failure_code: self.0,
 +                      sha256_of_onion: self.1
 +              }
 +      }
 +      fn to_inbound_htlc_state(self) -> InboundHTLCState {
 +              InboundHTLCState::LocalRemoved(
 +                      InboundHTLCRemovalReason::FailMalformed((self.1, self.0))
 +              )
 +      }
 +      fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
 +              HTLCUpdateAwaitingACK::FailMalformedHTLC {
 +                      htlc_id,
 +                      failure_code: self.0,
 +                      sha256_of_onion: self.1
 +              }
 +      }
 +}
 +
 +trait FailHTLCMessageName {
 +      fn name() -> &'static str;
 +}
 +impl FailHTLCMessageName for msgs::UpdateFailHTLC {
 +      fn name() -> &'static str {
 +              "update_fail_htlc"
 +      }
 +}
 +impl FailHTLCMessageName for msgs::UpdateFailMalformedHTLC {
 +      fn name() -> &'static str {
 +              "update_fail_malformed_htlc"
 +      }
 +}
 +
  impl<SP: Deref> Channel<SP> where
        SP::Target: SignerProvider,
        <SP::Target as SignerProvider>::EcdsaSigner: WriteableEcdsaChannelSigner
                self.context.latest_monitor_update_id += 1;
                let monitor_update = ChannelMonitorUpdate {
                        update_id: self.context.latest_monitor_update_id,
+                       counterparty_node_id: Some(self.context.counterparty_node_id),
                        updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
                                payment_preimage: payment_preimage_arg.clone(),
                        }],
                                                        return UpdateFulfillFetch::DuplicateClaim {};
                                                }
                                        },
 -                                      &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
 +                                      &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } |
 +                                              &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } =>
 +                                      {
                                                if htlc_id_arg == htlc_id {
                                                        log_warn!(logger, "Have preimage and want to fulfill HTLC with pending failure against channel {}", &self.context.channel_id());
                                                        // TODO: We may actually be able to switch to a fulfill here, though its
                        .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
        }
  
 +      /// Used for failing back with [`msgs::UpdateFailMalformedHTLC`]. For now, this is used when we
 +      /// want to fail blinded HTLCs where we are not the intro node.
 +      ///
 +      /// See [`Self::queue_fail_htlc`] for more info.
 +      pub fn queue_fail_malformed_htlc<L: Deref>(
 +              &mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L
 +      ) -> Result<(), ChannelError> where L::Target: Logger {
 +              self.fail_htlc(htlc_id_arg, (failure_code, sha256_of_onion), true, logger)
 +                      .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
 +      }
 +
        /// We can only have one resolution per HTLC. In some cases around reconnect, we may fulfill
        /// an HTLC more than once or fulfill once and then attempt to fail after reconnect. We cannot,
        /// however, fail more than once as we wait for an upstream failure to be irrevocably committed
        /// If we do fail twice, we `debug_assert!(false)` and return `Ok(None)`. Thus, this will always
        /// return `Ok(_)` if preconditions are met. In any case, `Err`s will only be
        /// [`ChannelError::Ignore`].
 -      fn fail_htlc<L: Deref>(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket, mut force_holding_cell: bool, logger: &L)
 -      -> Result<Option<msgs::UpdateFailHTLC>, ChannelError> where L::Target: Logger {
 +      fn fail_htlc<L: Deref, E: FailHTLCContents + Clone>(
 +              &mut self, htlc_id_arg: u64, err_packet: E, mut force_holding_cell: bool,
 +              logger: &L
 +      ) -> Result<Option<E::Message>, ChannelError> where L::Target: Logger {
                if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
                        panic!("Was asked to fail an HTLC when channel was not in an operational state");
                }
                                                        return Ok(None);
                                                }
                                        },
 -                                      &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => {
 +                                      &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } |
 +                                              &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, .. } =>
 +                                      {
                                                if htlc_id_arg == htlc_id {
                                                        debug_assert!(false, "Tried to fail an HTLC that was already failed");
                                                        return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned()));
                                }
                        }
                        log_trace!(logger, "Placing failure for HTLC ID {} in holding cell in channel {}.", htlc_id_arg, &self.context.channel_id());
 -                      self.context.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::FailHTLC {
 -                              htlc_id: htlc_id_arg,
 -                              err_packet,
 -                      });
 +                      self.context.holding_cell_htlc_updates.push(err_packet.to_htlc_update_awaiting_ack(htlc_id_arg));
                        return Ok(None);
                }
  
 -              log_trace!(logger, "Failing HTLC ID {} back with a update_fail_htlc message in channel {}.", htlc_id_arg, &self.context.channel_id());
 +              log_trace!(logger, "Failing HTLC ID {} back with {} message in channel {}.", htlc_id_arg,
 +                      E::Message::name(), &self.context.channel_id());
                {
                        let htlc = &mut self.context.pending_inbound_htlcs[pending_idx];
 -                      htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(err_packet.clone()));
 +                      htlc.state = err_packet.clone().to_inbound_htlc_state();
                }
  
 -              Ok(Some(msgs::UpdateFailHTLC {
 -                      channel_id: self.context.channel_id(),
 -                      htlc_id: htlc_id_arg,
 -                      reason: err_packet
 -              }))
 +              Ok(Some(err_packet.to_message(htlc_id_arg, self.context.channel_id())))
        }
  
        // Message handlers:
                self.context.channel_state.clear_waiting_for_batch();
        }
  
+       /// Unsets the existing funding information.
+       ///
+       /// This must only be used if the channel has not yet completed funding and has not been used.
+       ///
+       /// Further, the channel must be immediately shut down after this with a call to
+       /// [`ChannelContext::force_shutdown`].
+       pub fn unset_funding_info(&mut self, temporary_channel_id: ChannelId) {
+               debug_assert!(matches!(
+                       self.context.channel_state, ChannelState::AwaitingChannelReady(_)
+               ));
+               self.context.channel_transaction_parameters.funding_outpoint = None;
+               self.context.channel_id = temporary_channel_id;
+       }
        /// Handles a channel_ready message from our peer. If we've already sent our channel_ready
        /// and the channel is now usable (and public), this may generate an announcement_signatures to
        /// reply with.
                self.context.latest_monitor_update_id += 1;
                let mut monitor_update = ChannelMonitorUpdate {
                        update_id: self.context.latest_monitor_update_id,
+                       counterparty_node_id: Some(self.context.counterparty_node_id),
                        updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
                                commitment_tx: holder_commitment_tx,
                                htlc_outputs: htlcs_and_sigs,
  
                        let mut monitor_update = ChannelMonitorUpdate {
                                update_id: self.context.latest_monitor_update_id + 1, // We don't increment this yet!
+                               counterparty_node_id: Some(self.context.counterparty_node_id),
                                updates: Vec::new(),
                        };
  
                                                        }
                                                }
                                        },
 +                                      &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
 +                                              match self.fail_htlc(htlc_id, (failure_code, sha256_of_onion), false, logger) {
 +                                                      Ok(update_fail_malformed_opt) => {
 +                                                              debug_assert!(update_fail_malformed_opt.is_some()); // See above comment
 +                                                              update_fail_count += 1;
 +                                                      },
 +                                                      Err(e) => {
 +                                                              if let ChannelError::Ignore(_) = e {}
 +                                                              else {
 +                                                                      panic!("Got a non-IgnoreError action trying to fail holding cell HTLC");
 +                                                              }
 +                                                      }
 +                                              }
 +                                      },
                                }
                        }
                        if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
                self.context.latest_monitor_update_id += 1;
                let mut monitor_update = ChannelMonitorUpdate {
                        update_id: self.context.latest_monitor_update_id,
+                       counterparty_node_id: Some(self.context.counterparty_node_id),
                        updates: vec![ChannelMonitorUpdateStep::CommitmentSecret {
                                idx: self.context.cur_counterparty_commitment_transaction_number + 1,
                                secret: msg.per_commitment_secret,
  
        /// Indicates that the signer may have some signatures for us, so we should retry if we're
        /// blocked.
 -      #[allow(unused)]
 +      #[cfg(async_signing)]
        pub fn signer_maybe_unblocked<L: Deref>(&mut self, logger: &L) -> SignerResumeUpdates where L::Target: Logger {
                let commitment_update = if self.context.signer_pending_commitment_update {
                        self.get_last_commitment_update_for_send(logger).ok()
                        }
                        update
                } else {
 -                      if !self.context.signer_pending_commitment_update {
 -                              log_trace!(logger, "Commitment update awaiting signer: setting signer_pending_commitment_update");
 -                              self.context.signer_pending_commitment_update = true;
 +                      #[cfg(not(async_signing))] {
 +                              panic!("Failed to get signature for new commitment state");
 +                      }
 +                      #[cfg(async_signing)] {
 +                              if !self.context.signer_pending_commitment_update {
 +                                      log_trace!(logger, "Commitment update awaiting signer: setting signer_pending_commitment_update");
 +                                      self.context.signer_pending_commitment_update = true;
 +                              }
 +                              return Err(());
                        }
 -                      return Err(());
                };
                Ok(msgs::CommitmentUpdate {
                        update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, update_fee,
                        self.context.latest_monitor_update_id += 1;
                        let monitor_update = ChannelMonitorUpdate {
                                update_id: self.context.latest_monitor_update_id,
+                               counterparty_node_id: Some(self.context.counterparty_node_id),
                                updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
                                        scriptpubkey: self.get_closing_scriptpubkey(),
                                }],
                self.context.latest_monitor_update_id += 1;
                let monitor_update = ChannelMonitorUpdate {
                        update_id: self.context.latest_monitor_update_id,
+                       counterparty_node_id: Some(self.context.counterparty_node_id),
                        updates: vec![ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {
                                commitment_txid: counterparty_commitment_txid,
                                htlc_outputs: htlcs.clone(),
                        self.context.latest_monitor_update_id += 1;
                        let monitor_update = ChannelMonitorUpdate {
                                update_id: self.context.latest_monitor_update_id,
+                               counterparty_node_id: Some(self.context.counterparty_node_id),
                                updates: vec![ChannelMonitorUpdateStep::ShutdownScript {
                                        scriptpubkey: self.get_closing_scriptpubkey(),
                                }],
@@@ -6458,14 -6382,9 +6480,14 @@@ impl<SP: Deref> OutboundV1Channel<SP> w
  
                let funding_created = self.get_funding_created_msg(logger);
                if funding_created.is_none() {
 -                      if !self.context.signer_pending_funding {
 -                              log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding");
 -                              self.context.signer_pending_funding = true;
 +                      #[cfg(not(async_signing))] {
 +                              panic!("Failed to get signature for new funding creation");
 +                      }
 +                      #[cfg(async_signing)] {
 +                              if !self.context.signer_pending_funding {
 +                                      log_trace!(logger, "funding_created awaiting signer; setting signer_pending_funding");
 +                                      self.context.signer_pending_funding = true;
 +                              }
                        }
                }
  
  
        /// Indicates that the signer may have some signatures for us, so we should retry if we're
        /// blocked.
 -      #[allow(unused)]
 +      #[cfg(async_signing)]
        pub fn signer_maybe_unblocked<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
                if self.context.signer_pending_funding && self.context.is_outbound() {
                        log_trace!(logger, "Signer unblocked a funding_created");
@@@ -7536,8 -7455,6 +7558,8 @@@ impl<SP: Deref> Writeable for Channel<S
  
                let mut holding_cell_skimmed_fees: Vec<Option<u64>> = Vec::new();
                let mut holding_cell_blinding_points: Vec<Option<PublicKey>> = Vec::new();
 +              // Vec of (htlc_id, failure_code, sha256_of_onion)
 +              let mut malformed_htlcs: Vec<(u64, u16, [u8; 32])> = Vec::new();
                (self.context.holding_cell_htlc_updates.len() as u64).write(writer)?;
                for update in self.context.holding_cell_htlc_updates.iter() {
                        match update {
                                        htlc_id.write(writer)?;
                                        err_packet.write(writer)?;
                                }
 +                              &HTLCUpdateAwaitingACK::FailMalformedHTLC {
 +                                      htlc_id, failure_code, sha256_of_onion
 +                              } => {
 +                                      // We don't want to break downgrading by adding a new variant, so write a dummy
 +                                      // `::FailHTLC` variant and write the real malformed error as an optional TLV.
 +                                      malformed_htlcs.push((htlc_id, failure_code, sha256_of_onion));
 +
 +                                      let dummy_err_packet = msgs::OnionErrorPacket { data: Vec::new() };
 +                                      2u8.write(writer)?;
 +                                      htlc_id.write(writer)?;
 +                                      dummy_err_packet.write(writer)?;
 +                              }
                        }
                }
  
                        (38, self.context.is_batch_funding, option),
                        (39, pending_outbound_blinding_points, optional_vec),
                        (41, holding_cell_blinding_points, optional_vec),
 +                      (43, malformed_htlcs, optional_vec), // Added in 0.0.119
                });
  
                Ok(())
@@@ -8028,8 -7932,6 +8050,8 @@@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> 
                let mut pending_outbound_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
                let mut holding_cell_blinding_points_opt: Option<Vec<Option<PublicKey>>> = None;
  
 +              let mut malformed_htlcs: Option<Vec<(u64, u16, [u8; 32])>> = None;
 +
                read_tlv_fields!(reader, {
                        (0, announcement_sigs, option),
                        (1, minimum_depth, option),
                        (38, is_batch_funding, option),
                        (39, pending_outbound_blinding_points_opt, optional_vec),
                        (41, holding_cell_blinding_points_opt, optional_vec),
 +                      (43, malformed_htlcs, optional_vec), // Added in 0.0.119
                });
  
                let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
                        if iter.next().is_some() { return Err(DecodeError::InvalidValue) }
                }
  
 +              if let Some(malformed_htlcs) = malformed_htlcs {
 +                      for (malformed_htlc_id, failure_code, sha256_of_onion) in malformed_htlcs {
 +                              let htlc_idx = holding_cell_htlc_updates.iter().position(|htlc| {
 +                                      if let HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet } = htlc {
 +                                              let matches = *htlc_id == malformed_htlc_id;
 +                                              if matches { debug_assert!(err_packet.data.is_empty()) }
 +                                              matches
 +                                      } else { false }
 +                              }).ok_or(DecodeError::InvalidValue)?;
 +                              let malformed_htlc = HTLCUpdateAwaitingACK::FailMalformedHTLC {
 +                                      htlc_id: malformed_htlc_id, failure_code, sha256_of_onion
 +                              };
 +                              let _ = core::mem::replace(&mut holding_cell_htlc_updates[htlc_idx], malformed_htlc);
 +                      }
 +              }
 +
                Ok(Channel {
                        context: ChannelContext {
                                user_id,
@@@ -8303,7 -8188,6 +8325,7 @@@ mod tests 
        use bitcoin::blockdata::transaction::{Transaction, TxOut};
        use bitcoin::blockdata::opcodes;
        use bitcoin::network::constants::Network;
 +      use crate::ln::onion_utils::INVALID_ONION_BLINDING;
        use crate::ln::{PaymentHash, PaymentPreimage};
        use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
        use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
        }
  
        #[test]
 -      fn blinding_point_skimmed_fee_ser() {
 -              // Ensure that channel blinding points and skimmed fees are (de)serialized properly.
 +      fn blinding_point_skimmed_fee_malformed_ser() {
 +              // Ensure that channel blinding points, skimmed fees, and malformed HTLCs are (de)serialized
 +              // properly.
                let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
                let secp_ctx = Secp256k1::new();
                let seed = [42; 32];
                        payment_preimage: PaymentPreimage([42; 32]),
                        htlc_id: 0,
                };
 -              let mut holding_cell_htlc_updates = Vec::with_capacity(10);
 -              for i in 0..10 {
 -                      if i % 3 == 0 {
 +              let dummy_holding_cell_failed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailHTLC {
 +                      htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] }
 +              };
 +              let dummy_holding_cell_malformed_htlc = |htlc_id| HTLCUpdateAwaitingACK::FailMalformedHTLC {
 +                      htlc_id, failure_code: INVALID_ONION_BLINDING, sha256_of_onion: [0; 32],
 +              };
 +              let mut holding_cell_htlc_updates = Vec::with_capacity(12);
 +              for i in 0..12 {
 +                      if i % 5 == 0 {
                                holding_cell_htlc_updates.push(dummy_holding_cell_add_htlc.clone());
 -                      } else if i % 3 == 1 {
 +                      } else if i % 5 == 1 {
                                holding_cell_htlc_updates.push(dummy_holding_cell_claim_htlc.clone());
 -                      } else {
 +                      } else if i % 5 == 2 {
                                let mut dummy_add = dummy_holding_cell_add_htlc.clone();
                                if let HTLCUpdateAwaitingACK::AddHTLC {
                                        ref mut blinding_point, ref mut skimmed_fee_msat, ..
                                        *skimmed_fee_msat = Some(42);
                                } else { panic!() }
                                holding_cell_htlc_updates.push(dummy_add);
 +                      } else if i % 5 == 3 {
 +                              holding_cell_htlc_updates.push(dummy_holding_cell_malformed_htlc(i as u64));
 +                      } else {
 +                              holding_cell_htlc_updates.push(dummy_holding_cell_failed_htlc(i as u64));
                        }
                }
                chan.context.holding_cell_htlc_updates = holding_cell_htlc_updates.clone();
index 560a7e58edafb2f8a703dbbc91688c2dac79f993,08296c4346d834fbcdd7878e938565a6fa4334d6..b2b28cdf365cce7ed07eda808089525c039ad015
@@@ -65,7 -65,7 +65,7 @@@ use crate::offers::merkle::SignError
  use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
  use crate::offers::parse::Bolt12SemanticError;
  use crate::offers::refund::{Refund, RefundBuilder};
 -use crate::onion_message::{Destination, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
 +use crate::onion_message::{Destination, MessageRouter, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
  use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider};
  use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
  use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
@@@ -111,7 -111,6 +111,7 @@@ use crate::ln::script::ShutdownScript
  
  /// Information about where a received HTLC('s onion) has indicated the HTLC should go.
  #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
 +#[cfg_attr(test, derive(Debug, PartialEq))]
  pub enum PendingHTLCRouting {
        /// An HTLC which should be forwarded on to another node.
        Forward {
                /// [`Event::PaymentClaimable::onion_fields`] as
                /// [`RecipientOnionFields::custom_tlvs`].
                custom_tlvs: Vec<(u64, Vec<u8>)>,
 +              /// Set if this HTLC is the final hop in a multi-hop blinded path.
 +              requires_blinded_error: bool,
        },
        /// The onion indicates that this is for payment to us but which contains the preimage for
        /// claiming included, and is unrelated to any invoice we'd previously generated (aka a
  }
  
  /// Information used to forward or fail this HTLC that is being forwarded within a blinded path.
 -#[derive(Clone, Copy, Hash, PartialEq, Eq)]
 +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
  pub struct BlindedForward {
        /// The `blinding_point` that was set in the inbound [`msgs::UpdateAddHTLC`], or in the inbound
        /// onion payload if we're the introduction node. Useful for calculating the next hop's
  impl PendingHTLCRouting {
        // Used to override the onion failure code and data if the HTLC is blinded.
        fn blinded_failure(&self) -> Option<BlindedFailure> {
 -              // TODO: needs update when we support receiving to multi-hop blinded paths
 -              if let Self::Forward { blinded: Some(_), .. } = self {
 -                      Some(BlindedFailure::FromIntroductionNode)
 -              } else {
 -                      None
 +              // TODO: needs update when we support forwarding blinded HTLCs as non-intro node
 +              match self {
 +                      Self::Forward { blinded: Some(_), .. } => Some(BlindedFailure::FromIntroductionNode),
 +                      Self::Receive { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode),
 +                      _ => None,
                }
        }
  }
  /// Information about an incoming HTLC, including the [`PendingHTLCRouting`] describing where it
  /// should go next.
  #[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
 +#[cfg_attr(test, derive(Debug, PartialEq))]
  pub struct PendingHTLCInfo {
        /// Further routing details based on whether the HTLC is being forwarded or received.
        pub routing: PendingHTLCRouting,
@@@ -269,7 -265,6 +269,7 @@@ pub(super) enum PendingHTLCStatus 
        Fail(HTLCFailureMsg),
  }
  
 +#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
  pub(super) struct PendingAddHTLCInfo {
        pub(super) forward_info: PendingHTLCInfo,
  
        prev_user_channel_id: u128,
  }
  
 +#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
  pub(super) enum HTLCForwardInfo {
        AddHTLC(PendingAddHTLCInfo),
        FailHTLC {
                htlc_id: u64,
                err_packet: msgs::OnionErrorPacket,
        },
 +      FailMalformedHTLC {
 +              htlc_id: u64,
 +              failure_code: u16,
 +              sha256_of_onion: [u8; 32],
 +      },
  }
  
  // Used for failing blinded HTLCs backwards correctly.
 -#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
  enum BlindedFailure {
        FromIntroductionNode,
 -      // Another variant will be added here for non-intro nodes.
 +      FromBlindedNode,
  }
  
  /// Tracks the inbound corresponding to an outbound HTLC
@@@ -1150,7 -1139,7 +1150,7 @@@ wher
  //              |
  //              |__`peer_state`
  //                  |
- //                  |__`id_to_peer`
+ //                  |__`outpoint_to_peer`
  //                  |
  //                  |__`short_to_chan_info`
  //                  |
@@@ -1244,11 -1233,7 +1244,7 @@@ wher
        /// See `ChannelManager` struct-level documentation for lock order requirements.
        outbound_scid_aliases: Mutex<HashSet<u64>>,
  
-       /// `channel_id` -> `counterparty_node_id`.
-       ///
-       /// Only `channel_id`s are allowed as keys in this map, and not `temporary_channel_id`s. As
-       /// multiple channels with the same `temporary_channel_id` to different peers can exist,
-       /// allowing `temporary_channel_id`s in this map would cause collisions for such channels.
+       /// Channel funding outpoint -> `counterparty_node_id`.
        ///
        /// Note that this map should only be used for `MonitorEvent` handling, to be able to access
        /// the corresponding channel for the event, as we only have access to the `channel_id` during
        /// required to access the channel with the `counterparty_node_id`.
        ///
        /// See `ChannelManager` struct-level documentation for lock order requirements.
-       id_to_peer: Mutex<HashMap<ChannelId, PublicKey>>,
+       #[cfg(not(test))]
+       outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>,
+       #[cfg(test)]
+       pub(crate) outpoint_to_peer: Mutex<HashMap<OutPoint, PublicKey>>,
  
        /// SCIDs (and outbound SCID aliases) -> `counterparty_node_id`s and `channel_id`s.
        ///
@@@ -2006,7 -1994,9 +2005,9 @@@ macro_rules! handle_error 
  
  macro_rules! update_maps_on_chan_removal {
        ($self: expr, $channel_context: expr) => {{
-               $self.id_to_peer.lock().unwrap().remove(&$channel_context.channel_id());
+               if let Some(outpoint) = $channel_context.get_funding_txo() {
+                       $self.outpoint_to_peer.lock().unwrap().remove(&outpoint);
+               }
                let mut short_to_chan_info = $self.short_to_chan_info.write().unwrap();
                if let Some(short_id) = $channel_context.get_short_channel_id() {
                        short_to_chan_info.remove(&short_id);
@@@ -2425,7 -2415,7 +2426,7 @@@ wher
                        forward_htlcs: Mutex::new(HashMap::new()),
                        claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: HashMap::new(), pending_claiming_payments: HashMap::new() }),
                        pending_intercepted_htlcs: Mutex::new(HashMap::new()),
-                       id_to_peer: Mutex::new(HashMap::new()),
+                       outpoint_to_peer: Mutex::new(HashMap::new()),
                        short_to_chan_info: FairRwLock::new(HashMap::new()),
  
                        our_network_pubkey: node_signer.get_node_id(Recipient::Node).unwrap(),
        fn list_funded_channels_with_filter<Fn: FnMut(&(&ChannelId, &Channel<SP>)) -> bool + Copy>(&self, f: Fn) -> Vec<ChannelDetails> {
                // Allocate our best estimate of the number of channels we have in the `res`
                // Vec. Sadly the `short_to_chan_info` map doesn't cover channels without
-               // a scid or a scid alias, and the `id_to_peer` shouldn't be used outside
+               // a scid or a scid alias, and the `outpoint_to_peer` shouldn't be used outside
                // of the ChannelMonitor handling. Therefore reallocations may still occur, but is
                // unlikely as the `short_to_chan_info` map often contains 2 entries for
                // the same channel.
        pub fn list_channels(&self) -> Vec<ChannelDetails> {
                // Allocate our best estimate of the number of channels we have in the `res`
                // Vec. Sadly the `short_to_chan_info` map doesn't cover channels without
-               // a scid or a scid alias, and the `id_to_peer` shouldn't be used outside
+               // a scid or a scid alias, and the `outpoint_to_peer` shouldn't be used outside
                // of the ChannelMonitor handling. Therefore reallocations may still occur, but is
                // unlikely as the `short_to_chan_info` map often contains 2 entries for
                // the same channel.
                        msg, &self.node_signer, &self.logger, &self.secp_ctx
                )?;
  
 -              let is_blinded = match next_hop {
 +              let is_intro_node_forward = match next_hop {
                        onion_utils::Hop::Forward {
 +                              // TODO: update this when we support blinded forwarding as non-intro node
                                next_hop_data: msgs::InboundOnionPayload::BlindedForward { .. }, ..
                        } => true,
 -                      _ => false, // TODO: update this when we support receiving to multi-hop blinded paths
 +                      _ => false,
                };
  
                macro_rules! return_err {
                                                WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id)),
                                                "Failed to accept/forward incoming HTLC: {}", $msg
                                        );
 -                                      let (err_code, err_data) = if is_blinded {
 +                                      // If `msg.blinding_point` is set, we must always fail with malformed.
 +                                      if msg.blinding_point.is_some() {
 +                                              return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
 +                                                      channel_id: msg.channel_id,
 +                                                      htlc_id: msg.htlc_id,
 +                                                      sha256_of_onion: [0; 32],
 +                                                      failure_code: INVALID_ONION_BLINDING,
 +                                              }));
 +                                      }
 +
 +                                      let (err_code, err_data) = if is_intro_node_forward {
                                                (INVALID_ONION_BLINDING, &[0; 32][..])
                                        } else { ($err_code, $data) };
                                        return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                {
                                        let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id));
                                        log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
 +                                      if msg.blinding_point.is_some() {
 +                                              return PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(
 +                                                      msgs::UpdateFailMalformedHTLC {
 +                                                              channel_id: msg.channel_id,
 +                                                              htlc_id: msg.htlc_id,
 +                                                              sha256_of_onion: [0; 32],
 +                                                              failure_code: INVALID_ONION_BLINDING,
 +                                                      }
 +                                              ))
 +                                      }
                                        return PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                channel_id: msg.channel_id,
                                                htlc_id: msg.htlc_id,
  
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
+               let funding_txo;
                let (chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
                        Some(ChannelPhase::UnfundedOutboundV1(mut chan)) => {
-                               let funding_txo = find_funding_output(&chan, &funding_transaction)?;
+                               funding_txo = find_funding_output(&chan, &funding_transaction)?;
  
                                let logger = WithChannelContext::from(&self.logger, &chan.context);
                                let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger)
                                panic!("Generated duplicate funding txid?");
                        },
                        hash_map::Entry::Vacant(e) => {
-                               let mut id_to_peer = self.id_to_peer.lock().unwrap();
-                               if id_to_peer.insert(chan.context.channel_id(), chan.context.get_counterparty_node_id()).is_some() {
-                                       panic!("id_to_peer map already contained funding txid, which shouldn't be possible");
+                               let mut outpoint_to_peer = self.outpoint_to_peer.lock().unwrap();
+                               if outpoint_to_peer.insert(funding_txo, chan.context.get_counterparty_node_id()).is_some() {
+                                       panic!("outpoint_to_peer map already contained funding outpoint, which shouldn't be possible");
                                }
                                e.insert(ChannelPhase::UnfundedOutboundV1(chan));
                        }
                                                                                                let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
                                                                                                let next_hop = match onion_utils::decode_next_payment_hop(
                                                                                                        phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac,
 -                                                                                                      payment_hash, &self.node_signer
 +                                                                                                      payment_hash, None, &self.node_signer
                                                                                                ) {
                                                                                                        Ok(res) => res,
                                                                                                        Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
                                                                                        fail_forward!(format!("Unknown short channel id {} for forward HTLC", short_chan_id), 0x4000 | 10, Vec::new(), None);
                                                                                }
                                                                        },
 -                                                                      HTLCForwardInfo::FailHTLC { .. } => {
 +                                                                      HTLCForwardInfo::FailHTLC { .. } | HTLCForwardInfo::FailMalformedHTLC { .. } => {
                                                                                // Channel went away before we could fail it. This implies
                                                                                // the channel is now on chain and our counterparty is
                                                                                // trying to broadcast the HTLC-Timeout, but that's their
                                                                                continue;
                                                                        }
                                                                },
 +                                                              HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
 +                                                                      log_trace!(self.logger, "Failing malformed HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
 +                                                                      if let Err(e) = chan.queue_fail_malformed_htlc(htlc_id, failure_code, sha256_of_onion, &self.logger) {
 +                                                                              if let ChannelError::Ignore(msg) = e {
 +                                                                                      log_trace!(self.logger, "Failed to fail HTLC with ID {} backwards to short_id {}: {}", htlc_id, short_chan_id, msg);
 +                                                                              } else {
 +                                                                                      panic!("Stated return value requirements in queue_fail_malformed_htlc() were not met");
 +                                                                              }
 +                                                                              // fail-backs are best-effort, we probably already have one
 +                                                                              // pending, and if not that's OK, if not, the channel is on
 +                                                                              // the chain and sending the HTLC-Timeout is their problem.
 +                                                                              continue;
 +                                                                      }
 +                                                              },
                                                        }
                                                }
                                        } else {
                                                        }) => {
                                                                let blinded_failure = routing.blinded_failure();
                                                                let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields) = match routing {
 -                                                                      PendingHTLCRouting::Receive { payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret, custom_tlvs } => {
 +                                                                      PendingHTLCRouting::Receive {
 +                                                                              payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret,
 +                                                                              custom_tlvs, requires_blinded_error: _
 +                                                                      } => {
                                                                                let _legacy_hop_data = Some(payment_data.clone());
                                                                                let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
                                                                                                payment_metadata, custom_tlvs };
                                                                                                htlc_id: $htlc.prev_hop.htlc_id,
                                                                                                incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
                                                                                                phantom_shared_secret,
 -                                                                                              blinded_failure: None,
 +                                                                                              blinded_failure,
                                                                                        }), payment_hash,
                                                                                        HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
                                                                                        HTLCDestination::FailedPayment { payment_hash: $payment_hash },
                                                                        },
                                                                };
                                                        },
 -                                                      HTLCForwardInfo::FailHTLC { .. } => {
 +                                                      HTLCForwardInfo::FailHTLC { .. } | HTLCForwardInfo::FailMalformedHTLC { .. } => {
                                                                panic!("Got pending fail of our own HTLC");
                                                        }
                                                }
                                        "Failing {}HTLC with payment_hash {} backwards from us: {:?}",
                                        if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error
                                );
 -                              let err_packet = match blinded_failure {
 +                              let failure = match blinded_failure {
                                        Some(BlindedFailure::FromIntroductionNode) => {
                                                let blinded_onion_error = HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32]);
 -                                              blinded_onion_error.get_encrypted_failure_packet(
 +                                              let err_packet = blinded_onion_error.get_encrypted_failure_packet(
                                                        incoming_packet_shared_secret, phantom_shared_secret
 -                                              )
 +                                              );
 +                                              HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet }
 +                                      },
 +                                      Some(BlindedFailure::FromBlindedNode) => {
 +                                              HTLCForwardInfo::FailMalformedHTLC {
 +                                                      htlc_id: *htlc_id,
 +                                                      failure_code: INVALID_ONION_BLINDING,
 +                                                      sha256_of_onion: [0; 32]
 +                                              }
                                        },
                                        None => {
 -                                              onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret)
 +                                              let err_packet = onion_error.get_encrypted_failure_packet(
 +                                                      incoming_packet_shared_secret, phantom_shared_secret
 +                                              );
 +                                              HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet }
                                        }
                                };
  
                                }
                                match forward_htlcs.entry(*short_channel_id) {
                                        hash_map::Entry::Occupied(mut entry) => {
 -                                              entry.get_mut().push(HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet });
 +                                              entry.get_mut().push(failure);
                                        },
                                        hash_map::Entry::Vacant(entry) => {
 -                                              entry.insert(vec!(HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet }));
 +                                              entry.insert(vec!(failure));
                                        }
                                }
                                mem::drop(forward_htlcs);
                }
                let preimage_update = ChannelMonitorUpdate {
                        update_id: CLOSED_CHANNEL_UPDATE_ID,
+                       counterparty_node_id: None,
                        updates: vec![ChannelMonitorUpdateStep::PaymentPreimage {
                                payment_preimage,
                        }],
                        Some(cp_id) => cp_id.clone(),
                        None => {
                                // TODO: Once we can rely on the counterparty_node_id from the
-                               // monitor event, this and the id_to_peer map should be removed.
-                               let id_to_peer = self.id_to_peer.lock().unwrap();
-                               match id_to_peer.get(&funding_txo.to_channel_id()) {
+                               // monitor event, this and the outpoint_to_peer map should be removed.
+                               let outpoint_to_peer = self.outpoint_to_peer.lock().unwrap();
+                               match outpoint_to_peer.get(&funding_txo) {
                                        Some(cp_id) => cp_id.clone(),
                                        None => return,
                                }
  
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
-               let (chan, funding_msg_opt, monitor) =
+               let (mut chan, funding_msg_opt, monitor) =
                        match peer_state.channel_by_id.remove(&msg.temporary_channel_id) {
                                Some(ChannelPhase::UnfundedInboundV1(inbound_chan)) => {
                                        let logger = WithChannelContext::from(&self.logger, &inbound_chan.context);
                                        match inbound_chan.funding_created(msg, best_block, &self.signer_provider, &&logger) {
                                                Ok(res) => res,
-                                               Err((mut inbound_chan, err)) => {
+                                               Err((inbound_chan, err)) => {
                                                        // We've already removed this inbound channel from the map in `PeerState`
                                                        // above so at this point we just need to clean up any lingering entries
                                                        // concerning this channel as it is safe to do so.
-                                                       update_maps_on_chan_removal!(self, &inbound_chan.context);
-                                                       let user_id = inbound_chan.context.get_user_id();
-                                                       let shutdown_res = inbound_chan.context.force_shutdown(false);
-                                                       return Err(MsgHandleErrInternal::from_finish_shutdown(format!("{}", err),
-                                                               msg.temporary_channel_id, user_id, shutdown_res, None, inbound_chan.context.get_value_satoshis()));
+                                                       debug_assert!(matches!(err, ChannelError::Close(_)));
+                                                       // Really we should be returning the channel_id the peer expects based
+                                                       // on their funding info here, but they're horribly confused anyway, so
+                                                       // there's not a lot we can do to save them.
+                                                       return Err(convert_chan_phase_err!(self, err, &mut ChannelPhase::UnfundedInboundV1(inbound_chan), &msg.temporary_channel_id).1);
                                                },
                                        }
                                },
-                               Some(ChannelPhase::Funded(_)) | Some(ChannelPhase::UnfundedOutboundV1(_)) => {
-                                       return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got an unexpected funding_created message from peer with counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id));
+                               Some(mut phase) => {
+                                       let err_msg = format!("Got an unexpected funding_created message from peer with counterparty_node_id {}", counterparty_node_id);
+                                       let err = ChannelError::Close(err_msg);
+                                       return Err(convert_chan_phase_err!(self, err, &mut phase, &msg.temporary_channel_id).1);
                                },
                                None => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id))
                        };
  
-               match peer_state.channel_by_id.entry(chan.context.channel_id()) {
+               let funded_channel_id = chan.context.channel_id();
+               macro_rules! fail_chan { ($err: expr) => { {
+                       // Note that at this point we've filled in the funding outpoint on our
+                       // channel, but its actually in conflict with another channel. Thus, if
+                       // we call `convert_chan_phase_err` immediately (thus calling
+                       // `update_maps_on_chan_removal`), we'll remove the existing channel
+                       // from `outpoint_to_peer`. Thus, we must first unset the funding outpoint
+                       // on the channel.
+                       let err = ChannelError::Close($err.to_owned());
+                       chan.unset_funding_info(msg.temporary_channel_id);
+                       return Err(convert_chan_phase_err!(self, err, chan, &funded_channel_id, UNFUNDED_CHANNEL).1);
+               } } }
+               match peer_state.channel_by_id.entry(funded_channel_id) {
                        hash_map::Entry::Occupied(_) => {
-                               Err(MsgHandleErrInternal::send_err_msg_no_close(
-                                       "Already had channel with the new channel_id".to_owned(),
-                                       chan.context.channel_id()
-                               ))
+                               fail_chan!("Already had channel with the new channel_id");
                        },
                        hash_map::Entry::Vacant(e) => {
-                               let mut id_to_peer_lock = self.id_to_peer.lock().unwrap();
-                               match id_to_peer_lock.entry(chan.context.channel_id()) {
+                               let mut outpoint_to_peer_lock = self.outpoint_to_peer.lock().unwrap();
+                               match outpoint_to_peer_lock.entry(monitor.get_funding_txo().0) {
                                        hash_map::Entry::Occupied(_) => {
-                                               return Err(MsgHandleErrInternal::send_err_msg_no_close(
-                                                       "The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
-                                                       chan.context.channel_id()))
+                                               fail_chan!("The funding_created message had the same funding_txid as an existing channel - funding is not possible");
                                        },
                                        hash_map::Entry::Vacant(i_e) => {
                                                let monitor_res = self.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
                                                if let Ok(persist_state) = monitor_res {
                                                        i_e.insert(chan.context.get_counterparty_node_id());
-                                                       mem::drop(id_to_peer_lock);
+                                                       mem::drop(outpoint_to_peer_lock);
  
                                                        // There's no problem signing a counterparty's funding transaction if our monitor
                                                        // hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
                                                } else {
                                                        let logger = WithChannelContext::from(&self.logger, &chan.context);
                                                        log_error!(logger, "Persisting initial ChannelMonitor failed, implying the funding outpoint was duplicated");
-                                                       let channel_id = match funding_msg_opt {
-                                                               Some(msg) => msg.channel_id,
-                                                               None => chan.context.channel_id(),
-                                                       };
-                                                       return Err(MsgHandleErrInternal::send_err_msg_no_close(
-                                                               "The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
-                                                               channel_id));
+                                                       fail_chan!("Duplicate funding outpoint");
                                                }
                                        }
                                }
                                                Err(e) => PendingHTLCStatus::Fail(e)
                                        };
                                        let create_pending_htlc_status = |chan: &Channel<SP>, pending_forward_info: PendingHTLCStatus, error_code: u16| {
 +                                              if msg.blinding_point.is_some() {
 +                                                      return PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(
 +                                                                      msgs::UpdateFailMalformedHTLC {
 +                                                                              channel_id: msg.channel_id,
 +                                                                              htlc_id: msg.htlc_id,
 +                                                                              sha256_of_onion: [0; 32],
 +                                                                              failure_code: INVALID_ONION_BLINDING,
 +                                                                      }
 +                                                      ))
 +                                              }
                                                // If the update_add is completely bogus, the call will Err and we will close,
                                                // but if we've sent a shutdown and they haven't acknowledged it yet, we just
                                                // want to reject the new HTLC and fail it backwards instead of forwarding.
                                                        Some(cp_id) => Some(cp_id),
                                                        None => {
                                                                // TODO: Once we can rely on the counterparty_node_id from the
-                                                               // monitor event, this and the id_to_peer map should be removed.
-                                                               let id_to_peer = self.id_to_peer.lock().unwrap();
-                                                               id_to_peer.get(&funding_outpoint.to_channel_id()).cloned()
+                                                               // monitor event, this and the outpoint_to_peer map should be removed.
+                                                               let outpoint_to_peer = self.outpoint_to_peer.lock().unwrap();
+                                                               outpoint_to_peer.get(&funding_outpoint).cloned()
                                                        }
                                                };
                                                if let Some(counterparty_node_id) = counterparty_node_id_opt {
        /// attempted in every channel, or in the specifically provided channel.
        ///
        /// [`ChannelSigner`]: crate::sign::ChannelSigner
 -      #[cfg(test)] // This is only implemented for one signer method, and should be private until we
 -                   // actually finish implementing it fully.
 +      #[cfg(async_signing)]
        pub fn signer_unblocked(&self, channel_opt: Option<(PublicKey, ChannelId)>) {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
  
        ///
        /// # Privacy
        ///
 -      /// Uses a one-hop [`BlindedPath`] for the offer with [`ChannelManager::get_our_node_id`] as the
 -      /// introduction node and a derived signing pubkey for recipient privacy. As such, currently,
 -      /// the node must be announced. Otherwise, there is no way to find a path to the introduction
 -      /// node in order to send the [`InvoiceRequest`].
 +      /// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the offer.
 +      /// However, if one is not found, uses a one-hop [`BlindedPath`] with
 +      /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
 +      /// the node must be announced, otherwise, there is no way to find a path to the introduction in
 +      /// order to send the [`InvoiceRequest`].
 +      ///
 +      /// Also, uses a derived signing pubkey in the offer for recipient privacy.
        ///
        /// # Limitations
        ///
        /// Requires a direct connection to the introduction node in the responding [`InvoiceRequest`]'s
        /// reply path.
        ///
 +      /// # Errors
 +      ///
 +      /// Errors if the parameterized [`Router`] is unable to create a blinded path for the offer.
 +      ///
        /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
        ///
        /// [`Offer`]: crate::offers::offer::Offer
        /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
        pub fn create_offer_builder(
                &self, description: String
 -      ) -> OfferBuilder<DerivedMetadata, secp256k1::All> {
 +      ) -> Result<OfferBuilder<DerivedMetadata, secp256k1::All>, Bolt12SemanticError> {
                let node_id = self.get_our_node_id();
                let expanded_key = &self.inbound_payment_key;
                let entropy = &*self.entropy_source;
                let secp_ctx = &self.secp_ctx;
 -              let path = self.create_one_hop_blinded_path();
  
 -              OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, entropy, secp_ctx)
 +              let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
 +              let builder = OfferBuilder::deriving_signing_pubkey(
 +                      description, node_id, expanded_key, entropy, secp_ctx
 +              )
                        .chain_hash(self.chain_hash)
 -                      .path(path)
 +                      .path(path);
 +
 +              Ok(builder)
        }
  
        /// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
        ///
        /// # Privacy
        ///
 -      /// Uses a one-hop [`BlindedPath`] for the refund with [`ChannelManager::get_our_node_id`] as
 -      /// the introduction node and a derived payer id for payer privacy. As such, currently, the
 -      /// node must be announced. Otherwise, there is no way to find a path to the introduction node
 -      /// in order to send the [`Bolt12Invoice`].
 +      /// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the refund.
 +      /// However, if one is not found, uses a one-hop [`BlindedPath`] with
 +      /// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
 +      /// the node must be announced, otherwise, there is no way to find a path to the introduction in
 +      /// order to send the [`Bolt12Invoice`].
 +      ///
 +      /// Also, uses a derived payer id in the refund for payer privacy.
        ///
        /// # Limitations
        ///
        ///
        /// # Errors
        ///
 -      /// Errors if a duplicate `payment_id` is provided given the caveats in the aforementioned link
 -      /// or if `amount_msats` is invalid.
 +      /// Errors if:
 +      /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
 +      /// - `amount_msats` is invalid, or
 +      /// - the parameterized [`Router`] is unable to create a blinded path for the refund.
        ///
        /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
        ///
        /// [`Refund`]: crate::offers::refund::Refund
        /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
        /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
 +      /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
        pub fn create_refund_builder(
                &self, description: String, amount_msats: u64, absolute_expiry: Duration,
                payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
                let expanded_key = &self.inbound_payment_key;
                let entropy = &*self.entropy_source;
                let secp_ctx = &self.secp_ctx;
 -              let path = self.create_one_hop_blinded_path();
  
 +              let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = RefundBuilder::deriving_payer_id(
                        description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
                )?
        ///
        /// # Errors
        ///
 -      /// Errors if a duplicate `payment_id` is provided given the caveats in the aforementioned link
 -      /// or if the provided parameters are invalid for the offer.
 +      /// Errors if:
 +      /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
 +      /// - the provided parameters are invalid for the offer,
 +      /// - the parameterized [`Router`] is unable to create a blinded reply path for the invoice
 +      ///   request.
        ///
        /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
        /// [`InvoiceRequest::quantity`]: crate::offers::invoice_request::InvoiceRequest::quantity
                        None => builder,
                        Some(payer_note) => builder.payer_note(payer_note),
                };
 -
                let invoice_request = builder.build_and_sign()?;
 -              let reply_path = self.create_one_hop_blinded_path();
 +              let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
  
                let expiration = StaleExpiration::TimerTicks(1);
                self.pending_outbound_payments
        /// node meeting the aforementioned criteria, but there's no guarantee that they will be
        /// received and no retries will be made.
        ///
 +      /// # Errors
 +      ///
 +      /// Errors if the parameterized [`Router`] is unable to create a blinded payment path or reply
 +      /// path for the invoice.
 +      ///
        /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
        pub fn request_refund_payment(&self, refund: &Refund) -> Result<(), Bolt12SemanticError> {
                let expanded_key = &self.inbound_payment_key;
  
                match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
                        Ok((payment_hash, payment_secret)) => {
 -                              let payment_paths = vec![
 -                                      self.create_one_hop_blinded_payment_path(payment_secret),
 -                              ];
 +                              let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret)
 +                                      .map_err(|_| Bolt12SemanticError::MissingPaths)?;
 +
                                #[cfg(not(feature = "no-std"))]
                                let builder = refund.respond_using_derived_keys(
                                        payment_paths, payment_hash, expanded_key, entropy
                                        payment_paths, payment_hash, created_at, expanded_key, entropy
                                )?;
                                let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
 -                              let reply_path = self.create_one_hop_blinded_path();
 +                              let reply_path = self.create_blinded_path()
 +                                      .map_err(|_| Bolt12SemanticError::MissingPaths)?;
  
                                let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
                                if refund.paths().is_empty() {
                inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
        }
  
 -      /// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction
 -      /// node.
 -      fn create_one_hop_blinded_path(&self) -> BlindedPath {
 +      /// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
 +      ///
 +      /// Errors if the `MessageRouter` errors or returns an empty `Vec`.
 +      fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
 +              let recipient = self.get_our_node_id();
                let entropy_source = self.entropy_source.deref();
                let secp_ctx = &self.secp_ctx;
 -              BlindedPath::one_hop_for_message(self.get_our_node_id(), entropy_source, secp_ctx).unwrap()
 +
 +              let peers = self.per_peer_state.read().unwrap()
 +                      .iter()
 +                      .filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages())
 +                      .map(|(node_id, _)| *node_id)
 +                      .collect::<Vec<_>>();
 +
 +              self.router
 +                      .create_blinded_paths(recipient, peers, entropy_source, secp_ctx)
 +                      .and_then(|paths| paths.into_iter().next().ok_or(()))
        }
  
 -      /// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction
 -      /// node.
 -      fn create_one_hop_blinded_payment_path(
 -              &self, payment_secret: PaymentSecret
 -      ) -> (BlindedPayInfo, BlindedPath) {
 +      /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
 +      /// [`Router::create_blinded_payment_paths`].
 +      fn create_blinded_payment_paths(
 +              &self, amount_msats: u64, payment_secret: PaymentSecret
 +      ) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
                let entropy_source = self.entropy_source.deref();
                let secp_ctx = &self.secp_ctx;
  
 +              let first_hops = self.list_usable_channels();
                let payee_node_id = self.get_our_node_id();
 -              let max_cltv_expiry = self.best_block.read().unwrap().height() + LATENCY_GRACE_PERIOD_BLOCKS;
 +              let max_cltv_expiry = self.best_block.read().unwrap().height() + CLTV_FAR_FAR_AWAY
 +                      + LATENCY_GRACE_PERIOD_BLOCKS;
                let payee_tlvs = ReceiveTlvs {
                        payment_secret,
                        payment_constraints: PaymentConstraints {
                                htlc_minimum_msat: 1,
                        },
                };
 -              // TODO: Err for overflow?
 -              BlindedPath::one_hop_for_payment(
 -                      payee_node_id, payee_tlvs, entropy_source, secp_ctx
 -              ).unwrap()
 +              self.router.create_blinded_payment_paths(
 +                      payee_node_id, first_hops, payee_tlvs, amount_msats, entropy_source, secp_ctx
 +              )
        }
  
        /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
@@@ -9164,7 -9066,7 +9172,7 @@@ wher
                                let amount_msats = match InvoiceBuilder::<DerivedSigningPubkey>::amount_msats(
                                        &invoice_request
                                ) {
 -                                      Ok(amount_msats) => Some(amount_msats),
 +                                      Ok(amount_msats) => amount_msats,
                                        Err(error) => return Some(OffersMessage::InvoiceError(error.into())),
                                };
                                let invoice_request = match invoice_request.verify(expanded_key, secp_ctx) {
                                                return Some(OffersMessage::InvoiceError(error.into()));
                                        },
                                };
 -                              let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
  
 -                              match self.create_inbound_payment(amount_msats, relative_expiry, None) {
 -                                      Ok((payment_hash, payment_secret)) if invoice_request.keys.is_some() => {
 -                                              let payment_paths = vec![
 -                                                      self.create_one_hop_blinded_payment_path(payment_secret),
 -                                              ];
 -                                              #[cfg(not(feature = "no-std"))]
 -                                              let builder = invoice_request.respond_using_derived_keys(
 -                                                      payment_paths, payment_hash
 -                                              );
 -                                              #[cfg(feature = "no-std")]
 -                                              let created_at = Duration::from_secs(
 -                                                      self.highest_seen_timestamp.load(Ordering::Acquire) as u64
 -                                              );
 -                                              #[cfg(feature = "no-std")]
 -                                              let builder = invoice_request.respond_using_derived_keys_no_std(
 -                                                      payment_paths, payment_hash, created_at
 -                                              );
 -                                              match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) {
 -                                                      Ok(invoice) => Some(OffersMessage::Invoice(invoice)),
 -                                                      Err(error) => Some(OffersMessage::InvoiceError(error.into())),
 -                                              }
 -                                      },
 -                                      Ok((payment_hash, payment_secret)) => {
 -                                              let payment_paths = vec![
 -                                                      self.create_one_hop_blinded_payment_path(payment_secret),
 -                                              ];
 -                                              #[cfg(not(feature = "no-std"))]
 -                                              let builder = invoice_request.respond_with(payment_paths, payment_hash);
 -                                              #[cfg(feature = "no-std")]
 -                                              let created_at = Duration::from_secs(
 -                                                      self.highest_seen_timestamp.load(Ordering::Acquire) as u64
 -                                              );
 -                                              #[cfg(feature = "no-std")]
 -                                              let builder = invoice_request.respond_with_no_std(
 -                                                      payment_paths, payment_hash, created_at
 -                                              );
 -                                              let response = builder.and_then(|builder| builder.allow_mpp().build())
 -                                                      .map_err(|e| OffersMessage::InvoiceError(e.into()))
 -                                                      .and_then(|invoice|
 -                                                              match invoice.sign(|invoice| self.node_signer.sign_bolt12_invoice(invoice)) {
 -                                                                      Ok(invoice) => Ok(OffersMessage::Invoice(invoice)),
 -                                                                      Err(SignError::Signing(())) => Err(OffersMessage::InvoiceError(
 -                                                                                      InvoiceError::from_string("Failed signing invoice".to_string())
 -                                                                      )),
 -                                                                      Err(SignError::Verification(_)) => Err(OffersMessage::InvoiceError(
 -                                                                                      InvoiceError::from_string("Failed invoice signature verification".to_string())
 -                                                                      )),
 -                                                              });
 -                                              match response {
 -                                                      Ok(invoice) => Some(invoice),
 -                                                      Err(error) => Some(error),
 -                                              }
 +                              let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32;
 +                              let (payment_hash, payment_secret) = match self.create_inbound_payment(
 +                                      Some(amount_msats), relative_expiry, None
 +                              ) {
 +                                      Ok((payment_hash, payment_secret)) => (payment_hash, payment_secret),
 +                                      Err(()) => {
 +                                              let error = Bolt12SemanticError::InvalidAmount;
 +                                              return Some(OffersMessage::InvoiceError(error.into()));
                                        },
 +                              };
 +
 +                              let payment_paths = match self.create_blinded_payment_paths(
 +                                      amount_msats, payment_secret
 +                              ) {
 +                                      Ok(payment_paths) => payment_paths,
                                        Err(()) => {
 -                                              Some(OffersMessage::InvoiceError(Bolt12SemanticError::InvalidAmount.into()))
 +                                              let error = Bolt12SemanticError::MissingPaths;
 +                                              return Some(OffersMessage::InvoiceError(error.into()));
                                        },
 +                              };
 +
 +                              #[cfg(feature = "no-std")]
 +                              let created_at = Duration::from_secs(
 +                                      self.highest_seen_timestamp.load(Ordering::Acquire) as u64
 +                              );
 +
 +                              if invoice_request.keys.is_some() {
 +                                      #[cfg(not(feature = "no-std"))]
 +                                      let builder = invoice_request.respond_using_derived_keys(
 +                                              payment_paths, payment_hash
 +                                      );
 +                                      #[cfg(feature = "no-std")]
 +                                      let builder = invoice_request.respond_using_derived_keys_no_std(
 +                                              payment_paths, payment_hash, created_at
 +                                      );
 +                                      match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) {
 +                                              Ok(invoice) => Some(OffersMessage::Invoice(invoice)),
 +                                              Err(error) => Some(OffersMessage::InvoiceError(error.into())),
 +                                      }
 +                              } else {
 +                                      #[cfg(not(feature = "no-std"))]
 +                                      let builder = invoice_request.respond_with(payment_paths, payment_hash);
 +                                      #[cfg(feature = "no-std")]
 +                                      let builder = invoice_request.respond_with_no_std(
 +                                              payment_paths, payment_hash, created_at
 +                                      );
 +                                      let response = builder.and_then(|builder| builder.allow_mpp().build())
 +                                              .map_err(|e| OffersMessage::InvoiceError(e.into()))
 +                                              .and_then(|invoice|
 +                                                      match invoice.sign(|invoice| self.node_signer.sign_bolt12_invoice(invoice)) {
 +                                                              Ok(invoice) => Ok(OffersMessage::Invoice(invoice)),
 +                                                              Err(SignError::Signing(())) => Err(OffersMessage::InvoiceError(
 +                                                                              InvoiceError::from_string("Failed signing invoice".to_string())
 +                                                              )),
 +                                                              Err(SignError::Verification(_)) => Err(OffersMessage::InvoiceError(
 +                                                                              InvoiceError::from_string("Failed invoice signature verification".to_string())
 +                                                              )),
 +                                                      });
 +                                      match response {
 +                                              Ok(invoice) => Some(invoice),
 +                                              Err(error) => Some(error),
 +                                      }
                                }
                        },
                        OffersMessage::Invoice(invoice) => {
@@@ -9482,7 -9379,6 +9490,7 @@@ impl_writeable_tlv_based_enum!(PendingH
                (2, incoming_cltv_expiry, required),
                (3, payment_metadata, option),
                (5, custom_tlvs, optional_vec),
 +              (7, requires_blinded_error, (default_value, false)),
        },
        (2, ReceiveKeysend) => {
                (0, payment_preimage, required),
@@@ -9577,8 -9473,7 +9585,8 @@@ impl_writeable_tlv_based_enum!(PendingH
  );
  
  impl_writeable_tlv_based_enum!(BlindedFailure,
 -      (0, FromIntroductionNode) => {}, ;
 +      (0, FromIntroductionNode) => {},
 +      (2, FromBlindedNode) => {}, ;
  );
  
  impl_writeable_tlv_based!(HTLCPreviousHopData, {
@@@ -9742,68 -9637,13 +9750,68 @@@ impl_writeable_tlv_based!(PendingAddHTL
        (6, prev_funding_outpoint, required),
  });
  
 -impl_writeable_tlv_based_enum!(HTLCForwardInfo,
 -      (1, FailHTLC) => {
 -              (0, htlc_id, required),
 -              (2, err_packet, required),
 -      };
 -      (0, AddHTLC)
 -);
 +impl Writeable for HTLCForwardInfo {
 +      fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
 +              const FAIL_HTLC_VARIANT_ID: u8 = 1;
 +              match self {
 +                      Self::AddHTLC(info) => {
 +                              0u8.write(w)?;
 +                              info.write(w)?;
 +                      },
 +                      Self::FailHTLC { htlc_id, err_packet } => {
 +                              FAIL_HTLC_VARIANT_ID.write(w)?;
 +                              write_tlv_fields!(w, {
 +                                      (0, htlc_id, required),
 +                                      (2, err_packet, required),
 +                              });
 +                      },
 +                      Self::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
 +                              // Since this variant was added in 0.0.119, write this as `::FailHTLC` with an empty error
 +                              // packet so older versions have something to fail back with, but serialize the real data as
 +                              // optional TLVs for the benefit of newer versions.
 +                              FAIL_HTLC_VARIANT_ID.write(w)?;
 +                              let dummy_err_packet = msgs::OnionErrorPacket { data: Vec::new() };
 +                              write_tlv_fields!(w, {
 +                                      (0, htlc_id, required),
 +                                      (1, failure_code, required),
 +                                      (2, dummy_err_packet, required),
 +                                      (3, sha256_of_onion, required),
 +                              });
 +                      },
 +              }
 +              Ok(())
 +      }
 +}
 +
 +impl Readable for HTLCForwardInfo {
 +      fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
 +              let id: u8 = Readable::read(r)?;
 +              Ok(match id {
 +                      0 => Self::AddHTLC(Readable::read(r)?),
 +                      1 => {
 +                              _init_and_read_len_prefixed_tlv_fields!(r, {
 +                                      (0, htlc_id, required),
 +                                      (1, malformed_htlc_failure_code, option),
 +                                      (2, err_packet, required),
 +                                      (3, sha256_of_onion, option),
 +                              });
 +                              if let Some(failure_code) = malformed_htlc_failure_code {
 +                                      Self::FailMalformedHTLC {
 +                                              htlc_id: _init_tlv_based_struct_field!(htlc_id, required),
 +                                              failure_code,
 +                                              sha256_of_onion: sha256_of_onion.ok_or(DecodeError::InvalidValue)?,
 +                                      }
 +                              } else {
 +                                      Self::FailHTLC {
 +                                              htlc_id: _init_tlv_based_struct_field!(htlc_id, required),
 +                                              err_packet: _init_tlv_based_struct_field!(err_packet, required),
 +                                      }
 +                              }
 +                      },
 +                      _ => return Err(DecodeError::InvalidValue),
 +              })
 +      }
 +}
  
  impl_writeable_tlv_based!(PendingInboundPayment, {
        (0, payment_secret, required),
@@@ -10249,7 -10089,7 +10257,7 @@@ wher
                let channel_count: u64 = Readable::read(reader)?;
                let mut funding_txo_set = HashSet::with_capacity(cmp::min(channel_count as usize, 128));
                let mut funded_peer_channels: HashMap<PublicKey, HashMap<ChannelId, ChannelPhase<SP>>> = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
-               let mut id_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
+               let mut outpoint_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
                let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
                let mut channel_closures = VecDeque::new();
                let mut close_background_events = Vec::new();
                                        if let Some(short_channel_id) = channel.context.get_short_channel_id() {
                                                short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
                                        }
-                                       if channel.context.is_funding_broadcast() {
-                                               id_to_peer.insert(channel.context.channel_id(), channel.context.get_counterparty_node_id());
+                                       if let Some(funding_txo) = channel.context.get_funding_txo() {
+                                               outpoint_to_peer.insert(funding_txo, channel.context.get_counterparty_node_id());
                                        }
                                        match funded_peer_channels.entry(channel.context.get_counterparty_node_id()) {
                                                hash_map::Entry::Occupied(mut entry) => {
                                        &funding_txo.to_channel_id());
                                let monitor_update = ChannelMonitorUpdate {
                                        update_id: CLOSED_CHANNEL_UPDATE_ID,
+                                       counterparty_node_id: None,
                                        updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast: true }],
                                };
                                close_background_events.push(BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup((*funding_txo, monitor_update)));
                        // We only rebuild the pending payments map if we were most recently serialized by
                        // 0.0.102+
                        for (_, monitor) in args.channel_monitors.iter() {
-                               let counterparty_opt = id_to_peer.get(&monitor.get_funding_txo().0.to_channel_id());
+                               let counterparty_opt = outpoint_to_peer.get(&monitor.get_funding_txo().0);
                                if counterparty_opt.is_none() {
                                        let logger = WithChannelMonitor::from(&args.logger, monitor);
                                        for (htlc_source, (htlc, _)) in monitor.get_pending_or_resolved_outbound_htlcs() {
                                                // without the new monitor persisted - we'll end up right back here on
                                                // restart.
                                                let previous_channel_id = claimable_htlc.prev_hop.outpoint.to_channel_id();
-                                               if let Some(peer_node_id) = id_to_peer.get(&previous_channel_id){
+                                               if let Some(peer_node_id) = outpoint_to_peer.get(&claimable_htlc.prev_hop.outpoint) {
                                                        let peer_state_mutex = per_peer_state.get(peer_node_id).unwrap();
                                                        let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                                                        let peer_state = &mut *peer_state_lock;
                        forward_htlcs: Mutex::new(forward_htlcs),
                        claimable_payments: Mutex::new(ClaimablePayments { claimable_payments, pending_claiming_payments: pending_claiming_payments.unwrap() }),
                        outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
-                       id_to_peer: Mutex::new(id_to_peer),
+                       outpoint_to_peer: Mutex::new(outpoint_to_peer),
                        short_to_chan_info: FairRwLock::new(short_to_chan_info),
                        fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(),
  
@@@ -11098,14 -10939,12 +11107,14 @@@ mod tests 
        use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
        use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::ChannelId;
 -      use crate::ln::channelmanager::{create_recv_pending_htlc_info, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
 +      use crate::ln::channelmanager::{create_recv_pending_htlc_info, HTLCForwardInfo, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs::{self, ErrorAction};
        use crate::ln::msgs::ChannelMessageHandler;
 +      use crate::prelude::*;
        use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
        use crate::util::errors::APIError;
 +      use crate::util::ser::Writeable;
        use crate::util::test_utils;
        use crate::util::config::{ChannelConfig, ChannelConfigUpdate};
        use crate::sign::EntropySource;
        }
  
        #[test]
-       fn test_id_to_peer_coverage() {
-               // Test that the `ChannelManager:id_to_peer` contains channels which have been assigned
+       fn test_outpoint_to_peer_coverage() {
+               // Test that the `ChannelManager:outpoint_to_peer` contains channels which have been assigned
                // a `channel_id` (i.e. have had the funding tx created), and that they are removed once
                // the channel is successfully closed.
                let chanmon_cfgs = create_chanmon_cfgs(2);
                let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
                nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel);
  
-               let (temporary_channel_id, tx, _funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
+               let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
                let channel_id = ChannelId::from_bytes(tx.txid().to_byte_array());
                {
-                       // Ensure that the `id_to_peer` map is empty until either party has received the
+                       // Ensure that the `outpoint_to_peer` map is empty until either party has received the
                        // funding transaction, and have the real `channel_id`.
-                       assert_eq!(nodes[0].node.id_to_peer.lock().unwrap().len(), 0);
-                       assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+                       assert_eq!(nodes[0].node.outpoint_to_peer.lock().unwrap().len(), 0);
+                       assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 0);
                }
  
                nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
                {
-                       // Assert that `nodes[0]`'s `id_to_peer` map is populated with the channel as soon as
+                       // Assert that `nodes[0]`'s `outpoint_to_peer` map is populated with the channel as soon as
                        // as it has the funding transaction.
-                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       let nodes_0_lock = nodes[0].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_0_lock.len(), 1);
-                       assert!(nodes_0_lock.contains_key(&channel_id));
+                       assert!(nodes_0_lock.contains_key(&funding_output));
                }
  
-               assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+               assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 0);
  
                let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
  
                nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
                {
-                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       let nodes_0_lock = nodes[0].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_0_lock.len(), 1);
-                       assert!(nodes_0_lock.contains_key(&channel_id));
+                       assert!(nodes_0_lock.contains_key(&funding_output));
                }
                expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
  
                {
-                       // Assert that `nodes[1]`'s `id_to_peer` map is populated with the channel as soon as
-                       // as it has the funding transaction.
-                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       // Assert that `nodes[1]`'s `outpoint_to_peer` map is populated with the channel as
+                       // soon as it has the funding transaction.
+                       let nodes_1_lock = nodes[1].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_1_lock.len(), 1);
-                       assert!(nodes_1_lock.contains_key(&channel_id));
+                       assert!(nodes_1_lock.contains_key(&funding_output));
                }
                check_added_monitors!(nodes[1], 1);
                let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
                let closing_signed_node_0 = get_event_msg!(nodes[0], MessageSendEvent::SendClosingSigned, nodes[1].node.get_our_node_id());
                nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &closing_signed_node_0);
                {
-                       // Assert that the channel is kept in the `id_to_peer` map for both nodes until the
+                       // Assert that the channel is kept in the `outpoint_to_peer` map for both nodes until the
                        // channel can be fully closed by both parties (i.e. no outstanding htlcs exists, the
                        // fee for the closing transaction has been negotiated and the parties has the other
                        // party's signature for the fee negotiated closing transaction.)
-                       let nodes_0_lock = nodes[0].node.id_to_peer.lock().unwrap();
+                       let nodes_0_lock = nodes[0].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_0_lock.len(), 1);
-                       assert!(nodes_0_lock.contains_key(&channel_id));
+                       assert!(nodes_0_lock.contains_key(&funding_output));
                }
  
                {
                        // At this stage, `nodes[1]` has proposed a fee for the closing transaction in the
                        // `handle_closing_signed` call above. As `nodes[1]` has not yet received the signature
                        // from `nodes[0]` for the closing transaction with the proposed fee, the channel is
-                       // kept in the `nodes[1]`'s `id_to_peer` map.
-                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       // kept in the `nodes[1]`'s `outpoint_to_peer` map.
+                       let nodes_1_lock = nodes[1].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_1_lock.len(), 1);
-                       assert!(nodes_1_lock.contains_key(&channel_id));
+                       assert!(nodes_1_lock.contains_key(&funding_output));
                }
  
                nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendClosingSigned, nodes[0].node.get_our_node_id()));
                        // `nodes[0]` accepts `nodes[1]`'s proposed fee for the closing transaction, and
                        // therefore has all it needs to fully close the channel (both signatures for the
                        // closing transaction).
-                       // Assert that the channel is removed from `nodes[0]`'s `id_to_peer` map as it can be
+                       // Assert that the channel is removed from `nodes[0]`'s `outpoint_to_peer` map as it can be
                        // fully closed by `nodes[0]`.
-                       assert_eq!(nodes[0].node.id_to_peer.lock().unwrap().len(), 0);
+                       assert_eq!(nodes[0].node.outpoint_to_peer.lock().unwrap().len(), 0);
  
-                       // Assert that the channel is still in `nodes[1]`'s  `id_to_peer` map, as `nodes[1]`
+                       // Assert that the channel is still in `nodes[1]`'s  `outpoint_to_peer` map, as `nodes[1]`
                        // doesn't have `nodes[0]`'s signature for the closing transaction yet.
-                       let nodes_1_lock = nodes[1].node.id_to_peer.lock().unwrap();
+                       let nodes_1_lock = nodes[1].node.outpoint_to_peer.lock().unwrap();
                        assert_eq!(nodes_1_lock.len(), 1);
-                       assert!(nodes_1_lock.contains_key(&channel_id));
+                       assert!(nodes_1_lock.contains_key(&funding_output));
                }
  
                let (_nodes_0_update, closing_signed_node_0) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id());
  
                nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &closing_signed_node_0.unwrap());
                {
-                       // Assert that the channel has now been removed from both parties `id_to_peer` map once
+                       // Assert that the channel has now been removed from both parties `outpoint_to_peer` map once
                        // they both have everything required to fully close the channel.
-                       assert_eq!(nodes[1].node.id_to_peer.lock().unwrap().len(), 0);
+                       assert_eq!(nodes[1].node.outpoint_to_peer.lock().unwrap().len(), 0);
                }
                let (_nodes_1_update, _none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id());
  
                        check_spends!(txn[0], funding_tx);
                }
        }
 +
 +      #[test]
 +      fn test_malformed_forward_htlcs_ser() {
 +              // Ensure that `HTLCForwardInfo::FailMalformedHTLC`s are (de)serialized properly.
 +              let chanmon_cfg = create_chanmon_cfgs(1);
 +              let node_cfg = create_node_cfgs(1, &chanmon_cfg);
 +              let persister;
 +              let chain_monitor;
 +              let chanmgrs = create_node_chanmgrs(1, &node_cfg, &[None]);
 +              let deserialized_chanmgr;
 +              let mut nodes = create_network(1, &node_cfg, &chanmgrs);
 +
 +              let dummy_failed_htlc = |htlc_id| {
 +                      HTLCForwardInfo::FailHTLC { htlc_id, err_packet: msgs::OnionErrorPacket { data: vec![42] }, }
 +              };
 +              let dummy_malformed_htlc = |htlc_id| {
 +                      HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code: 0x4000, sha256_of_onion: [0; 32] }
 +              };
 +
 +              let dummy_htlcs_1: Vec<HTLCForwardInfo> = (1..10).map(|htlc_id| {
 +                      if htlc_id % 2 == 0 {
 +                              dummy_failed_htlc(htlc_id)
 +                      } else {
 +                              dummy_malformed_htlc(htlc_id)
 +                      }
 +              }).collect();
 +
 +              let dummy_htlcs_2: Vec<HTLCForwardInfo> = (1..10).map(|htlc_id| {
 +                      if htlc_id % 2 == 1 {
 +                              dummy_failed_htlc(htlc_id)
 +                      } else {
 +                              dummy_malformed_htlc(htlc_id)
 +                      }
 +              }).collect();
 +
 +
 +              let (scid_1, scid_2) = (42, 43);
 +              let mut forward_htlcs = HashMap::new();
 +              forward_htlcs.insert(scid_1, dummy_htlcs_1.clone());
 +              forward_htlcs.insert(scid_2, dummy_htlcs_2.clone());
 +
 +              let mut chanmgr_fwd_htlcs = nodes[0].node.forward_htlcs.lock().unwrap();
 +              *chanmgr_fwd_htlcs = forward_htlcs.clone();
 +              core::mem::drop(chanmgr_fwd_htlcs);
 +
 +              reload_node!(nodes[0], nodes[0].node.encode(), &[], persister, chain_monitor, deserialized_chanmgr);
 +
 +              let mut deserialized_fwd_htlcs = nodes[0].node.forward_htlcs.lock().unwrap();
 +              for scid in [scid_1, scid_2].iter() {
 +                      let deserialized_htlcs = deserialized_fwd_htlcs.remove(scid).unwrap();
 +                      assert_eq!(forward_htlcs.remove(scid).unwrap(), deserialized_htlcs);
 +              }
 +              assert!(deserialized_fwd_htlcs.is_empty());
 +              core::mem::drop(deserialized_fwd_htlcs);
 +
 +              expect_pending_htlcs_forwardable!(nodes[0]);
 +      }
  }
  
  #[cfg(ldk_bench)]
index 5828ca8038ca241a8d8c6d96464cbe3555bfc1ef,eba30404f4d38ea73b73599fc769e18c93aca974..a2d9631716c4c23098135a8f95ee37a1fc5a6949
@@@ -1536,6 -1536,18 +1536,18 @@@ pub struct ExpectedCloseEvent 
        pub reason: Option<ClosureReason>,
  }
  
+ impl ExpectedCloseEvent {
+       pub fn from_id_reason(channel_id: ChannelId, discard_funding: bool, reason: ClosureReason) -> Self {
+               Self {
+                       channel_capacity_sats: None,
+                       channel_id: Some(channel_id),
+                       counterparty_node_id: None,
+                       discard_funding,
+                       reason: Some(reason),
+               }
+       }
+ }
  /// Check that multiple channel closing events have been issued.
  pub fn check_closed_events(node: &Node, expected_close_events: &[ExpectedCloseEvent]) {
        let closed_events_count = expected_close_events.len();
@@@ -1971,18 -1983,6 +1983,18 @@@ pub fn get_route(send_node: &Node, rout
        )
  }
  
 +/// Like `get_route` above, but adds a random CLTV offset to the final hop.
 +pub fn find_route(send_node: &Node, route_params: &RouteParameters) -> Result<Route, msgs::LightningError> {
 +      let scorer = TestScorer::new();
 +      let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
 +      let random_seed_bytes = keys_manager.get_secure_random_bytes();
 +      router::find_route(
 +              &send_node.node.get_our_node_id(), route_params, &send_node.network_graph,
 +              Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
 +              send_node.logger, &scorer, &Default::default(), &random_seed_bytes
 +      )
 +}
 +
  /// Gets a route from the given sender to the node described in `payment_params`.
  ///
  /// Don't use this, use the identically-named function instead.
index 5d8cc59978eb1d8f01379b47be6be41900aa8cd1,fca6abb35969ef25b3a929a6eed34a45db448784..2ad53faa8b2e129874cbec1391156ab58aabc6e5
@@@ -2273,15 -2273,9 +2273,15 @@@ fn channel_monitor_network_test() 
        nodes[1].node.force_close_broadcasting_latest_txn(&chan_1.2, &nodes[0].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[1], 1);
        check_closed_broadcast!(nodes[1], true);
 +      check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
        {
                let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
                assert_eq!(node_txn.len(), 1);
 +              mine_transaction(&nodes[1], &node_txn[0]);
 +              if nodes[1].connect_style.borrow().updates_best_block_first() {
 +                      let _ = nodes[1].tx_broadcaster.txn_broadcast();
 +              }
 +
                mine_transaction(&nodes[0], &node_txn[0]);
                check_added_monitors!(nodes[0], 1);
                test_txn_broadcast(&nodes[0], &chan_1, Some(node_txn[0].clone()), HTLCType::NONE);
        assert_eq!(nodes[0].node.list_channels().len(), 0);
        assert_eq!(nodes[1].node.list_channels().len(), 1);
        check_closed_event!(nodes[0], 1, ClosureReason::CommitmentTxConfirmed, [nodes[1].node.get_our_node_id()], 100000);
 -      check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
  
        // One pending HTLC is discarded by the force-close:
        let (payment_preimage_1, payment_hash_1, ..) = route_payment(&nodes[1], &[&nodes[2], &nodes[3]], 3_000_000);
@@@ -3561,7 -3556,7 +3561,7 @@@ fn test_htlc_ignore_latest_remote_commi
                // connect_style.
                return;
        }
 -      create_announced_chan_between_nodes(&nodes, 0, 1);
 +      let funding_tx = create_announced_chan_between_nodes(&nodes, 0, 1).3;
  
        route_payment(&nodes[0], &[&nodes[1]], 10000000);
        nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
        check_added_monitors!(nodes[0], 1);
        check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
  
 -      let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
 -      assert_eq!(node_txn.len(), 3);
 -      assert_eq!(node_txn[0].txid(), node_txn[1].txid());
 +      let node_txn = nodes[0].tx_broadcaster.unique_txn_broadcast();
 +      assert_eq!(node_txn.len(), 2);
 +      check_spends!(node_txn[0], funding_tx);
 +      check_spends!(node_txn[1], node_txn[0]);
  
 -      let block = create_dummy_block(nodes[1].best_block_hash(), 42, vec![node_txn[0].clone(), node_txn[1].clone()]);
 +      let block = create_dummy_block(nodes[1].best_block_hash(), 42, vec![node_txn[0].clone()]);
        connect_block(&nodes[1], &block);
        check_closed_broadcast!(nodes[1], true);
        check_added_monitors!(nodes[1], 1);
@@@ -3632,7 -3626,7 +3632,7 @@@ fn test_force_close_fail_back() 
        check_closed_broadcast!(nodes[2], true);
        check_added_monitors!(nodes[2], 1);
        check_closed_event!(nodes[2], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
 -      let tx = {
 +      let commitment_tx = {
                let mut node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
                // Note that we don't bother broadcasting the HTLC-Success transaction here as we don't
                // have a use for it unless nodes[2] learns the preimage somehow, the funds will go
                node_txn.remove(0)
        };
  
 -      mine_transaction(&nodes[1], &tx);
 +      mine_transaction(&nodes[1], &commitment_tx);
  
        // Note no UpdateHTLCs event here from nodes[1] to nodes[0]!
        check_closed_broadcast!(nodes[1], true);
                get_monitor!(nodes[2], payment_event.commitment_msg.channel_id)
                        .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &LowerBoundedFeeEstimator::new(node_cfgs[2].fee_estimator), &node_cfgs[2].logger);
        }
 -      mine_transaction(&nodes[2], &tx);
 -      let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
 -      assert_eq!(node_txn.len(), 1);
 -      assert_eq!(node_txn[0].input.len(), 1);
 -      assert_eq!(node_txn[0].input[0].previous_output.txid, tx.txid());
 -      assert_eq!(node_txn[0].lock_time, LockTime::ZERO); // Must be an HTLC-Success
 -      assert_eq!(node_txn[0].input[0].witness.len(), 5); // Must be an HTLC-Success
 +      mine_transaction(&nodes[2], &commitment_tx);
 +      let mut node_txn = nodes[2].tx_broadcaster.txn_broadcast();
 +      assert_eq!(node_txn.len(), if nodes[2].connect_style.borrow().updates_best_block_first() { 2 } else { 1 });
 +      let htlc_tx = node_txn.pop().unwrap();
 +      assert_eq!(htlc_tx.input.len(), 1);
 +      assert_eq!(htlc_tx.input[0].previous_output.txid, commitment_tx.txid());
 +      assert_eq!(htlc_tx.lock_time, LockTime::ZERO); // Must be an HTLC-Success
 +      assert_eq!(htlc_tx.input[0].witness.len(), 5); // Must be an HTLC-Success
  
 -      check_spends!(node_txn[0], tx);
 +      check_spends!(htlc_tx, commitment_tx);
  }
  
  #[test]
@@@ -8575,11 -8568,10 +8575,11 @@@ fn test_concurrent_monitor_claim() 
        watchtower_alice.chain_monitor.block_connected(&block, HTLC_TIMEOUT_BROADCAST);
  
        // Watchtower Alice should have broadcast a commitment/HTLC-timeout
 -      let alice_state = {
 +      {
                let mut txn = alice_broadcaster.txn_broadcast();
                assert_eq!(txn.len(), 2);
 -              txn.remove(0)
 +              check_spends!(txn[0], chan_1.3);
 +              check_spends!(txn[1], txn[0]);
        };
  
        // Copy ChainMonitor to simulate watchtower Bob and make it receive a commitment update first.
        check_added_monitors(&nodes[0], 1);
        {
                let htlc_txn = alice_broadcaster.txn_broadcast();
 -              assert_eq!(htlc_txn.len(), 2);
 +              assert_eq!(htlc_txn.len(), 1);
                check_spends!(htlc_txn[0], bob_state_y);
 -              // Alice doesn't clean up the old HTLC claim since it hasn't seen a conflicting spend for
 -              // it. However, she should, because it now has an invalid parent.
 -              check_spends!(htlc_txn[1], alice_state);
        }
  }
  
@@@ -8888,12 -8883,7 +8888,12 @@@ fn do_test_onchain_htlc_settlement_afte
                        assert_eq!(bob_txn.len(), 1);
                        check_spends!(bob_txn[0], txn_to_broadcast[0]);
                } else {
 -                      assert_eq!(bob_txn.len(), 2);
 +                      if nodes[1].connect_style.borrow().updates_best_block_first() {
 +                              assert_eq!(bob_txn.len(), 3);
 +                              assert_eq!(bob_txn[0].txid(), bob_txn[1].txid());
 +                      } else {
 +                              assert_eq!(bob_txn.len(), 2);
 +                      }
                        check_spends!(bob_txn[0], chan_ab.3);
                }
        }
                // If Alice force-closed, Bob only broadcasts a HTLC-output-claiming transaction. Otherwise,
                // Bob force-closed and broadcasts the commitment transaction along with a
                // HTLC-output-claiming transaction.
 -              let bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
 +              let mut bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
                if broadcast_alice {
                        assert_eq!(bob_txn.len(), 1);
                        check_spends!(bob_txn[0], txn_to_broadcast[0]);
                        assert_eq!(bob_txn[0].input[0].witness.last().unwrap().len(), script_weight);
                } else {
 -                      assert_eq!(bob_txn.len(), 2);
 -                      check_spends!(bob_txn[1], txn_to_broadcast[0]);
 -                      assert_eq!(bob_txn[1].input[0].witness.last().unwrap().len(), script_weight);
 +                      assert_eq!(bob_txn.len(), if nodes[1].connect_style.borrow().updates_best_block_first() { 3 } else { 2 });
 +                      let htlc_tx = bob_txn.pop().unwrap();
 +                      check_spends!(htlc_tx, txn_to_broadcast[0]);
 +                      assert_eq!(htlc_tx.input[0].witness.last().unwrap().len(), script_weight);
                }
        }
  }
@@@ -8981,6 -8970,54 +8981,54 @@@ fn test_duplicate_temporary_channel_id_
        }
  }
  
+ #[test]
+ fn test_duplicate_funding_err_in_funding() {
+       // Test that if we have a live channel with one peer, then another peer comes along and tries
+       // to create a second channel with the same txid we'll fail and not overwrite the
+       // outpoint_to_peer map in `ChannelManager`.
+       //
+       // This was previously broken.
+       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 nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       let (_, _, _, real_channel_id, funding_tx) = create_chan_between_nodes(&nodes[0], &nodes[1]);
+       let real_chan_funding_txo = chain::transaction::OutPoint { txid: funding_tx.txid(), index: 0 };
+       assert_eq!(real_chan_funding_txo.to_channel_id(), real_channel_id);
+       nodes[2].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap();
+       let mut open_chan_msg = get_event_msg!(nodes[2], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+       let node_c_temp_chan_id = open_chan_msg.temporary_channel_id;
+       open_chan_msg.temporary_channel_id = real_channel_id;
+       nodes[1].node.handle_open_channel(&nodes[2].node.get_our_node_id(), &open_chan_msg);
+       let mut accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[2].node.get_our_node_id());
+       accept_chan_msg.temporary_channel_id = node_c_temp_chan_id;
+       nodes[2].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_chan_msg);
+       // Now that we have a second channel with the same funding txo, send a bogus funding message
+       // and let nodes[1] remove the inbound channel.
+       let (_, funding_tx, _) = create_funding_transaction(&nodes[2], &nodes[1].node.get_our_node_id(), 100_000, 42);
+       nodes[2].node.funding_transaction_generated(&node_c_temp_chan_id, &nodes[1].node.get_our_node_id(), funding_tx).unwrap();
+       let mut funding_created_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
+       funding_created_msg.temporary_channel_id = real_channel_id;
+       // Make the signature invalid by changing the funding output
+       funding_created_msg.funding_output_index += 10;
+       nodes[1].node.handle_funding_created(&nodes[2].node.get_our_node_id(), &funding_created_msg);
+       get_err_msg(&nodes[1], &nodes[2].node.get_our_node_id());
+       let err = "Invalid funding_created signature from peer".to_owned();
+       let reason = ClosureReason::ProcessingError { err };
+       let expected_closing = ExpectedCloseEvent::from_id_reason(real_channel_id, false, reason);
+       check_closed_events(&nodes[1], &[expected_closing]);
+       assert_eq!(
+               *nodes[1].node.outpoint_to_peer.lock().unwrap().get(&real_chan_funding_txo).unwrap(),
+               nodes[0].node.get_our_node_id()
+       );
+ }
  #[test]
  fn test_duplicate_chan_id() {
        // Test that if a given peer tries to open a channel with the same channel_id as one that is
        // without trying to persist the `ChannelMonitor`.
        check_added_monitors!(nodes[1], 0);
  
+       check_closed_events(&nodes[1], &[
+               ExpectedCloseEvent::from_id_reason(channel_id, false, ClosureReason::ProcessingError {
+                       err: "Already had channel with the new channel_id".to_owned()
+               })
+       ]);
        // ...still, nodes[1] will reject the duplicate channel.
        {
                let events = nodes[1].node.get_and_clear_pending_msg_events();
@@@ -9394,12 -9437,8 +9448,12 @@@ fn do_test_tx_confirmed_skipping_blocks
                // We should broadcast an HTLC transaction spending our funding transaction first
                let spending_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
                assert_eq!(spending_txn.len(), 2);
 -              assert_eq!(spending_txn[0].txid(), node_txn[0].txid());
 -              check_spends!(spending_txn[1], node_txn[0]);
 +              let htlc_tx = if spending_txn[0].txid() == node_txn[0].txid() {
 +                      &spending_txn[1]
 +              } else {
 +                      &spending_txn[0]
 +              };
 +              check_spends!(htlc_tx, node_txn[0]);
                // We should also generate a SpendableOutputs event with the to_self output (as its
                // timelock is up).
                let descriptor_spend_txn = check_spendable_outputs!(nodes[1], node_cfgs[1].keys_manager);
                // should immediately fail-backwards the HTLC to the previous hop, without waiting for an
                // additional block built on top of the current chain.
                nodes[1].chain_monitor.chain_monitor.transactions_confirmed(
 -                      &nodes[1].get_block_header(conf_height + 1), &[(0, &spending_txn[1])], conf_height + 1);
 +                      &nodes[1].get_block_header(conf_height + 1), &[(0, htlc_tx)], conf_height + 1);
                expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: channel_id }]);
                check_added_monitors!(nodes[1], 1);