Skip to content

Commit 06a4828

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 06a4828

File tree

3 files changed

+312
-33
lines changed

3 files changed

+312
-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: 154 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,37 @@ 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+
current_path_key: Option<PublicKey>
78+
}
79+
}
80+
6481
pub(super) fn create_fwd_pending_htlc_info(
6582
msg: &msgs::UpdateAddHTLC, hop_data: onion_utils::Hop, shared_secret: [u8; 32],
6683
next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
6784
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
6885
debug_assert!(next_packet_pubkey_opt.is_some());
6986

7087
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
88+
routing_info, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
89+
next_blinding_override
7390
) = match hop_data {
7491
onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload {
7592
short_channel_id, amt_to_forward, outgoing_cltv_value
7693
}, new_packet_bytes, next_hop_hmac, .. } =>
77-
(short_channel_id, amt_to_forward, outgoing_cltv_value, None, None, new_packet_bytes, next_hop_hmac),
94+
(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, None, None),
7895
onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload {
7996
short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
8097
next_blinding_override,
@@ -90,38 +107,124 @@ pub(super) fn create_fwd_pending_htlc_info(
90107
err_data: vec![0; 32],
91108
}
92109
})?;
93-
(short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
94-
next_blinding_override, new_packet_bytes, next_hop_hmac)
110+
(RoutingInfo::Direct { short_channel_id, new_packet_bytes, next_hop_hmac }, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
111+
next_blinding_override)
95112
},
96113
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } =>
97114
return Err(InboundHTLCErr {
98115
msg: "Final Node OnionHopData provided for us as an intermediary node",
99116
err_code: 0x4000 | 22,
100117
err_data: Vec::new(),
101118
}),
119+
#[cfg(trampoline)]
120+
onion_utils::Hop::TrampolineReceive { .. } =>
121+
return Err(InboundHTLCErr {
122+
msg: "Final Node OnionHopData provided for us as an intermediary node",
123+
err_code: 0x4000 | 22,
124+
err_data: Vec::new(),
125+
}),
126+
#[cfg(trampoline)]
127+
onion_utils::Hop::TrampolineForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
128+
(
129+
RoutingInfo::Trampoline {
130+
outgoing_node_id: next_trampoline_hop_data.outgoing_node_id,
131+
new_packet_bytes: new_trampoline_packet_bytes,
132+
next_hop_hmac: next_trampoline_hop_hmac,
133+
shared_secret: trampoline_shared_secret,
134+
current_path_key: None
135+
},
136+
next_trampoline_hop_data.amt_to_forward,
137+
next_trampoline_hop_data.outgoing_cltv_value,
138+
None,
139+
None
140+
)
141+
},
142+
#[cfg(trampoline)]
143+
onion_utils::Hop::TrampolineBlindedForward { outer_hop_data, next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
144+
let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
145+
msg.amount_msat, msg.cltv_expiry, &next_trampoline_hop_data.payment_relay, &next_trampoline_hop_data.payment_constraints, &next_trampoline_hop_data.features
146+
).map_err(|()| {
147+
// We should be returning malformed here if `msg.blinding_point` is set, but this is
148+
// unreachable right now since we checked it in `decode_update_add_htlc_onion`.
149+
InboundHTLCErr {
150+
msg: "Underflow calculating outbound amount or cltv value for blinded forward",
151+
err_code: INVALID_ONION_BLINDING,
152+
err_data: vec![0; 32],
153+
}
154+
})?;
155+
(
156+
RoutingInfo::Trampoline {
157+
outgoing_node_id: next_trampoline_hop_data.outgoing_node_id,
158+
new_packet_bytes: new_trampoline_packet_bytes,
159+
next_hop_hmac: next_trampoline_hop_hmac,
160+
shared_secret: trampoline_shared_secret,
161+
current_path_key: outer_hop_data.current_path_key
162+
},
163+
amt_to_forward,
164+
outgoing_cltv_value,
165+
next_trampoline_hop_data.intro_node_blinding_point,
166+
next_trampoline_hop_data.next_blinding_override
167+
)
168+
},
102169
};
103170

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

111226
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-
},
227+
routing,
125228
payment_hash: msg.payment_hash,
126229
incoming_shared_secret: shared_secret,
127230
incoming_amt_msat: Some(msg.amount_msat),
@@ -167,6 +270,8 @@ pub(super) fn create_recv_pending_htlc_info(
167270
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
168271
intro_node_blinding_point.is_none(), true, invoice_request)
169272
}
273+
#[cfg(trampoline)]
274+
onion_utils::Hop::TrampolineReceive { .. } => todo!(),
170275
onion_utils::Hop::Forward { .. } => {
171276
return Err(InboundHTLCErr {
172277
err_code: 0x4000|22,
@@ -181,6 +286,14 @@ pub(super) fn create_recv_pending_htlc_info(
181286
msg: "Got blinded non final data with an HMAC of 0",
182287
})
183288
},
289+
#[cfg(trampoline)]
290+
onion_utils::Hop::TrampolineForward { .. } | onion_utils::Hop::TrampolineBlindedForward { .. } => {
291+
return Err(InboundHTLCErr {
292+
err_code: 0x4000|22,
293+
err_data: Vec::new(),
294+
msg: "Got Trampoline non final data with an HMAC of 0",
295+
})
296+
},
184297
};
185298
// final_incorrect_cltv_expiry
186299
if onion_cltv_expiry > cltv_expiry {
@@ -391,7 +504,7 @@ where
391504
return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
392505
}
393506

394-
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], data: &[u8]| {
507+
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], trampoline_shared_secret: Option<[u8; 32]>, data: &[u8]| {
395508
if msg.blinding_point.is_some() {
396509
return_malformed_err!(message, INVALID_ONION_BLINDING)
397510
}
@@ -401,7 +514,7 @@ where
401514
channel_id: msg.channel_id,
402515
htlc_id: msg.htlc_id,
403516
reason: HTLCFailReason::reason(err_code, data.to_vec())
404-
.get_encrypted_failure_packet(&shared_secret, &None),
517+
.get_encrypted_failure_packet(&shared_secret, &trampoline_shared_secret),
405518
}));
406519
};
407520

@@ -413,8 +526,8 @@ where
413526
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
414527
return_malformed_err!(err_msg, err_code);
415528
},
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]);
529+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret, trampoline_shared_secret }) => {
530+
return encode_relay_error(err_msg, err_code, shared_secret.secret_bytes(), trampoline_shared_secret.map(|tss| tss.secret_bytes()), &[0; 0]);
418531
},
419532
};
420533

@@ -434,7 +547,7 @@ where
434547
Ok((amt, cltv)) => (amt, cltv),
435548
Err(()) => {
436549
return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward",
437-
INVALID_ONION_BLINDING, shared_secret.secret_bytes(), &[0; 32]);
550+
INVALID_ONION_BLINDING, shared_secret.secret_bytes(), None, &[0; 32]);
438551
}
439552
};
440553
let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx,
@@ -444,6 +557,17 @@ where
444557
outgoing_cltv_value
445558
})
446559
}
560+
#[cfg(trampoline)]
561+
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, .. } => {
562+
let next_trampoline_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
563+
incoming_trampoline_public_key, &trampoline_shared_secret.secret_bytes());
564+
Some(NextPacketDetails {
565+
next_packet_pubkey: next_trampoline_packet_pubkey,
566+
outgoing_connector: HopConnector::Trampoline(outgoing_node_id),
567+
outgoing_amt_msat: amt_to_forward,
568+
outgoing_cltv_value,
569+
})
570+
}
447571
_ => None
448572
};
449573

0 commit comments

Comments
 (0)