Skip to content

Commit bcdb67e

Browse files
Extract onion_utils::build_onion_payloads_callback helper.
Will be useful when we want to calculate the total size of the payloads without actually allocating for them.
1 parent 2de600b commit bcdb67e

File tree

1 file changed

+88
-35
lines changed

1 file changed

+88
-35
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 88 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
// You may not use this file except in accordance with one or both of these
88
// licenses.
99

10+
use crate::blinded_path::BlindedHop;
1011
use crate::crypto::chacha20::ChaCha20;
1112
use crate::crypto::streams::ChaChaReader;
1213
use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
1314
use crate::ln::msgs;
1415
use crate::ln::types::{PaymentHash, PaymentPreimage};
1516
use crate::ln::wire::Encode;
1617
use crate::routing::gossip::NetworkUpdate;
17-
use crate::routing::router::{BlindedTail, Path, RouteHop};
18+
use crate::routing::router::{Path, RouteHop};
1819
use crate::sign::NodeSigner;
1920
use crate::util::errors::{self, APIError};
2021
use crate::util::logger::Logger;
@@ -178,14 +179,56 @@ pub(super) fn build_onion_payloads<'a>(
178179
path: &'a Path, total_msat: u64, recipient_onion: &'a RecipientOnionFields,
179180
starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>,
180181
) -> Result<(Vec<msgs::OutboundOnionPayload<'a>>, u64, u32), APIError> {
181-
let mut cur_value_msat = 0u64;
182-
let mut cur_cltv = starting_htlc_offset;
183-
let mut last_short_channel_id = 0;
184182
let mut res: Vec<msgs::OutboundOnionPayload> = Vec::with_capacity(
185183
path.hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()),
186184
);
185+
let blinded_tail_with_hop_iter = path.blinded_tail.as_ref().map(|bt| BlindedTailHopIter {
186+
hops: bt.hops.iter(),
187+
blinding_point: bt.blinding_point,
188+
final_value_msat: bt.final_value_msat,
189+
excess_final_cltv_expiry_delta: bt.excess_final_cltv_expiry_delta,
190+
});
191+
192+
let (value_msat, cltv) = build_onion_payloads_callback(
193+
path.hops.iter(),
194+
blinded_tail_with_hop_iter,
195+
total_msat,
196+
recipient_onion,
197+
starting_htlc_offset,
198+
keysend_preimage,
199+
|action, payload| match action {
200+
PayloadCallbackAction::PushBack => res.push(payload),
201+
PayloadCallbackAction::PushFront => res.insert(0, payload),
202+
},
203+
)?;
204+
Ok((res, value_msat, cltv))
205+
}
187206

188-
for (idx, hop) in path.hops.iter().rev().enumerate() {
207+
struct BlindedTailHopIter<'a, I: Iterator<Item = &'a BlindedHop>> {
208+
hops: I,
209+
blinding_point: PublicKey,
210+
final_value_msat: u64,
211+
excess_final_cltv_expiry_delta: u32,
212+
}
213+
enum PayloadCallbackAction {
214+
PushBack,
215+
PushFront,
216+
}
217+
fn build_onion_payloads_callback<'a, H, B, F>(
218+
hops: H, mut blinded_tail: Option<BlindedTailHopIter<'a, B>>, total_msat: u64,
219+
recipient_onion: &'a RecipientOnionFields, starting_htlc_offset: u32,
220+
keysend_preimage: &Option<PaymentPreimage>, mut callback: F,
221+
) -> Result<(u64, u32), APIError>
222+
where
223+
H: DoubleEndedIterator<Item = &'a RouteHop>,
224+
B: ExactSizeIterator<Item = &'a BlindedHop>,
225+
F: FnMut(PayloadCallbackAction, msgs::OutboundOnionPayload<'a>),
226+
{
227+
let mut cur_value_msat = 0u64;
228+
let mut cur_cltv = starting_htlc_offset;
229+
let mut last_short_channel_id = 0;
230+
231+
for (idx, hop) in hops.rev().enumerate() {
189232
// First hop gets special values so that it can check, on receipt, that everything is
190233
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
191234
// the intended recipient).
@@ -196,53 +239,63 @@ pub(super) fn build_onion_payloads<'a>(
196239
cur_cltv
197240
};
198241
if idx == 0 {
199-
if let Some(BlindedTail {
242+
if let Some(BlindedTailHopIter {
200243
blinding_point,
201244
hops,
202245
final_value_msat,
203246
excess_final_cltv_expiry_delta,
204247
..
205-
}) = &path.blinded_tail
248+
}) = blinded_tail.take()
206249
{
207-
let mut blinding_point = Some(*blinding_point);
208-
for (i, blinded_hop) in hops.iter().enumerate() {
209-
if i == hops.len() - 1 {
250+
let mut blinding_point = Some(blinding_point);
251+
let hops_len = hops.len();
252+
for (i, blinded_hop) in hops.enumerate() {
253+
if i == hops_len - 1 {
210254
cur_value_msat += final_value_msat;
211-
res.push(msgs::OutboundOnionPayload::BlindedReceive {
212-
sender_intended_htlc_amt_msat: *final_value_msat,
213-
total_msat,
214-
cltv_expiry_height: cur_cltv + excess_final_cltv_expiry_delta,
215-
encrypted_tlvs: &blinded_hop.encrypted_payload,
216-
intro_node_blinding_point: blinding_point.take(),
217-
keysend_preimage: *keysend_preimage,
218-
custom_tlvs: &recipient_onion.custom_tlvs,
219-
});
255+
callback(
256+
PayloadCallbackAction::PushBack,
257+
msgs::OutboundOnionPayload::BlindedReceive {
258+
sender_intended_htlc_amt_msat: final_value_msat,
259+
total_msat,
260+
cltv_expiry_height: cur_cltv + excess_final_cltv_expiry_delta,
261+
encrypted_tlvs: &blinded_hop.encrypted_payload,
262+
intro_node_blinding_point: blinding_point.take(),
263+
keysend_preimage: *keysend_preimage,
264+
custom_tlvs: &recipient_onion.custom_tlvs,
265+
},
266+
);
220267
} else {
221-
res.push(msgs::OutboundOnionPayload::BlindedForward {
222-
encrypted_tlvs: &blinded_hop.encrypted_payload,
223-
intro_node_blinding_point: blinding_point.take(),
224-
});
268+
callback(
269+
PayloadCallbackAction::PushBack,
270+
msgs::OutboundOnionPayload::BlindedForward {
271+
encrypted_tlvs: &blinded_hop.encrypted_payload,
272+
intro_node_blinding_point: blinding_point.take(),
273+
},
274+
);
225275
}
226276
}
227277
} else {
228-
res.push(msgs::OutboundOnionPayload::Receive {
229-
payment_data: recipient_onion.payment_secret.map(|payment_secret| {
230-
msgs::FinalOnionHopData { payment_secret, total_msat }
231-
}),
232-
payment_metadata: recipient_onion.payment_metadata.as_ref(),
233-
keysend_preimage: *keysend_preimage,
234-
custom_tlvs: &recipient_onion.custom_tlvs,
235-
sender_intended_htlc_amt_msat: value_msat,
236-
cltv_expiry_height: cltv,
237-
});
278+
callback(
279+
PayloadCallbackAction::PushBack,
280+
msgs::OutboundOnionPayload::Receive {
281+
payment_data: recipient_onion.payment_secret.map(|payment_secret| {
282+
msgs::FinalOnionHopData { payment_secret, total_msat }
283+
}),
284+
payment_metadata: recipient_onion.payment_metadata.as_ref(),
285+
keysend_preimage: *keysend_preimage,
286+
custom_tlvs: &recipient_onion.custom_tlvs,
287+
sender_intended_htlc_amt_msat: value_msat,
288+
cltv_expiry_height: cltv,
289+
},
290+
);
238291
}
239292
} else {
240293
let payload = msgs::OutboundOnionPayload::Forward {
241294
short_channel_id: last_short_channel_id,
242295
amt_to_forward: value_msat,
243296
outgoing_cltv_value: cltv,
244297
};
245-
res.insert(0, payload);
298+
callback(PayloadCallbackAction::PushFront, payload);
246299
}
247300
cur_value_msat += hop.fee_msat;
248301
if cur_value_msat >= 21000000 * 100000000 * 1000 {
@@ -254,7 +307,7 @@ pub(super) fn build_onion_payloads<'a>(
254307
}
255308
last_short_channel_id = hop.short_channel_id;
256309
}
257-
Ok((res, cur_value_msat, cur_cltv))
310+
Ok((cur_value_msat, cur_cltv))
258311
}
259312

260313
/// Length of the onion data packet. Before TLV-based onions this was 20 65-byte hops, though now

0 commit comments

Comments
 (0)