Skip to content

Commit 3013c22

Browse files
committed
Decrypt Trampoline onions
In this commit, we start decrypting the inner onion we receive, and lay some groundwork towards handling the subsequent routing or payment receipt.
1 parent 4a10d2a commit 3013c22

File tree

3 files changed

+302
-33
lines changed

3 files changed

+302
-33
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4479,11 +4479,36 @@ where
44794479
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44804480
}
44814481
},
4482+
#[cfg(trampoline)]
4483+
onion_utils::Hop::TrampolineReceive { .. } => {
4484+
// OUR PAYMENT!
4485+
let current_height: u32 = self.best_block.read().unwrap().height;
4486+
match create_recv_pending_htlc_info(decoded_hop, shared_secret, msg.payment_hash,
4487+
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
4488+
current_height)
4489+
{
4490+
Ok(info) => {
4491+
// Note that we could obviously respond immediately with an update_fulfill_htlc
4492+
// message, however that would leak that we are the recipient of this payment, so
4493+
// instead we stay symmetric with the forwarding case, only responding (after a
4494+
// delay) once they've sent us a commitment_signed!
4495+
PendingHTLCStatus::Forward(info)
4496+
},
4497+
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4498+
}
4499+
},
44824500
onion_utils::Hop::Forward { .. } | onion_utils::Hop::BlindedForward { .. } => {
44834501
match create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) {
44844502
Ok(info) => PendingHTLCStatus::Forward(info),
44854503
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44864504
}
4505+
},
4506+
#[cfg(trampoline)]
4507+
onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => {
4508+
match create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) {
4509+
Ok(info) => PendingHTLCStatus::Forward(info),
4510+
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4511+
}
44874512
}
44884513
}
44894514
}
@@ -5895,7 +5920,7 @@ where
58955920
// of the onion.
58965921
failed_payment!(err_msg, err_code, sha256_of_onion.to_vec(), None);
58975922
},
5898-
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret }) => {
5923+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret, .. }) => {
58995924
let phantom_shared_secret = shared_secret.secret_bytes();
59005925
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
59015926
},

lightning/src/ln/onion_payment.rs

Lines changed: 144 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use bitcoin::hashes::Hash;
77
use bitcoin::hashes::sha256::Hash as Sha256;
8-
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
8+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, ecdh::SharedSecret};
99

1010
use crate::blinded_path;
1111
use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
@@ -15,7 +15,7 @@ use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWA
1515
use crate::types::features::BlindedHopFeatures;
1616
use crate::ln::msgs;
1717
use crate::ln::onion_utils;
18-
use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
18+
use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING, ONION_DATA_LEN};
1919
use crate::routing::gossip::NodeId;
2020
use crate::sign::{NodeSigner, Recipient};
2121
use crate::util::logger::Logger;
@@ -61,20 +61,36 @@ fn check_blinded_forward(
6161
Ok((amt_to_forward, outgoing_cltv_value))
6262
}
6363

64+
enum RoutingInfo {
65+
Direct {
66+
short_channel_id: u64,
67+
new_packet_bytes: [u8; ONION_DATA_LEN],
68+
next_hop_hmac: [u8; 32]
69+
},
70+
#[cfg(trampoline)]
71+
Trampoline {
72+
outgoing_node_id: NodeId,
73+
// Trampoline onions are currently variable length
74+
new_packet_bytes: Vec<u8>,
75+
next_hop_hmac: [u8; 32],
76+
shared_secret: SharedSecret
77+
}
78+
}
79+
6480
pub(super) fn create_fwd_pending_htlc_info(
6581
msg: &msgs::UpdateAddHTLC, hop_data: onion_utils::Hop, shared_secret: [u8; 32],
6682
next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
6783
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
6884
debug_assert!(next_packet_pubkey_opt.is_some());
6985

7086
let (
71-
short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
72-
next_blinding_override, new_packet_bytes, next_hop_hmac
87+
routing_info, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
88+
next_blinding_override
7389
) = match hop_data {
7490
onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload {
7591
short_channel_id, amt_to_forward, outgoing_cltv_value
7692
}, new_packet_bytes, next_hop_hmac, .. } =>
77-
(short_channel_id, amt_to_forward, outgoing_cltv_value, None, None, new_packet_bytes, next_hop_hmac),
93+
(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, None, None),
7894
onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload {
7995
short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
8096
next_blinding_override,
@@ -90,38 +106,115 @@ pub(super) fn create_fwd_pending_htlc_info(
90106
err_data: vec![0; 32],
91107
}
92108
})?;
93-
(short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
94-
next_blinding_override, new_packet_bytes, next_hop_hmac)
109+
(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
110+
next_blinding_override)
95111
},
96112
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } =>
97113
return Err(InboundHTLCErr {
98114
msg: "Final Node OnionHopData provided for us as an intermediary node",
99115
err_code: 0x4000 | 22,
100116
err_data: Vec::new(),
101117
}),
118+
#[cfg(trampoline)]
119+
onion_utils::Hop::TrampolineReceive { .. } =>
120+
return Err(InboundHTLCErr {
121+
msg: "Final Node OnionHopData provided for us as an intermediary node",
122+
err_code: 0x4000 | 22,
123+
err_data: Vec::new(),
124+
}),
125+
#[cfg(trampoline)]
126+
onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
127+
(
128+
RoutingInfo::Trampoline {
129+
outgoing_node_id: next_trampoline_hop_data.outgoing_node_id,
130+
new_packet_bytes: new_trampoline_packet_bytes,
131+
next_hop_hmac: next_trampoline_hop_hmac,
132+
shared_secret: trampoline_shared_secret
133+
},
134+
next_trampoline_hop_data.amt_to_forward,
135+
next_trampoline_hop_data.outgoing_cltv_value,
136+
None,
137+
None
138+
)
139+
},
140+
#[cfg(trampoline)]
141+
onion_utils::Hop::TrampolineBlindedForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
142+
let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
143+
msg.amount_msat, msg.cltv_expiry, &next_trampoline_hop_data.payment_relay, &next_trampoline_hop_data.payment_constraints, &next_trampoline_hop_data.features
144+
).map_err(|()| {
145+
// We should be returning malformed here if `msg.blinding_point` is set, but this is
146+
// unreachable right now since we checked it in `decode_update_add_htlc_onion`.
147+
InboundHTLCErr {
148+
msg: "Underflow calculating outbound amount or cltv value for blinded forward",
149+
err_code: INVALID_ONION_BLINDING,
150+
err_data: vec![0; 32],
151+
}
152+
})?;
153+
(
154+
RoutingInfo::Trampoline {
155+
outgoing_node_id: next_trampoline_hop_data.outgoing_node_id,
156+
new_packet_bytes: new_trampoline_packet_bytes,
157+
next_hop_hmac: next_trampoline_hop_hmac,
158+
shared_secret: trampoline_shared_secret
159+
},
160+
amt_to_forward,
161+
outgoing_cltv_value,
162+
next_trampoline_hop_data.intro_node_blinding_point,
163+
next_trampoline_hop_data.next_blinding_override
164+
)
165+
},
102166
};
103167

104-
let outgoing_packet = msgs::OnionPacket {
105-
version: 0,
106-
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
107-
hop_data: new_packet_bytes,
108-
hmac: next_hop_hmac,
168+
let routing = match routing_info {
169+
RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac } => {
170+
let outgoing_packet = msgs::OnionPacket {
171+
version: 0,
172+
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
173+
hop_data: new_packet_bytes,
174+
hmac: next_hop_hmac,
175+
};
176+
PendingHTLCRouting::Forward {
177+
onion_packet: outgoing_packet,
178+
short_channel_id,
179+
incoming_cltv_expiry: Some(msg.cltv_expiry),
180+
blinded: intro_node_blinding_point.or(msg.blinding_point)
181+
.map(|bp| BlindedForward {
182+
inbound_blinding_point: bp,
183+
next_blinding_override,
184+
failure: intro_node_blinding_point
185+
.map(|_| BlindedFailure::FromIntroductionNode)
186+
.unwrap_or(BlindedFailure::FromBlindedNode),
187+
}),
188+
}
189+
}
190+
#[cfg(trampoline)]
191+
RoutingInfo::Trampoline { outgoing_node_id, new_packet_bytes, next_hop_hmac, shared_secret } => {
192+
let next_trampoline_packet_pubkey = match next_packet_pubkey_opt {
193+
Some(Ok(pubkey)) => pubkey,
194+
_ => return Err(InboundHTLCErr {
195+
msg: "Missing next Trampoline hop pubkey from intermediate Trampoline forwarding data",
196+
err_code: 0x4000 | 22,
197+
err_data: Vec::new(),
198+
}),
199+
};
200+
let outgoing_packet = msgs::TrampolineOnionPacket {
201+
version: 0,
202+
public_key: next_trampoline_packet_pubkey,
203+
hop_data: new_packet_bytes,
204+
hmac: next_hop_hmac,
205+
};
206+
PendingHTLCRouting::TrampolineForward {
207+
incoming_shared_secret: shared_secret.secret_bytes(),
208+
onion_packet: outgoing_packet,
209+
node_id: outgoing_node_id,
210+
incoming_cltv_expiry: msg.cltv_expiry,
211+
blinded: None
212+
}
213+
}
109214
};
110215

111216
Ok(PendingHTLCInfo {
112-
routing: PendingHTLCRouting::Forward {
113-
onion_packet: outgoing_packet,
114-
short_channel_id,
115-
incoming_cltv_expiry: Some(msg.cltv_expiry),
116-
blinded: intro_node_blinding_point.or(msg.blinding_point)
117-
.map(|bp| BlindedForward {
118-
inbound_blinding_point: bp,
119-
next_blinding_override,
120-
failure: intro_node_blinding_point
121-
.map(|_| BlindedFailure::FromIntroductionNode)
122-
.unwrap_or(BlindedFailure::FromBlindedNode),
123-
}),
124-
},
217+
routing,
125218
payment_hash: msg.payment_hash,
126219
incoming_shared_secret: shared_secret,
127220
incoming_amt_msat: Some(msg.amount_msat),
@@ -167,6 +260,8 @@ pub(super) fn create_recv_pending_htlc_info(
167260
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
168261
intro_node_blinding_point.is_none(), true, invoice_request)
169262
}
263+
#[cfg(trampoline)]
264+
onion_utils::Hop::TrampolineReceive { .. } => todo!(),
170265
onion_utils::Hop::Forward { .. } => {
171266
return Err(InboundHTLCErr {
172267
err_code: 0x4000|22,
@@ -181,6 +276,14 @@ pub(super) fn create_recv_pending_htlc_info(
181276
msg: "Got blinded non final data with an HMAC of 0",
182277
})
183278
},
279+
#[cfg(trampoline)]
280+
onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => {
281+
return Err(InboundHTLCErr {
282+
err_code: 0x4000|22,
283+
err_data: Vec::new(),
284+
msg: "Got Trampoline non final data with an HMAC of 0",
285+
})
286+
},
184287
};
185288
// final_incorrect_cltv_expiry
186289
if onion_cltv_expiry > cltv_expiry {
@@ -391,7 +494,7 @@ where
391494
return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
392495
}
393496

394-
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], data: &[u8]| {
497+
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], trampoline_shared_secret: Option<[u8; 32]>, data: &[u8]| {
395498
if msg.blinding_point.is_some() {
396499
return_malformed_err!(message, INVALID_ONION_BLINDING)
397500
}
@@ -401,7 +504,7 @@ where
401504
channel_id: msg.channel_id,
402505
htlc_id: msg.htlc_id,
403506
reason: HTLCFailReason::reason(err_code, data.to_vec())
404-
.get_encrypted_failure_packet(&shared_secret, &None),
507+
.get_encrypted_failure_packet(&shared_secret, &trampoline_shared_secret),
405508
}));
406509
};
407510

@@ -413,8 +516,8 @@ where
413516
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
414517
return_malformed_err!(err_msg, err_code);
415518
},
416-
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret }) => {
417-
return encode_relay_error(err_msg, err_code, shared_secret.secret_bytes(), &[0; 0]);
519+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret, trampoline_shared_secret }) => {
520+
return encode_relay_error(err_msg, err_code, shared_secret.secret_bytes(), trampoline_shared_secret.map(|tss| tss.secret_bytes()), &[0; 0]);
418521
},
419522
};
420523

@@ -434,7 +537,7 @@ where
434537
Ok((amt, cltv)) => (amt, cltv),
435538
Err(()) => {
436539
return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward",
437-
INVALID_ONION_BLINDING, shared_secret.secret_bytes(), &[0; 32]);
540+
INVALID_ONION_BLINDING, shared_secret.secret_bytes(), None, &[0; 32]);
438541
}
439542
};
440543
let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx,
@@ -444,6 +547,17 @@ where
444547
outgoing_cltv_value
445548
})
446549
}
550+
#[cfg(trampoline)]
551+
onion_utils::Hop::TrampolineForward { next_trampoline_hop_data: msgs::InboundTrampolineForwardPayload { amt_to_forward, outgoing_cltv_value, outgoing_node_id }, trampoline_shared_secret, incoming_trampoline_public_key, .. } => {
552+
let next_trampoline_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
553+
incoming_trampoline_public_key, &trampoline_shared_secret.secret_bytes());
554+
Some(NextPacketDetails {
555+
next_packet_pubkey: next_trampoline_packet_pubkey,
556+
outgoing_connector: HopConnector::Trampoline(outgoing_node_id),
557+
outgoing_amt_msat: amt_to_forward,
558+
outgoing_cltv_value,
559+
})
560+
}
447561
_ => None
448562
};
449563

0 commit comments

Comments
 (0)