Skip to content

Commit 80c6ad5

Browse files
committed
Fix trampoline error packet encryption using trampoline shared secret
When handling HTLC failures in trampoline routing, error packets were not being properly encrypted with the trampoline shared secret. This caused error messages to be unreadable by the original sender when failures occurred within trampoline hops. The fix prioritizes trampoline_shared_secret over phantom_shared_secret when both are available, ensuring error packets can be properly decrypted by trampoline senders.
1 parent c997f22 commit 80c6ad5

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ pub enum PendingHTLCRouting {
277277
/// provide the onion shared secret used to decrypt the next level of forwarding
278278
/// instructions.
279279
phantom_shared_secret: Option<[u8; 32]>,
280+
/// If the onion had trampoline forwarding instruction to our node.
281+
/// This will provice the onion shared secret to encrypt error packets to the sender.
282+
trampoline_shared_secret: Option<[u8; 32]>,
280283
/// Custom TLVs which were set by the sender.
281284
///
282285
/// For HTLCs received by LDK, this will ultimately be exposed in
@@ -466,6 +469,13 @@ impl PendingAddHTLCInfo {
466469
PendingHTLCRouting::Receive { phantom_shared_secret, .. } => phantom_shared_secret,
467470
_ => None,
468471
};
472+
let trampoline_shared_secret = match self.forward_info.routing {
473+
PendingHTLCRouting::Receive { trampoline_shared_secret, .. } => {
474+
trampoline_shared_secret
475+
},
476+
_ => None,
477+
};
478+
469479
HTLCPreviousHopData {
470480
short_channel_id: self.prev_short_channel_id,
471481
user_channel_id: Some(self.prev_user_channel_id),
@@ -475,6 +485,7 @@ impl PendingAddHTLCInfo {
475485
htlc_id: self.prev_htlc_id,
476486
incoming_packet_shared_secret: self.forward_info.incoming_shared_secret,
477487
phantom_shared_secret,
488+
trampoline_shared_secret,
478489
blinded_failure: self.forward_info.routing.blinded_failure(),
479490
cltv_expiry: self.forward_info.routing.incoming_cltv_expiry(),
480491
}
@@ -798,6 +809,7 @@ mod fuzzy_channelmanager {
798809
pub htlc_id: u64,
799810
pub incoming_packet_shared_secret: [u8; 32],
800811
pub phantom_shared_secret: Option<[u8; 32]>,
812+
pub trampoline_shared_secret: Option<[u8; 32]>,
801813
pub blinded_failure: Option<BlindedFailure>,
802814
pub channel_id: ChannelId,
803815

@@ -7276,13 +7288,15 @@ where
72767288
mut onion_fields,
72777289
has_recipient_created_payment_secret,
72787290
invoice_request_opt,
7291+
trampoline_shared_secret,
72797292
) = match routing {
72807293
PendingHTLCRouting::Receive {
72817294
payment_data,
72827295
payment_metadata,
72837296
payment_context,
72847297
incoming_cltv_expiry,
72857298
phantom_shared_secret,
7299+
trampoline_shared_secret,
72867300
custom_tlvs,
72877301
requires_blinded_error: _,
72887302
} => {
@@ -7301,6 +7315,7 @@ where
73017315
onion_fields,
73027316
true,
73037317
None,
7318+
trampoline_shared_secret,
73047319
)
73057320
},
73067321
PendingHTLCRouting::ReceiveKeysend {
@@ -7330,6 +7345,7 @@ where
73307345
onion_fields,
73317346
has_recipient_created_payment_secret,
73327347
invoice_request,
7348+
None,
73337349
)
73347350
},
73357351
_ => {
@@ -7377,6 +7393,7 @@ where
73777393
htlc_id: $htlc.prev_hop.htlc_id,
73787394
incoming_packet_shared_secret,
73797395
phantom_shared_secret,
7396+
trampoline_shared_secret,
73807397
blinded_failure,
73817398
cltv_expiry: Some(cltv_expiry),
73827399
}),
@@ -8176,6 +8193,7 @@ where
81768193
ref htlc_id,
81778194
ref incoming_packet_shared_secret,
81788195
ref phantom_shared_secret,
8196+
ref trampoline_shared_secret,
81798197
outpoint: _,
81808198
ref blinded_failure,
81818199
ref channel_id,
@@ -8188,6 +8206,7 @@ where
81888206
&payment_hash,
81898207
onion_error
81908208
);
8209+
let secondary_shared_secret = trampoline_shared_secret.or(*phantom_shared_secret);
81918210
let failure = match blinded_failure {
81928211
Some(BlindedFailure::FromIntroductionNode) => {
81938212
let blinded_onion_error = HTLCFailReason::reason(
@@ -8196,7 +8215,7 @@ where
81968215
);
81978216
let err_packet = blinded_onion_error.get_encrypted_failure_packet(
81988217
incoming_packet_shared_secret,
8199-
phantom_shared_secret,
8218+
&secondary_shared_secret,
82008219
);
82018220
HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet }
82028221
},
@@ -8208,7 +8227,7 @@ where
82088227
None => {
82098228
let err_packet = onion_error.get_encrypted_failure_packet(
82108229
incoming_packet_shared_secret,
8211-
phantom_shared_secret,
8230+
&secondary_shared_secret,
82128231
);
82138232
HTLCForwardInfo::FailHTLC { htlc_id: *htlc_id, err_packet }
82148233
},
@@ -15173,6 +15192,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
1517315192
(5, custom_tlvs, optional_vec),
1517415193
(7, requires_blinded_error, (default_value, false)),
1517515194
(9, payment_context, option),
15195+
(11, trampoline_shared_secret, option),
1517615196
},
1517715197
(2, ReceiveKeysend) => {
1517815198
(0, payment_preimage, required),
@@ -15301,6 +15321,7 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
1530115321
// filled in, so we can safely unwrap it here.
1530215322
(9, channel_id, (default_value, ChannelId::v1_from_funding_outpoint(outpoint.0.unwrap()))),
1530315323
(11, counterparty_node_id, option),
15324+
(13, trampoline_shared_secret, option),
1530415325
});
1530515326

1530615327
impl Writeable for ClaimableHTLC {

lightning/src/ln/onion_payment.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,14 @@ pub(super) fn create_recv_pending_htlc_info(
253253
let (
254254
payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry,
255255
payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret,
256-
invoice_request
256+
invoice_request, trampoline_shared_secret,
257257
) = match hop_data {
258258
onion_utils::Hop::Receive { hop_data: msgs::InboundOnionReceivePayload {
259259
payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
260260
cltv_expiry_height, payment_metadata, ..
261261
}, .. } =>
262262
(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
263-
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
263+
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None, None),
264264
onion_utils::Hop::BlindedReceive { hop_data: msgs::InboundOnionBlindedReceivePayload {
265265
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
266266
intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
@@ -279,17 +279,19 @@ pub(super) fn create_recv_pending_htlc_info(
279279
let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
280280
(Some(payment_data), keysend_preimage, custom_tlvs,
281281
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
282-
intro_node_blinding_point.is_none(), true, invoice_request)
282+
intro_node_blinding_point.is_none(), true, invoice_request, None)
283283
}
284284
onion_utils::Hop::TrampolineReceive {
285+
trampoline_shared_secret,
285286
trampoline_hop_data: msgs::InboundOnionReceivePayload {
286287
payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
287288
cltv_expiry_height, payment_metadata, ..
288289
}, ..
289290
} =>
290291
(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
291-
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
292+
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None, Some(trampoline_shared_secret.secret_bytes())),
292293
onion_utils::Hop::TrampolineBlindedReceive {
294+
trampoline_shared_secret,
293295
trampoline_hop_data: msgs::InboundOnionBlindedReceivePayload {
294296
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
295297
intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
@@ -309,7 +311,7 @@ pub(super) fn create_recv_pending_htlc_info(
309311
let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
310312
(Some(payment_data), keysend_preimage, custom_tlvs,
311313
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
312-
intro_node_blinding_point.is_none(), true, invoice_request)
314+
intro_node_blinding_point.is_none(), true, invoice_request, Some(trampoline_shared_secret.secret_bytes()))
313315
},
314316
onion_utils::Hop::Forward { .. } => {
315317
return Err(InboundHTLCErr {
@@ -398,6 +400,7 @@ pub(super) fn create_recv_pending_htlc_info(
398400
payment_context,
399401
incoming_cltv_expiry: onion_cltv_expiry,
400402
phantom_shared_secret,
403+
trampoline_shared_secret,
401404
custom_tlvs,
402405
requires_blinded_error,
403406
}

lightning/src/ln/onion_utils.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,7 +2195,6 @@ pub(crate) enum Hop {
21952195
outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
21962196
outer_shared_secret: SharedSecret,
21972197
trampoline_hop_data: msgs::InboundOnionReceivePayload,
2198-
#[allow(unused)]
21992198
trampoline_shared_secret: SharedSecret,
22002199
},
22012200
/// This onion payload was for us, not for forwarding to a next-hop, and it was sent to us via
@@ -2205,7 +2204,6 @@ pub(crate) enum Hop {
22052204
outer_hop_data: msgs::InboundTrampolineEntrypointPayload,
22062205
outer_shared_secret: SharedSecret,
22072206
trampoline_hop_data: msgs::InboundOnionBlindedReceivePayload,
2208-
#[allow(unused)]
22092207
trampoline_shared_secret: SharedSecret,
22102208
},
22112209
}

0 commit comments

Comments
 (0)