Skip to content

Commit e768f53

Browse files
committed
Trampoline key construction methods.
1 parent 1e2d12f commit e768f53

File tree

1 file changed

+61
-3
lines changed

1 file changed

+61
-3
lines changed

lightning/src/ln/onion_utils.rs

+61-3
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;
@@ -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.
177235
pub(super) fn build_onion_payloads(
178236
path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields,
@@ -261,8 +319,8 @@ pub(super) fn build_onion_payloads(
261319

262320
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
263321
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>,
266324
) -> Result<(Vec<msgs::OutboundTrampolinePayload>, u64, u32), APIError> {
267325
let mut cur_value_msat = 0u64;
268326
let mut cur_cltv = starting_htlc_offset;

0 commit comments

Comments
 (0)