@@ -104,12 +104,23 @@ pub(crate) fn next_hop_packet_pubkey<T: secp256k1::Signing + secp256k1::Verifica
104
104
105
105
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
106
106
#[ inline]
107
- pub ( super ) fn construct_onion_keys_callback < T : secp256k1:: Signing , FType : FnMut ( SharedSecret , [ u8 ; 32 ] , PublicKey , & RouteHop , usize ) > ( secp_ctx : & Secp256k1 < T > , path : & Vec < RouteHop > , session_priv : & SecretKey , mut callback : FType ) -> Result < ( ) , secp256k1:: Error > {
107
+ pub ( super ) fn construct_onion_keys_callback < T , FType > (
108
+ secp_ctx : & Secp256k1 < T > , path : & Path , session_priv : & SecretKey , mut callback : FType
109
+ ) -> Result < ( ) , secp256k1:: Error >
110
+ where
111
+ T : secp256k1:: Signing ,
112
+ FType : FnMut ( SharedSecret , [ u8 ; 32 ] , PublicKey , Option < & RouteHop > , usize )
113
+ {
108
114
let mut blinded_priv = session_priv. clone ( ) ;
109
115
let mut blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
110
116
111
- for ( idx, hop) in path. iter ( ) . enumerate ( ) {
112
- let shared_secret = SharedSecret :: new ( & hop. pubkey , & blinded_priv) ;
117
+ let unblinded_hops_iter = path. hops . iter ( ) . map ( |h| ( & h. pubkey , Some ( h) ) ) ;
118
+ let blinded_pks_iter = path. blinded_tail . as_ref ( )
119
+ . map ( |t| t. hops . iter ( ) ) . unwrap_or ( [ ] . iter ( ) )
120
+ . skip ( 1 ) // Skip the intro node because it's included in the unblinded hops
121
+ . map ( |h| ( & h. blinded_node_id , None ) ) ;
122
+ for ( idx, ( pubkey, route_hop_opt) ) in unblinded_hops_iter. chain ( blinded_pks_iter) . enumerate ( ) {
123
+ let shared_secret = SharedSecret :: new ( pubkey, & blinded_priv) ;
113
124
114
125
let mut sha = Sha256 :: engine ( ) ;
115
126
sha. input ( & blinded_pub. serialize ( ) [ ..] ) ;
@@ -121,7 +132,7 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
121
132
blinded_priv = blinded_priv. mul_tweak ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ?;
122
133
blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
123
134
124
- callback ( shared_secret, blinding_factor, ephemeral_pubkey, hop , idx) ;
135
+ callback ( shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt , idx) ;
125
136
}
126
137
127
138
Ok ( ( ) )
@@ -131,7 +142,9 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
131
142
pub ( super ) fn construct_onion_keys < T : secp256k1:: Signing > ( secp_ctx : & Secp256k1 < T > , path : & Path , session_priv : & SecretKey ) -> Result < Vec < OnionKeys > , secp256k1:: Error > {
132
143
let mut res = Vec :: with_capacity ( path. hops . len ( ) ) ;
133
144
134
- construct_onion_keys_callback ( secp_ctx, & path. hops , session_priv, |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| {
145
+ construct_onion_keys_callback ( secp_ctx, & path, session_priv,
146
+ |shared_secret, _blinding_factor, ephemeral_pubkey, _, _|
147
+ {
135
148
let ( rho, mu) = gen_rho_mu_from_shared_secret ( shared_secret. as_ref ( ) ) ;
136
149
137
150
res. push ( OnionKeys {
@@ -400,10 +413,28 @@ where L::Target: Logger {
400
413
let mut error_packet_ret = None ;
401
414
let mut is_from_final_node = false ;
402
415
416
+ const BADONION : u16 = 0x8000 ;
417
+ const PERM : u16 = 0x4000 ;
418
+ const NODE : u16 = 0x2000 ;
419
+ const UPDATE : u16 = 0x1000 ;
420
+
403
421
// Handle packed channel/node updates for passing back for the route handler
404
- construct_onion_keys_callback ( secp_ctx, & path. hops , session_priv, |shared_secret, _, _, route_hop, route_hop_idx| {
422
+ construct_onion_keys_callback ( secp_ctx, & path, session_priv,
423
+ |shared_secret, _, _, route_hop_opt, route_hop_idx|
424
+ {
405
425
if res. is_some ( ) { return ; }
406
426
427
+ let route_hop = match route_hop_opt {
428
+ Some ( hop) => hop,
429
+ None => {
430
+ // Got an error from within a blinded route.
431
+ error_code_ret = Some ( BADONION | PERM | 24 ) ; // invalid_onion_blinding
432
+ error_packet_ret = Some ( vec ! [ 0 ; 32 ] ) ;
433
+ is_from_final_node = false ;
434
+ return
435
+ } ,
436
+ } ;
437
+
407
438
let amt_to_forward = htlc_msat - route_hop. fee_msat ;
408
439
htlc_msat = amt_to_forward;
409
440
@@ -443,10 +474,6 @@ where L::Target: Logger {
443
474
return
444
475
}
445
476
} ;
446
- const BADONION : u16 = 0x8000 ;
447
- const PERM : u16 = 0x4000 ;
448
- const NODE : u16 = 0x2000 ;
449
- const UPDATE : u16 = 0x1000 ;
450
477
451
478
let error_code = u16:: from_be_bytes ( error_code_slice. try_into ( ) . expect ( "len is 2" ) ) ;
452
479
error_code_ret = Some ( error_code) ;
0 commit comments