@@ -176,6 +176,72 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(
176176 Ok ( res)
177177}
178178
179+ #[ inline]
180+ pub ( super ) fn construct_trampoline_onion_keys_callback < T , FType > (
181+ secp_ctx : & Secp256k1 < T > , path : & Path , session_priv : & SecretKey , mut callback : FType ,
182+ ) -> Result < ( ) , secp256k1:: Error >
183+ where
184+ T : secp256k1:: Signing ,
185+ FType : FnMut ( SharedSecret , [ u8 ; 32 ] , PublicKey , Option < & TrampolineHop > , usize ) ,
186+ {
187+ let mut blinded_priv = session_priv. clone ( ) ;
188+ let mut blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
189+
190+ let unblinded_hops_iter = path. trampoline_hops . iter ( ) . map ( |h| ( & h. pubkey , Some ( h) ) ) ;
191+ let blinded_pks_iter = path
192+ . blinded_tail
193+ . as_ref ( )
194+ . map ( |t| t. hops . iter ( ) )
195+ . unwrap_or ( [ ] . iter ( ) )
196+ . skip ( 1 ) // Skip the intro node because it's included in the unblinded hops
197+ . map ( |h| ( & h. blinded_node_id , None ) ) ;
198+ for ( idx, ( pubkey, route_hop_opt) ) in unblinded_hops_iter. chain ( blinded_pks_iter) . enumerate ( ) {
199+ let shared_secret = SharedSecret :: new ( pubkey, & blinded_priv) ;
200+
201+ let mut sha = Sha256 :: engine ( ) ;
202+ sha. input ( & blinded_pub. serialize ( ) [ ..] ) ;
203+ sha. input ( shared_secret. as_ref ( ) ) ;
204+ let blinding_factor = Sha256 :: from_engine ( sha) . to_byte_array ( ) ;
205+
206+ let ephemeral_pubkey = blinded_pub;
207+
208+ blinded_priv = blinded_priv. mul_tweak ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ?;
209+ blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
210+
211+ callback ( shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt, idx) ;
212+ }
213+
214+ Ok ( ( ) )
215+ }
216+
217+ // can only fail if an intermediary hop has an invalid public key or session_priv is invalid
218+ pub ( super ) fn construct_trampoline_onion_keys < T : secp256k1:: Signing > (
219+ secp_ctx : & Secp256k1 < T > , path : & Path , session_priv : & SecretKey ,
220+ ) -> Result < Vec < OnionKeys > , secp256k1:: Error > {
221+ let mut res = Vec :: with_capacity ( path. trampoline_hops . len ( ) ) ;
222+
223+ construct_trampoline_onion_keys_callback (
224+ secp_ctx,
225+ & path,
226+ session_priv,
227+ |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| {
228+ let ( rho, mu) = gen_rho_mu_from_shared_secret ( shared_secret. as_ref ( ) ) ;
229+
230+ res. push ( OnionKeys {
231+ #[ cfg( test) ]
232+ shared_secret,
233+ #[ cfg( test) ]
234+ blinding_factor : _blinding_factor,
235+ ephemeral_pubkey,
236+ rho,
237+ mu,
238+ } ) ;
239+ } ,
240+ ) ?;
241+
242+ Ok ( res)
243+ }
244+
179245fn build_trampoline_onion_payloads < ' a > (
180246 path : & ' a Path , total_msat : u64 , recipient_onion : & ' a RecipientOnionFields ,
181247 starting_htlc_offset : u32 , keysend_preimage : & Option < PaymentPreimage > ,
0 commit comments