@@ -12,7 +12,7 @@ use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
12
12
use crate :: ln:: msgs;
13
13
use crate :: ln:: wire:: Encode ;
14
14
use crate :: routing:: gossip:: NetworkUpdate ;
15
- use crate :: routing:: router:: { Path , RouteHop } ;
15
+ use crate :: routing:: router:: { BlindedTail , Path , RouteHop } ;
16
16
use crate :: util:: chacha20:: { ChaCha20 , ChaChaReader } ;
17
17
use crate :: util:: errors:: { self , APIError } ;
18
18
use crate :: util:: ser:: { Readable , ReadableArgs , Writeable , Writer , LengthCalculatingWriter } ;
@@ -169,35 +169,61 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
169
169
let mut cur_value_msat = 0u64 ;
170
170
let mut cur_cltv = starting_htlc_offset;
171
171
let mut last_short_channel_id = 0 ;
172
- let mut res: Vec < msgs:: OutboundOnionPayload > = Vec :: with_capacity ( path. hops . len ( ) ) ;
172
+ let mut res: Vec < msgs:: OutboundOnionPayload > = Vec :: with_capacity (
173
+ path. hops . len ( ) + path. blinded_tail . as_ref ( ) . map_or ( 0 , |t| t. hops . len ( ) )
174
+ ) ;
173
175
174
176
for ( idx, hop) in path. hops . iter ( ) . rev ( ) . enumerate ( ) {
175
177
// First hop gets special values so that it can check, on receipt, that everything is
176
178
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
177
179
// the intended recipient).
178
180
let value_msat = if cur_value_msat == 0 { hop. fee_msat } else { cur_value_msat } ;
179
181
let cltv = if cur_cltv == starting_htlc_offset { hop. cltv_expiry_delta + starting_htlc_offset } else { cur_cltv } ;
180
- res. insert ( 0 , if idx == 0 {
181
- msgs:: OutboundOnionPayload :: Receive {
182
- payment_data : if let Some ( secret) = recipient_onion. payment_secret . take ( ) {
183
- Some ( msgs:: FinalOnionHopData {
184
- payment_secret : secret,
185
- total_msat,
186
- } )
187
- } else { None } ,
188
- payment_metadata : recipient_onion. payment_metadata . take ( ) ,
189
- keysend_preimage : * keysend_preimage,
190
- custom_tlvs : recipient_onion. custom_tlvs . clone ( ) ,
191
- amt_msat : value_msat,
192
- outgoing_cltv_value : cltv,
182
+ if idx == 0 {
183
+ if let Some ( BlindedTail {
184
+ blinding_point, hops, final_value_msat, excess_final_cltv_expiry_delta, ..
185
+ } ) = & path. blinded_tail {
186
+ let mut blinding_point = Some ( * blinding_point) ;
187
+ for ( i, blinded_hop) in hops. iter ( ) . enumerate ( ) {
188
+ if i == hops. len ( ) - 1 {
189
+ cur_value_msat += final_value_msat;
190
+ cur_cltv += excess_final_cltv_expiry_delta;
191
+ res. push ( msgs:: OutboundOnionPayload :: BlindedReceive {
192
+ amt_msat : * final_value_msat,
193
+ total_msat,
194
+ outgoing_cltv_value : cltv,
195
+ encrypted_tlvs : blinded_hop. encrypted_payload . clone ( ) ,
196
+ intro_node_blinding_point : blinding_point. take ( ) ,
197
+ } ) ;
198
+ } else {
199
+ res. push ( msgs:: OutboundOnionPayload :: BlindedForward {
200
+ encrypted_tlvs : blinded_hop. encrypted_payload . clone ( ) ,
201
+ intro_node_blinding_point : blinding_point. take ( ) ,
202
+ } ) ;
203
+ }
204
+ }
205
+ } else {
206
+ res. push ( msgs:: OutboundOnionPayload :: Receive {
207
+ payment_data : if let Some ( secret) = recipient_onion. payment_secret . take ( ) {
208
+ Some ( msgs:: FinalOnionHopData {
209
+ payment_secret : secret,
210
+ total_msat,
211
+ } )
212
+ } else { None } ,
213
+ payment_metadata : recipient_onion. payment_metadata . take ( ) ,
214
+ keysend_preimage : * keysend_preimage,
215
+ custom_tlvs : recipient_onion. custom_tlvs . clone ( ) ,
216
+ amt_msat : value_msat,
217
+ outgoing_cltv_value : cltv,
218
+ } ) ;
193
219
}
194
220
} else {
195
- msgs:: OutboundOnionPayload :: Forward {
221
+ res . insert ( 0 , msgs:: OutboundOnionPayload :: Forward {
196
222
short_channel_id : last_short_channel_id,
197
223
amt_to_forward : value_msat,
198
224
outgoing_cltv_value : cltv,
199
- }
200
- } ) ;
225
+ } ) ;
226
+ }
201
227
cur_value_msat += hop. fee_msat ;
202
228
if cur_value_msat >= 21000000 * 100000000 * 1000 {
203
229
return Err ( APIError :: InvalidRoute { err : "Channel fees overflowed?" . to_owned ( ) } ) ;
0 commit comments