From b26480189e152784e1ff1f37e6519f83ad405e9f Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Wed, 6 Dec 2023 15:19:23 -0500 Subject: [PATCH] Support failing blinded non-intro HTLCs after RAA processing. If an HTLC fails after its RAA is processed, it is failed back with ChannelManager::fail_htlc_backwards_internal. This method will now correctly inform the channel that this HTLC is blinded and to construct an update_malformed message accordingly. --- lightning/src/ln/channel.rs | 11 +++++++++++ lightning/src/ln/channelmanager.rs | 23 ++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index a991c8eed..bac450768 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -2881,6 +2881,17 @@ impl Channel where .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( + &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 diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index aed58f84d..bf02015fa 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -4387,8 +4387,19 @@ where continue; } }, - HTLCForwardInfo::FailMalformedHTLC { .. } => { - todo!() + 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; + } }, } } @@ -5257,7 +5268,13 @@ where ); HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet } }, - Some(BlindedFailure::FromBlindedNode) => todo!(), + Some(BlindedFailure::FromBlindedNode) => { + HTLCForwardInfo::FailMalformedHTLC { + htlc_id: *htlc_id, + failure_code: INVALID_ONION_BLINDING, + sha256_of_onion: [0; 32] + } + }, None => { let err_packet = onion_error.get_encrypted_failure_packet( incoming_packet_shared_secret, phantom_shared_secret -- 2.39.5