Skip to content

Commit f06ef64

Browse files
committed
Trampoline payload construction method.
1 parent 45ea39d commit f06ef64

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,62 @@ pub(super) fn build_onion_payloads(
314314
Ok((res, cur_value_msat, cur_cltv))
315315
}
316316

317+
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
318+
pub(super) fn build_trampoline_payloads(
319+
path: &[TrampolineHop], total_msat: u64, mut recipient_onion: RecipientOnionFields,
320+
starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>,
321+
) -> Result<(Vec<msgs::OutboundOnionPayload>, u64, u32), APIError> {
322+
let mut cur_value_msat = 0u64;
323+
let mut cur_cltv = starting_htlc_offset;
324+
let mut res: Vec<msgs::OutboundOnionPayload> = Vec::with_capacity(path.len());
325+
let mut last_node_id = None;
326+
327+
for (idx, hop) in path.iter().rev().enumerate() {
328+
// First hop gets special values so that it can check, on receipt, that everything is
329+
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
330+
// the intended recipient).
331+
let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
332+
let cltv = if cur_cltv == starting_htlc_offset {
333+
hop.cltv_expiry_delta + starting_htlc_offset
334+
} else {
335+
cur_cltv
336+
};
337+
if idx == 0 {
338+
res.push(msgs::OutboundOnionPayload::Receive {
339+
payment_data: if let Some(secret) = recipient_onion.payment_secret.take() {
340+
Some(msgs::FinalOnionHopData { payment_secret: secret, total_msat })
341+
} else {
342+
None
343+
},
344+
payment_metadata: recipient_onion.payment_metadata.take(),
345+
keysend_preimage: *keysend_preimage,
346+
custom_tlvs: recipient_onion.custom_tlvs.clone(),
347+
sender_intended_htlc_amt_msat: value_msat,
348+
cltv_expiry_height: cltv,
349+
});
350+
} else {
351+
res.insert(
352+
0,
353+
msgs::OutboundOnionPayload::TrampolineForward {
354+
amt_to_forward: value_msat,
355+
outgoing_cltv_value: cltv,
356+
outgoing_node_id: last_node_id.unwrap(),
357+
},
358+
);
359+
}
360+
cur_value_msat += hop.fee_msat;
361+
if cur_value_msat >= 21000000 * 100000000 * 1000 {
362+
return Err(APIError::InvalidRoute { err: "Channel fees overflowed?".to_owned() });
363+
}
364+
cur_cltv += hop.cltv_expiry_delta as u32;
365+
if cur_cltv >= 500000000 {
366+
return Err(APIError::InvalidRoute { err: "Channel CLTV overflowed?".to_owned() });
367+
}
368+
last_node_id = Some(hop.pubkey);
369+
}
370+
Ok((res, cur_value_msat, cur_cltv))
371+
}
372+
317373
/// Length of the onion data packet. Before TLV-based onions this was 20 65-byte hops, though now
318374
/// the hops can be of variable length.
319375
pub(crate) const ONION_DATA_LEN: usize = 20 * 65;

0 commit comments

Comments
 (0)