Skip to content

Commit ef89d0f

Browse files
committed
Trampoline key construction methods.
1 parent f082933 commit ef89d0f

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::ln::msgs;
1414
use crate::ln::wire::Encode;
1515
use crate::ln::{PaymentHash, PaymentPreimage};
1616
use crate::routing::gossip::NetworkUpdate;
17-
use crate::routing::router::{BlindedTail, Path, RouteHop};
17+
use crate::routing::router::{BlindedTail, Path, RouteHop, TrampolineHop};
1818
use crate::sign::NodeSigner;
1919
use crate::util::errors::{self, APIError};
2020
use crate::util::logger::Logger;
@@ -172,6 +172,64 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(
172172
Ok(res)
173173
}
174174

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+
175233
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
176234
pub(super) fn build_onion_payloads(
177235
path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields,

0 commit comments

Comments
 (0)