Skip to content

Commit d7b6314

Browse files
committed
Create TrampolineForward HTLCSource variant [rephrase]
Primarily for error handling purposes
1 parent 9bf1001 commit d7b6314

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
24322432
None => panic!("Outbound HTLCs should have a source"),
24332433
Some(&HTLCSource::PreviousHopData(_)) => false,
24342434
Some(&HTLCSource::OutboundRoute { .. }) => true,
2435+
Some(&HTLCSource::TrampolineForward { .. }) => false,
24352436
};
24362437
return Some(Balance::MaybeTimeoutClaimableHTLC {
24372438
amount_satoshis: htlc.amount_msat / 1000,
@@ -2646,6 +2647,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
26462647
None => panic!("Outbound HTLCs should have a source"),
26472648
Some(HTLCSource::PreviousHopData(_)) => false,
26482649
Some(HTLCSource::OutboundRoute { .. }) => true,
2650+
Some(HTLCSource::TrampolineForward { .. }) => false,
26492651
};
26502652
if outbound_payment {
26512653
outbound_payment_htlc_rounded_msat += rounded_value_msat;

lightning/src/ln/channelmanager.rs

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use crate::ln::channel_state::ChannelDetails;
5656
use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
5757
#[cfg(any(feature = "_test_utils", test))]
5858
use crate::types::features::Bolt11InvoiceFeatures;
59-
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, RouteParameters, RouteParametersConfig, Router, FixedRouter, Route};
59+
use crate::routing::router::{BlindedTail, FixedRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteHop, RouteParameters, RouteParametersConfig, Router};
6060
use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, HopConnector, InboundHTLCErr, NextPacketDetails};
6161
use crate::ln::msgs;
6262
use crate::ln::onion_utils::{self};
@@ -628,6 +628,7 @@ impl Readable for InterceptId {
628628
pub(crate) enum SentHTLCId {
629629
PreviousHopData { short_channel_id: u64, htlc_id: u64 },
630630
OutboundRoute { session_priv: [u8; SECRET_KEY_SIZE] },
631+
TrampolineForward { session_priv: [u8; SECRET_KEY_SIZE], previous_short_channel_id: u64, htlc_id: u64 }
631632
}
632633
impl SentHTLCId {
633634
pub(crate) fn from_source(source: &HTLCSource) -> Self {
@@ -638,6 +639,11 @@ impl SentHTLCId {
638639
},
639640
HTLCSource::OutboundRoute { session_priv, .. } =>
640641
Self::OutboundRoute { session_priv: session_priv.secret_bytes() },
642+
HTLCSource::TrampolineForward { previous_hop_data, session_priv, .. } => Self::TrampolineForward {
643+
session_priv: session_priv.secret_bytes(),
644+
previous_short_channel_id: previous_hop_data.short_channel_id,
645+
htlc_id: previous_hop_data.htlc_id,
646+
},
641647
}
642648
}
643649
}
@@ -649,6 +655,11 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
649655
(2, OutboundRoute) => {
650656
(0, session_priv, required),
651657
},
658+
(4, TrampolineForward) => {
659+
(0, session_priv, required),
660+
(2, previous_short_channel_id, required),
661+
(4, htlc_id, required),
662+
},
652663
);
653664

654665
mod fuzzy_channelmanager {
@@ -659,6 +670,12 @@ mod fuzzy_channelmanager {
659670
#[derive(Clone, Debug, PartialEq, Eq)]
660671
pub enum HTLCSource {
661672
PreviousHopData(HTLCPreviousHopData),
673+
TrampolineForward {
674+
previous_hop_data: HTLCPreviousHopData,
675+
incoming_trampoline_shared_secret: [u8; 32],
676+
hops: Vec<RouteHop>,
677+
session_priv: SecretKey,
678+
},
662679
OutboundRoute {
663680
path: Path,
664681
session_priv: SecretKey,
@@ -710,6 +727,13 @@ impl core::hash::Hash for HTLCSource {
710727
payment_id.hash(hasher);
711728
first_hop_htlc_msat.hash(hasher);
712729
},
730+
HTLCSource::TrampolineForward { previous_hop_data, incoming_trampoline_shared_secret, hops, session_priv } => {
731+
2u8.hash(hasher);
732+
previous_hop_data.hash(hasher);
733+
incoming_trampoline_shared_secret.hash(hasher);
734+
hops.hash(hasher);
735+
session_priv[..].hash(hasher);
736+
},
713737
}
714738
}
715739
}
@@ -7067,6 +7091,61 @@ where
70677091
failed_next_destination: destination,
70687092
}, None));
70697093
},
7094+
HTLCSource::TrampolineForward { previous_hop_data, incoming_trampoline_shared_secret, .. } => {
7095+
// todo: what do we want to do with this given we do not wish to propagate it directly?
7096+
let _decoded_onion_failure = onion_error.decode_onion_failure(&self.secp_ctx, &self.logger, &source);
7097+
7098+
let incoming_packet_shared_secret = previous_hop_data.incoming_packet_shared_secret;
7099+
let channel_id = previous_hop_data.channel_id;
7100+
let short_channel_id = previous_hop_data.short_channel_id;
7101+
let htlc_id = previous_hop_data.htlc_id;
7102+
let blinded_failure = previous_hop_data.blinded_failure;
7103+
log_trace!(
7104+
WithContext::from(&self.logger, None, Some(channel_id), Some(*payment_hash)),
7105+
"Failing {}HTLC with payment_hash {} backwards from us following Trampoline forwarding failure: {:?}",
7106+
if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error
7107+
);
7108+
let failure = match blinded_failure {
7109+
Some(BlindedFailure::FromIntroductionNode) => {
7110+
let blinded_onion_error = HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32]);
7111+
let err_packet = blinded_onion_error.get_encrypted_failure_packet(
7112+
&incoming_packet_shared_secret, &Some(incoming_trampoline_shared_secret.clone())
7113+
);
7114+
HTLCForwardInfo::FailHTLC { htlc_id, err_packet }
7115+
},
7116+
Some(BlindedFailure::FromBlindedNode) => {
7117+
HTLCForwardInfo::FailMalformedHTLC {
7118+
htlc_id,
7119+
failure_code: INVALID_ONION_BLINDING,
7120+
sha256_of_onion: [0; 32]
7121+
}
7122+
},
7123+
None => {
7124+
let err_code = 0x2000 | 25;
7125+
let err_packet = HTLCFailReason::reason(err_code, Vec::new())
7126+
.get_encrypted_failure_packet(&incoming_packet_shared_secret, &Some(incoming_trampoline_shared_secret.clone()));
7127+
HTLCForwardInfo::FailHTLC { htlc_id, err_packet }
7128+
}
7129+
};
7130+
7131+
push_forward_event = self.decode_update_add_htlcs.lock().unwrap().is_empty();
7132+
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
7133+
push_forward_event &= forward_htlcs.is_empty();
7134+
match forward_htlcs.entry(short_channel_id) {
7135+
hash_map::Entry::Occupied(mut entry) => {
7136+
entry.get_mut().push(failure);
7137+
},
7138+
hash_map::Entry::Vacant(entry) => {
7139+
entry.insert(vec!(failure));
7140+
}
7141+
}
7142+
mem::drop(forward_htlcs);
7143+
let mut pending_events = self.pending_events.lock().unwrap();
7144+
pending_events.push_back((events::Event::HTLCHandlingFailed {
7145+
prev_channel_id: channel_id,
7146+
failed_next_destination: destination,
7147+
}, None));
7148+
},
70707149
}
70717150
push_forward_event
70727151
}
@@ -7471,7 +7550,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
74717550
session_priv, path, from_onchain, ev_completion_action, &self.pending_events,
74727551
&self.logger);
74737552
},
7474-
HTLCSource::PreviousHopData(hop_data) => {
7553+
HTLCSource::PreviousHopData(hop_data) | HTLCSource::TrampolineForward { previous_hop_data: hop_data, .. } => {
74757554
let prev_channel_id = hop_data.channel_id;
74767555
let prev_user_channel_id = hop_data.user_channel_id;
74777556
let prev_node_id = hop_data.counterparty_node_id;
@@ -13176,6 +13255,24 @@ impl Readable for HTLCSource {
1317613255
})
1317713256
}
1317813257
1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
13258+
2 => {
13259+
let mut previous_hop_data: crate::util::ser::RequiredWrapper<HTLCPreviousHopData> = crate::util::ser::RequiredWrapper(None);
13260+
let mut incoming_trampoline_shared_secret: crate::util::ser::RequiredWrapper<[u8; 32]> = crate::util::ser::RequiredWrapper(None);
13261+
let mut session_priv: crate::util::ser::RequiredWrapper<SecretKey> = crate::util::ser::RequiredWrapper(None);
13262+
let mut hops = Vec::new();
13263+
read_tlv_fields!(reader, {
13264+
(0, previous_hop_data, required),
13265+
(2, incoming_trampoline_shared_secret, required),
13266+
(4, session_priv, required),
13267+
(6, hops, required_vec),
13268+
});
13269+
Ok(HTLCSource::TrampolineForward {
13270+
previous_hop_data: previous_hop_data.0.unwrap(),
13271+
incoming_trampoline_shared_secret: incoming_trampoline_shared_secret.0.unwrap(),
13272+
hops,
13273+
session_priv: session_priv.0.unwrap(),
13274+
})
13275+
},
1317913276
_ => Err(DecodeError::UnknownRequiredFeature),
1318013277
}
1318113278
}
@@ -13201,6 +13298,16 @@ impl Writeable for HTLCSource {
1320113298
1u8.write(writer)?;
1320213299
field.write(writer)?;
1320313300
}
13301+
HTLCSource::TrampolineForward { ref previous_hop_data, ref incoming_trampoline_shared_secret, ref session_priv, hops: hops_ref } => {
13302+
2u8.write(writer)?;
13303+
let hops = hops_ref.clone();
13304+
write_tlv_fields!(writer, {
13305+
(0, previous_hop_data, required),
13306+
(2, incoming_trampoline_shared_secret, required),
13307+
(4, session_priv, required),
13308+
(6, hops, required_vec),
13309+
});
13310+
}
1320413311
}
1320513312
Ok(())
1320613313
}
@@ -14334,7 +14441,7 @@ where
1433414441
for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() {
1433514442
let logger = WithChannelMonitor::from(&args.logger, monitor, Some(htlc.payment_hash));
1433614443
match htlc_source {
14337-
HTLCSource::PreviousHopData(prev_hop_data) => {
14444+
HTLCSource::PreviousHopData(prev_hop_data) | HTLCSource::TrampolineForward { previous_hop_data: prev_hop_data, .. } => {
1433814445
let pending_forward_matches_htlc = |info: &PendingAddHTLCInfo| {
1433914446
info.prev_funding_outpoint == prev_hop_data.outpoint &&
1434014447
info.prev_htlc_id == prev_hop_data.htlc_id

lightning/src/ln/onion_utils.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,13 @@ pub fn process_onion_failure<T: secp256k1::Signing, L: Deref>(
10041004
where
10051005
L::Target: Logger,
10061006
{
1007+
let mut trampoline_forward_path_option = None;
10071008
let (path, primary_session_priv) = match htlc_source {
10081009
HTLCSource::OutboundRoute { ref path, ref session_priv, .. } => (path, session_priv),
1010+
HTLCSource::TrampolineForward { ref hops, ref session_priv, .. } => {
1011+
trampoline_forward_path_option.replace(Path { hops: hops.clone(), blinded_tail: None });
1012+
(trampoline_forward_path_option.as_ref().unwrap(), session_priv)
1013+
},
10091014
_ => unreachable!(),
10101015
};
10111016

0 commit comments

Comments
 (0)