@@ -14,7 +14,7 @@ use crate::ln::msgs;
1414use crate :: ln:: wire:: Encode ;
1515use crate :: ln:: { PaymentHash , PaymentPreimage } ;
1616use crate :: routing:: gossip:: NetworkUpdate ;
17- use crate :: routing:: router:: { BlindedTail , Path , RouteHop } ;
17+ use crate :: routing:: router:: { BlindedTail , Path , RouteHop , TrampolineHop } ;
1818use crate :: sign:: NodeSigner ;
1919use crate :: util:: errors:: { self , APIError } ;
2020use crate :: util:: logger:: Logger ;
@@ -173,6 +173,64 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(
173173 Ok ( res)
174174}
175175
176+ pub ( super ) fn construct_trampoline_keys_callback < T , FType > (
177+ secp_ctx : & Secp256k1 < T > , path : & [ TrampolineHop ] , session_priv : & SecretKey , mut callback : FType ,
178+ ) -> Result < ( ) , secp256k1:: Error >
179+ where
180+ T : secp256k1:: Signing ,
181+ FType : FnMut ( SharedSecret , [ u8 ; 32 ] , PublicKey , Option < & TrampolineHop > , usize ) ,
182+ {
183+ let mut blinded_priv = session_priv. clone ( ) ;
184+ let mut blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
185+
186+ let unblinded_hops_iter = path. iter ( ) . map ( |h| ( & h. pubkey , Some ( h) ) ) ;
187+ for ( idx, ( pubkey, route_hop_opt) ) in unblinded_hops_iter. enumerate ( ) {
188+ let shared_secret = SharedSecret :: new ( pubkey, & blinded_priv) ;
189+
190+ let mut sha = Sha256 :: engine ( ) ;
191+ sha. input ( & blinded_pub. serialize ( ) [ ..] ) ;
192+ sha. input ( shared_secret. as_ref ( ) ) ;
193+ let blinding_factor = Sha256 :: from_engine ( sha) . to_byte_array ( ) ;
194+
195+ let ephemeral_pubkey = blinded_pub;
196+
197+ blinded_priv = blinded_priv. mul_tweak ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ?;
198+ blinded_pub = PublicKey :: from_secret_key ( secp_ctx, & blinded_priv) ;
199+
200+ callback ( shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt, idx) ;
201+ }
202+
203+ Ok ( ( ) )
204+ }
205+
206+ // can only fail if an intermediary hop has an invalid public key or session_priv is invalid
207+ pub ( super ) fn construct_trampoline_keys < T : secp256k1:: Signing > (
208+ secp_ctx : & Secp256k1 < T > , path : & [ TrampolineHop ] , session_priv : & SecretKey ,
209+ ) -> Result < Vec < OnionKeys > , secp256k1:: Error > {
210+ let mut res = Vec :: with_capacity ( path. len ( ) ) ;
211+
212+ construct_trampoline_keys_callback (
213+ secp_ctx,
214+ & path,
215+ session_priv,
216+ |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| {
217+ let ( rho, mu) = gen_rho_mu_from_shared_secret ( shared_secret. as_ref ( ) ) ;
218+
219+ res. push ( OnionKeys {
220+ #[ cfg( test) ]
221+ shared_secret,
222+ #[ cfg( test) ]
223+ blinding_factor : _blinding_factor,
224+ ephemeral_pubkey,
225+ rho,
226+ mu,
227+ } ) ;
228+ } ,
229+ ) ?;
230+
231+ Ok ( res)
232+ }
233+
176234/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
177235pub ( super ) fn build_onion_payloads (
178236 path : & Path , total_msat : u64 , mut recipient_onion : RecipientOnionFields ,
0 commit comments