Skip to content

Commit 51539af

Browse files
committed
Trampoline payload construction method.
1 parent 5d7ba6a commit 51539af

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

lightning/src/ln/onion_utils.rs

+74
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,80 @@ pub(super) fn build_onion_payloads(
317317
Ok((res, cur_value_msat, cur_cltv))
318318
}
319319

320+
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
321+
pub(super) fn build_trampoline_payloads(
322+
path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields,
323+
starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>,
324+
) -> Result<(Vec<msgs::OutboundTrampolinePayload>, u64, u32), APIError> {
325+
let mut cur_value_msat = 0u64;
326+
let mut cur_cltv = starting_htlc_offset;
327+
let mut last_node_id = None;
328+
let mut res: Vec<msgs::OutboundTrampolinePayload> = Vec::with_capacity(
329+
path.trampoline_hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()),
330+
);
331+
332+
for (idx, hop) in path.trampoline_hops.iter().rev().enumerate() {
333+
// First hop gets special values so that it can check, on receipt, that everything is
334+
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
335+
// the intended recipient).
336+
let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
337+
let cltv = if cur_cltv == starting_htlc_offset {
338+
hop.cltv_expiry_delta + starting_htlc_offset
339+
} else {
340+
cur_cltv
341+
};
342+
if idx == 0 {
343+
let BlindedTail {
344+
blinding_point,
345+
hops,
346+
final_value_msat,
347+
excess_final_cltv_expiry_delta,
348+
..
349+
} = path.blinded_tail.as_ref().ok_or(APIError::InvalidRoute {
350+
err: "Trampoline payments must terminate in blinded tails.".to_owned(),
351+
})?;
352+
let mut blinding_point = Some(*blinding_point);
353+
for (i, blinded_hop) in hops.iter().enumerate() {
354+
if i == hops.len() - 1 {
355+
cur_value_msat += final_value_msat;
356+
res.push(msgs::OutboundTrampolinePayload::BlindedReceive {
357+
sender_intended_htlc_amt_msat: *final_value_msat,
358+
total_msat,
359+
cltv_expiry_height: cur_cltv + excess_final_cltv_expiry_delta,
360+
encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
361+
intro_node_blinding_point: blinding_point.take(),
362+
keysend_preimage: *keysend_preimage,
363+
custom_tlvs: recipient_onion.custom_tlvs.clone(),
364+
});
365+
} else {
366+
res.push(msgs::OutboundTrampolinePayload::BlindedForward {
367+
encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
368+
intro_node_blinding_point: blinding_point.take(),
369+
});
370+
}
371+
}
372+
} else {
373+
let payload = msgs::OutboundTrampolinePayload::Forward {
374+
amt_to_forward: value_msat,
375+
outgoing_cltv_value: cltv,
376+
outgoing_node_id: last_node_id
377+
.expect("outgoing node id cannot be None after last hop"),
378+
};
379+
res.insert(0, payload);
380+
}
381+
cur_value_msat += hop.fee_msat;
382+
if cur_value_msat >= 21000000 * 100000000 * 1000 {
383+
return Err(APIError::InvalidRoute { err: "Channel fees overflowed?".to_owned() });
384+
}
385+
cur_cltv += hop.cltv_expiry_delta as u32;
386+
if cur_cltv >= 500000000 {
387+
return Err(APIError::InvalidRoute { err: "Channel CLTV overflowed?".to_owned() });
388+
}
389+
last_node_id = Some(hop.pubkey);
390+
}
391+
Ok((res, cur_value_msat, cur_cltv))
392+
}
393+
320394
/// Length of the onion data packet. Before TLV-based onions this was 20 65-byte hops, though now
321395
/// the hops can be of variable length.
322396
pub(crate) const ONION_DATA_LEN: usize = 20 * 65;

0 commit comments

Comments
 (0)