+ let blinded_tail_with_hop_iter = path.blinded_tail.as_ref().map(|bt| BlindedTailHopIter {
+ hops: bt.hops.iter(),
+ blinding_point: bt.blinding_point,
+ final_value_msat: bt.final_value_msat,
+ excess_final_cltv_expiry_delta: bt.excess_final_cltv_expiry_delta,
+ });
+
+ let (value_msat, cltv) = build_onion_payloads_callback(
+ path.hops.iter(),
+ blinded_tail_with_hop_iter,
+ total_msat,
+ recipient_onion,
+ starting_htlc_offset,
+ keysend_preimage,
+ |action, payload| match action {
+ PayloadCallbackAction::PushBack => res.push(payload),
+ PayloadCallbackAction::PushFront => res.insert(0, payload),
+ },
+ )?;
+ Ok((res, value_msat, cltv))
+}
+
+struct BlindedTailHopIter<'a, I: Iterator<Item = &'a BlindedHop>> {
+ hops: I,
+ blinding_point: PublicKey,
+ final_value_msat: u64,
+ excess_final_cltv_expiry_delta: u32,
+}
+enum PayloadCallbackAction {
+ PushBack,
+ PushFront,
+}
+fn build_onion_payloads_callback<'a, H, B, F>(
+ hops: H, mut blinded_tail: Option<BlindedTailHopIter<'a, B>>, total_msat: u64,
+ recipient_onion: &'a RecipientOnionFields, starting_htlc_offset: u32,
+ keysend_preimage: &Option<PaymentPreimage>, mut callback: F,
+) -> Result<(u64, u32), APIError>
+where
+ H: DoubleEndedIterator<Item = &'a RouteHop>,
+ B: ExactSizeIterator<Item = &'a BlindedHop>,
+ F: FnMut(PayloadCallbackAction, msgs::OutboundOnionPayload<'a>),
+{
+ let mut cur_value_msat = 0u64;
+ let mut cur_cltv = starting_htlc_offset;
+ let mut last_short_channel_id = 0;