Skip to content

Commit b5aa36b

Browse files
committed
Create TrampolineForward HTLCSource variant [rephrase]
Primarily for error handling purposes
1 parent 02a39bf commit b5aa36b

File tree

3 files changed

+114
-2
lines changed

3 files changed

+114
-2
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,6 +2427,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
24272427
None => panic!("Outbound HTLCs should have a source"),
24282428
Some(&HTLCSource::PreviousHopData(_)) => false,
24292429
Some(&HTLCSource::OutboundRoute { .. }) => true,
2430+
Some(&HTLCSource::TrampolineForward { .. }) => false,
24302431
};
24312432
return Some(Balance::MaybeTimeoutClaimableHTLC {
24322433
amount_satoshis: htlc.amount_msat / 1000,
@@ -2641,6 +2642,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
26412642
None => panic!("Outbound HTLCs should have a source"),
26422643
Some(HTLCSource::PreviousHopData(_)) => false,
26432644
Some(HTLCSource::OutboundRoute { .. }) => true,
2645+
Some(HTLCSource::TrampolineForward { .. }) => false,
26442646
};
26452647
if outbound_payment {
26462648
outbound_payment_htlc_rounded_msat += rounded_value_msat;

lightning/src/ln/channelmanager.rs

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ impl Readable for InterceptId {
630630
pub(crate) enum SentHTLCId {
631631
PreviousHopData { short_channel_id: u64, htlc_id: u64 },
632632
OutboundRoute { session_priv: [u8; SECRET_KEY_SIZE] },
633+
TrampolineForward { session_priv: [u8; SECRET_KEY_SIZE], previous_short_channel_id: u64, htlc_id: u64 }
633634
}
634635
impl SentHTLCId {
635636
pub(crate) fn from_source(source: &HTLCSource) -> Self {
@@ -640,6 +641,11 @@ impl SentHTLCId {
640641
},
641642
HTLCSource::OutboundRoute { session_priv, .. } =>
642643
Self::OutboundRoute { session_priv: session_priv.secret_bytes() },
644+
HTLCSource::TrampolineForward { previous_hop_data, session_priv, .. } => Self::TrampolineForward {
645+
session_priv: session_priv.secret_bytes(),
646+
previous_short_channel_id: previous_hop_data.short_channel_id,
647+
htlc_id: previous_hop_data.htlc_id,
648+
},
643649
}
644650
}
645651
}
@@ -651,6 +657,11 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
651657
(2, OutboundRoute) => {
652658
(0, session_priv, required),
653659
},
660+
(4, TrampolineForward) => {
661+
(0, session_priv, required),
662+
(2, previous_short_channel_id, required),
663+
(4, htlc_id, required),
664+
},
654665
);
655666

656667
mod fuzzy_channelmanager {
@@ -661,6 +672,12 @@ mod fuzzy_channelmanager {
661672
#[derive(Clone, Debug, PartialEq, Eq)]
662673
pub enum HTLCSource {
663674
PreviousHopData(HTLCPreviousHopData),
675+
TrampolineForward {
676+
previous_hop_data: HTLCPreviousHopData,
677+
incoming_trampoline_shared_secret: [u8; 32],
678+
hops: Vec<RouteHop>,
679+
session_priv: SecretKey,
680+
},
664681
OutboundRoute {
665682
path: Path,
666683
session_priv: SecretKey,
@@ -712,6 +729,13 @@ impl core::hash::Hash for HTLCSource {
712729
payment_id.hash(hasher);
713730
first_hop_htlc_msat.hash(hasher);
714731
},
732+
HTLCSource::TrampolineForward { previous_hop_data, incoming_trampoline_shared_secret, hops, session_priv } => {
733+
2u8.hash(hasher);
734+
previous_hop_data.hash(hasher);
735+
incoming_trampoline_shared_secret.hash(hasher);
736+
hops.hash(hasher);
737+
session_priv[..].hash(hasher);
738+
},
715739
}
716740
}
717741
}
@@ -7113,6 +7137,61 @@ where
71137137
failed_next_destination: destination,
71147138
}, None));
71157139
},
7140+
HTLCSource::TrampolineForward { previous_hop_data, incoming_trampoline_shared_secret, .. } => {
7141+
// todo: what do we want to do with this given we do not wish to propagate it directly?
7142+
let _decoded_onion_failure = onion_error.decode_onion_failure(&self.secp_ctx, &self.logger, &source);
7143+
7144+
let incoming_packet_shared_secret = previous_hop_data.incoming_packet_shared_secret;
7145+
let channel_id = previous_hop_data.channel_id;
7146+
let short_channel_id = previous_hop_data.short_channel_id;
7147+
let htlc_id = previous_hop_data.htlc_id;
7148+
let blinded_failure = previous_hop_data.blinded_failure;
7149+
log_trace!(
7150+
WithContext::from(&self.logger, None, Some(channel_id), Some(*payment_hash)),
7151+
"Failing {}HTLC with payment_hash {} backwards from us following Trampoline forwarding failure: {:?}",
7152+
if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error
7153+
);
7154+
let failure = match blinded_failure {
7155+
Some(BlindedFailure::FromIntroductionNode) => {
7156+
let blinded_onion_error = HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32]);
7157+
let err_packet = blinded_onion_error.get_encrypted_failure_packet(
7158+
&incoming_packet_shared_secret, &Some(incoming_trampoline_shared_secret.clone())
7159+
);
7160+
HTLCForwardInfo::FailHTLC { htlc_id, err_packet }
7161+
},
7162+
Some(BlindedFailure::FromBlindedNode) => {
7163+
HTLCForwardInfo::FailMalformedHTLC {
7164+
htlc_id,
7165+
failure_code: INVALID_ONION_BLINDING,
7166+
sha256_of_onion: [0; 32]
7167+
}
7168+
},
7169+
None => {
7170+
let err_code = 0x2000 | 25;
7171+
let err_packet = HTLCFailReason::reason(err_code, Vec::new())
7172+
.get_encrypted_failure_packet(&incoming_packet_shared_secret, &Some(incoming_trampoline_shared_secret.clone()));
7173+
HTLCForwardInfo::FailHTLC { htlc_id, err_packet }
7174+
}
7175+
};
7176+
7177+
push_forward_event = self.decode_update_add_htlcs.lock().unwrap().is_empty();
7178+
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
7179+
push_forward_event &= forward_htlcs.is_empty();
7180+
match forward_htlcs.entry(short_channel_id) {
7181+
hash_map::Entry::Occupied(mut entry) => {
7182+
entry.get_mut().push(failure);
7183+
},
7184+
hash_map::Entry::Vacant(entry) => {
7185+
entry.insert(vec!(failure));
7186+
}
7187+
}
7188+
mem::drop(forward_htlcs);
7189+
let mut pending_events = self.pending_events.lock().unwrap();
7190+
pending_events.push_back((events::Event::HTLCHandlingFailed {
7191+
prev_channel_id: channel_id,
7192+
failed_next_destination: destination,
7193+
}, None));
7194+
},
71167195
}
71177196
push_forward_event
71187197
}
@@ -7517,7 +7596,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
75177596
session_priv, path, from_onchain, ev_completion_action, &self.pending_events,
75187597
&self.logger);
75197598
},
7520-
HTLCSource::PreviousHopData(hop_data) => {
7599+
HTLCSource::PreviousHopData(hop_data) | HTLCSource::TrampolineForward { previous_hop_data: hop_data, .. } => {
75217600
let prev_channel_id = hop_data.channel_id;
75227601
let prev_user_channel_id = hop_data.user_channel_id;
75237602
let prev_node_id = hop_data.counterparty_node_id;
@@ -13223,6 +13302,24 @@ impl Readable for HTLCSource {
1322313302
})
1322413303
}
1322513304
1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
13305+
2 => {
13306+
let mut previous_hop_data: crate::util::ser::RequiredWrapper<HTLCPreviousHopData> = crate::util::ser::RequiredWrapper(None);
13307+
let mut incoming_trampoline_shared_secret: crate::util::ser::RequiredWrapper<[u8; 32]> = crate::util::ser::RequiredWrapper(None);
13308+
let mut session_priv: crate::util::ser::RequiredWrapper<SecretKey> = crate::util::ser::RequiredWrapper(None);
13309+
let mut hops = Vec::new();
13310+
read_tlv_fields!(reader, {
13311+
(0, previous_hop_data, required),
13312+
(2, incoming_trampoline_shared_secret, required),
13313+
(4, session_priv, required),
13314+
(6, hops, required_vec),
13315+
});
13316+
Ok(HTLCSource::TrampolineForward {
13317+
previous_hop_data: previous_hop_data.0.unwrap(),
13318+
incoming_trampoline_shared_secret: incoming_trampoline_shared_secret.0.unwrap(),
13319+
hops,
13320+
session_priv: session_priv.0.unwrap(),
13321+
})
13322+
},
1322613323
_ => Err(DecodeError::UnknownRequiredFeature),
1322713324
}
1322813325
}
@@ -13248,6 +13345,16 @@ impl Writeable for HTLCSource {
1324813345
1u8.write(writer)?;
1324913346
field.write(writer)?;
1325013347
}
13348+
HTLCSource::TrampolineForward { ref previous_hop_data, ref incoming_trampoline_shared_secret, ref session_priv, hops: hops_ref } => {
13349+
2u8.write(writer)?;
13350+
let hops = hops_ref.clone();
13351+
write_tlv_fields!(writer, {
13352+
(0, previous_hop_data, required),
13353+
(2, incoming_trampoline_shared_secret, required),
13354+
(4, session_priv, required),
13355+
(6, hops, required_vec),
13356+
});
13357+
}
1325113358
}
1325213359
Ok(())
1325313360
}
@@ -14381,7 +14488,7 @@ where
1438114488
for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() {
1438214489
let logger = WithChannelMonitor::from(&args.logger, monitor, Some(htlc.payment_hash));
1438314490
match htlc_source {
14384-
HTLCSource::PreviousHopData(prev_hop_data) => {
14491+
HTLCSource::PreviousHopData(prev_hop_data) | HTLCSource::TrampolineForward { previous_hop_data: prev_hop_data, .. } => {
1438514492
let pending_forward_matches_htlc = |info: &PendingAddHTLCInfo| {
1438614493
info.prev_funding_outpoint == prev_hop_data.outpoint &&
1438714494
info.prev_htlc_id == prev_hop_data.htlc_id

lightning/src/ln/onion_utils.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,9 @@ where
10061006
{
10071007
let (path, primary_session_priv) = match htlc_source {
10081008
HTLCSource::OutboundRoute { ref path, ref session_priv, .. } => (path, session_priv),
1009+
HTLCSource::TrampolineForward { ref hops, ref session_priv, .. } => {
1010+
(&Path { hops: hops.clone(), blinded_tail: None }, session_priv)
1011+
},
10091012
_ => unreachable!(),
10101013
};
10111014

0 commit comments

Comments
 (0)