@@ -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 ;
@@ -173,6 +173,64 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(
173
173
Ok ( res)
174
174
}
175
175
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
+
176
234
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
177
235
pub ( super ) fn build_onion_payloads (
178
236
path : & Path , total_msat : u64 , mut recipient_onion : RecipientOnionFields ,
@@ -261,8 +319,8 @@ pub(super) fn build_onion_payloads(
261
319
262
320
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
263
321
pub ( super ) fn build_trampoline_payloads (
264
- path : & Path , total_msat : u64 , recipient_onion : RecipientOnionFields ,
265
- starting_htlc_offset : u32 , keysend_preimage : & Option < PaymentPreimage > ,
322
+ path : & Path , total_msat : u64 , recipient_onion : RecipientOnionFields , starting_htlc_offset : u32 ,
323
+ keysend_preimage : & Option < PaymentPreimage > ,
266
324
) -> Result < ( Vec < msgs:: OutboundTrampolinePayload > , u64 , u32 ) , APIError > {
267
325
let mut cur_value_msat = 0u64 ;
268
326
let mut cur_cltv = starting_htlc_offset;
0 commit comments