Skip to content

Commit 32e28fe

Browse files
Support constructing onion keys for blinded hops
1 parent 6144e30 commit 32e28fe

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

lightning/src/ln/onion_utils.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,23 @@ pub(crate) fn next_hop_packet_pubkey<T: secp256k1::Signing + secp256k1::Verifica
104104

105105
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
106106
#[inline]
107-
pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(SharedSecret, [u8; 32], PublicKey, &RouteHop, usize)> (secp_ctx: &Secp256k1<T>, path: &Vec<RouteHop>, session_priv: &SecretKey, mut callback: FType) -> Result<(), secp256k1::Error> {
107+
pub(super) fn construct_onion_keys_callback<T, FType>(
108+
secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey, mut callback: FType
109+
) -> Result<(), secp256k1::Error>
110+
where
111+
T: secp256k1::Signing,
112+
FType: FnMut(SharedSecret, [u8; 32], PublicKey, Option<&RouteHop>, usize)
113+
{
108114
let mut blinded_priv = session_priv.clone();
109115
let mut blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
110116

111-
for (idx, hop) in path.iter().enumerate() {
112-
let shared_secret = SharedSecret::new(&hop.pubkey, &blinded_priv);
117+
let unblinded_hops_iter = path.hops.iter().map(|h| (&h.pubkey, Some(h)));
118+
let blinded_pks_iter = path.blinded_tail.as_ref()
119+
.map(|t| t.hops.iter()).unwrap_or([].iter())
120+
.skip(1) // Skip the intro node because it's included in the unblinded hops
121+
.map(|h| (&h.blinded_node_id, None));
122+
for (idx, (pubkey, route_hop_opt)) in unblinded_hops_iter.chain(blinded_pks_iter).enumerate() {
123+
let shared_secret = SharedSecret::new(pubkey, &blinded_priv);
113124

114125
let mut sha = Sha256::engine();
115126
sha.input(&blinded_pub.serialize()[..]);
@@ -121,7 +132,7 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
121132
blinded_priv = blinded_priv.mul_tweak(&Scalar::from_be_bytes(blinding_factor).unwrap())?;
122133
blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
123134

124-
callback(shared_secret, blinding_factor, ephemeral_pubkey, hop, idx);
135+
callback(shared_secret, blinding_factor, ephemeral_pubkey, route_hop_opt, idx);
125136
}
126137

127138
Ok(())
@@ -131,7 +142,9 @@ pub(super) fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(
131142
pub(super) fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, secp256k1::Error> {
132143
let mut res = Vec::with_capacity(path.hops.len());
133144

134-
construct_onion_keys_callback(secp_ctx, &path.hops, session_priv, |shared_secret, _blinding_factor, ephemeral_pubkey, _, _| {
145+
construct_onion_keys_callback(secp_ctx, &path, session_priv,
146+
|shared_secret, _blinding_factor, ephemeral_pubkey, _, _|
147+
{
135148
let (rho, mu) = gen_rho_mu_from_shared_secret(shared_secret.as_ref());
136149

137150
res.push(OnionKeys {
@@ -401,9 +414,16 @@ where L::Target: Logger {
401414
let mut is_from_final_node = false;
402415

403416
// Handle packed channel/node updates for passing back for the route handler
404-
construct_onion_keys_callback(secp_ctx, &path.hops, session_priv, |shared_secret, _, _, route_hop, route_hop_idx| {
417+
construct_onion_keys_callback(secp_ctx, &path, session_priv,
418+
|shared_secret, _, _, route_hop_opt, route_hop_idx|
419+
{
405420
if res.is_some() { return; }
406421

422+
let route_hop = match route_hop_opt {
423+
Some(hop) => hop,
424+
None => return,
425+
};
426+
407427
let amt_to_forward = htlc_msat - route_hop.fee_msat;
408428
htlc_msat = amt_to_forward;
409429

0 commit comments

Comments
 (0)