@@ -104,12 +104,23 @@ pub(crate) fn next_hop_packet_pubkey<T: secp256k1::Signing + secp256k1::Verifica
104104
105105// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
106106#[ 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+ {
108114 let mut blinded_priv = session_priv. clone ( ) ;
109115 let mut blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
110116
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) ;
113124
114125 let mut sha = Sha256 :: engine ( ) ;
115126 sha. input ( & blinded_pub. serialize ( ) [ ..] ) ;
@@ -121,7 +132,7 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
121132 blinded_priv = blinded_priv. mul_tweak ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ?;
122133 blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
123134
124- callback ( shared_secret, blinding_factor, ephemeral_pubkey, hop , idx) ;
135+ callback ( shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt , idx) ;
125136 }
126137
127138 Ok ( ( ) )
@@ -131,7 +142,9 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
131142pub ( super ) fn construct_onion_keys < T : secp256k1:: Signing > ( secp_ctx : & Secp256k1 < T > , path : & Path , session_priv : & SecretKey ) -> Result < Vec < OnionKeys > , secp256k1:: Error > {
132143 let mut res = Vec :: with_capacity ( path. hops . len ( ) ) ;
133144
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+ {
135148 let ( rho, mu) = gen_rho_mu_from_shared_secret ( shared_secret. as_ref ( ) ) ;
136149
137150 res. push ( OnionKeys {
@@ -401,9 +414,16 @@ where L::Target: Logger {
401414 let mut is_from_final_node = false ;
402415
403416 // 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| {
417+ construct_onion_keys_callback ( secp_ctx, & path, session_priv,
418+ |shared_secret, _, _, route_hop_opt, route_hop_idx|
419+ {
405420 if res. is_some ( ) { return ; }
406421
422+ let route_hop = match route_hop_opt {
423+ Some ( hop) => hop,
424+ None => return ,
425+ } ;
426+
407427 let amt_to_forward = htlc_msat - route_hop. fee_msat ;
408428 htlc_msat = amt_to_forward;
409429
0 commit comments