@@ -630,6 +630,7 @@ impl Readable for InterceptId {
630
630
pub(crate) enum SentHTLCId {
631
631
PreviousHopData { short_channel_id: u64, htlc_id: u64 },
632
632
OutboundRoute { session_priv: [u8; SECRET_KEY_SIZE] },
633
+ TrampolineForward { session_priv: [u8; SECRET_KEY_SIZE], previous_short_channel_id: u64, htlc_id: u64 }
633
634
}
634
635
impl SentHTLCId {
635
636
pub(crate) fn from_source(source: &HTLCSource) -> Self {
@@ -640,6 +641,11 @@ impl SentHTLCId {
640
641
},
641
642
HTLCSource::OutboundRoute { session_priv, .. } =>
642
643
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
+ },
643
649
}
644
650
}
645
651
}
@@ -651,6 +657,11 @@ impl_writeable_tlv_based_enum!(SentHTLCId,
651
657
(2, OutboundRoute) => {
652
658
(0, session_priv, required),
653
659
},
660
+ (4, TrampolineForward) => {
661
+ (0, session_priv, required),
662
+ (2, previous_short_channel_id, required),
663
+ (4, htlc_id, required),
664
+ },
654
665
);
655
666
656
667
mod fuzzy_channelmanager {
@@ -661,6 +672,12 @@ mod fuzzy_channelmanager {
661
672
#[derive(Clone, Debug, PartialEq, Eq)]
662
673
pub enum HTLCSource {
663
674
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
+ },
664
681
OutboundRoute {
665
682
path: Path,
666
683
session_priv: SecretKey,
@@ -712,6 +729,13 @@ impl core::hash::Hash for HTLCSource {
712
729
payment_id.hash(hasher);
713
730
first_hop_htlc_msat.hash(hasher);
714
731
},
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
+ },
715
739
}
716
740
}
717
741
}
@@ -7113,6 +7137,61 @@ where
7113
7137
failed_next_destination: destination,
7114
7138
}, None));
7115
7139
},
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
+ },
7116
7195
}
7117
7196
push_forward_event
7118
7197
}
@@ -7517,7 +7596,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
7517
7596
session_priv, path, from_onchain, ev_completion_action, &self.pending_events,
7518
7597
&self.logger);
7519
7598
},
7520
- HTLCSource::PreviousHopData(hop_data) => {
7599
+ HTLCSource::PreviousHopData(hop_data) | HTLCSource::TrampolineForward { previous_hop_data: hop_data, .. } => {
7521
7600
let prev_channel_id = hop_data.channel_id;
7522
7601
let prev_user_channel_id = hop_data.user_channel_id;
7523
7602
let prev_node_id = hop_data.counterparty_node_id;
@@ -13223,6 +13302,24 @@ impl Readable for HTLCSource {
13223
13302
})
13224
13303
}
13225
13304
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
+ },
13226
13323
_ => Err(DecodeError::UnknownRequiredFeature),
13227
13324
}
13228
13325
}
@@ -13248,6 +13345,16 @@ impl Writeable for HTLCSource {
13248
13345
1u8.write(writer)?;
13249
13346
field.write(writer)?;
13250
13347
}
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
+ }
13251
13358
}
13252
13359
Ok(())
13253
13360
}
@@ -14381,7 +14488,7 @@ where
14381
14488
for (htlc_source, (htlc, preimage_opt)) in monitor.get_all_current_outbound_htlcs() {
14382
14489
let logger = WithChannelMonitor::from(&args.logger, monitor, Some(htlc.payment_hash));
14383
14490
match htlc_source {
14384
- HTLCSource::PreviousHopData(prev_hop_data) => {
14491
+ HTLCSource::PreviousHopData(prev_hop_data) | HTLCSource::TrampolineForward { previous_hop_data: prev_hop_data, .. } => {
14385
14492
let pending_forward_matches_htlc = |info: &PendingAddHTLCInfo| {
14386
14493
info.prev_funding_outpoint == prev_hop_data.outpoint &&
14387
14494
info.prev_htlc_id == prev_hop_data.htlc_id
0 commit comments