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