Skip to content

Commit 5291445

Browse files
committed
Calculate shared secret within hop decode function
For Trampoline, we'll need to keep track of both the outer and inner onion's shared secrets. To this end, we're moving the secret calculation inside `decode_next_payment_hop` such that, when applicable, it can return both.
1 parent 1518e67 commit 5291445

File tree

5 files changed

+140
-85
lines changed

5 files changed

+140
-85
lines changed

lightning/src/ln/blinded_payment_tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,7 @@ fn route_blinding_spec_test_vector() {
15611561
let bob_node_signer = TestEcdhSigner { node_secret: bob_secret };
15621562
// Can't use the public API here as we need to avoid the CLTV delta checks (test vector uses
15631563
// < MIN_CLTV_EXPIRY_DELTA).
1564-
let (bob_peeled_onion, _, next_packet_details_opt) =
1564+
let (bob_peeled_onion, next_packet_details_opt) =
15651565
match onion_payment::decode_incoming_update_add_htlc_onion(
15661566
&bob_update_add, &bob_node_signer, &logger, &secp_ctx
15671567
) {
@@ -1571,7 +1571,7 @@ fn route_blinding_spec_test_vector() {
15711571
let (carol_packet_bytes, carol_hmac) = if let onion_utils::Hop::BlindedForward {
15721572
next_hop_data: msgs::InboundOnionBlindedForwardPayload {
15731573
short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override
1574-
}, next_hop_hmac, new_packet_bytes
1574+
}, next_hop_hmac, new_packet_bytes, ..
15751575
} = bob_peeled_onion {
15761576
assert_eq!(short_channel_id, 1729);
15771577
assert!(next_blinding_override.is_none());
@@ -1595,7 +1595,7 @@ fn route_blinding_spec_test_vector() {
15951595
carol_onion
15961596
);
15971597
let carol_node_signer = TestEcdhSigner { node_secret: carol_secret };
1598-
let (carol_peeled_onion, _, next_packet_details_opt) =
1598+
let (carol_peeled_onion, next_packet_details_opt) =
15991599
match onion_payment::decode_incoming_update_add_htlc_onion(
16001600
&carol_update_add, &carol_node_signer, &logger, &secp_ctx
16011601
) {
@@ -1605,7 +1605,7 @@ fn route_blinding_spec_test_vector() {
16051605
let (dave_packet_bytes, dave_hmac) = if let onion_utils::Hop::BlindedForward {
16061606
next_hop_data: msgs::InboundOnionBlindedForwardPayload {
16071607
short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override
1608-
}, next_hop_hmac, new_packet_bytes
1608+
}, next_hop_hmac, new_packet_bytes, ..
16091609
} = carol_peeled_onion {
16101610
assert_eq!(short_channel_id, 1105);
16111611
assert_eq!(next_blinding_override, Some(pubkey_from_hex("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f")));
@@ -1629,7 +1629,7 @@ fn route_blinding_spec_test_vector() {
16291629
dave_onion
16301630
);
16311631
let dave_node_signer = TestEcdhSigner { node_secret: dave_secret };
1632-
let (dave_peeled_onion, _, next_packet_details_opt) =
1632+
let (dave_peeled_onion, next_packet_details_opt) =
16331633
match onion_payment::decode_incoming_update_add_htlc_onion(
16341634
&dave_update_add, &dave_node_signer, &logger, &secp_ctx
16351635
) {
@@ -1639,7 +1639,7 @@ fn route_blinding_spec_test_vector() {
16391639
let (eve_packet_bytes, eve_hmac) = if let onion_utils::Hop::BlindedForward {
16401640
next_hop_data: msgs::InboundOnionBlindedForwardPayload {
16411641
short_channel_id, payment_relay, payment_constraints, features, intro_node_blinding_point, next_blinding_override
1642-
}, next_hop_hmac, new_packet_bytes
1642+
}, next_hop_hmac, new_packet_bytes, ..
16431643
} = dave_peeled_onion {
16441644
assert_eq!(short_channel_id, 561);
16451645
assert!(next_blinding_override.is_none());

lightning/src/ln/channelmanager.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4429,8 +4429,8 @@ where
44294429
match decoded_hop {
44304430
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => {
44314431
let inbound_onion_payload = match decoded_hop {
4432-
onion_utils::Hop::Receive(hop_data) => msgs::InboundOnionPayload::Receive(hop_data),
4433-
onion_utils::Hop::BlindedReceive(hop_data) => msgs::InboundOnionPayload::BlindedReceive(hop_data),
4432+
onion_utils::Hop::Receive { hop_data, .. } => msgs::InboundOnionPayload::Receive(hop_data),
4433+
onion_utils::Hop::BlindedReceive { hop_data, .. } => msgs::InboundOnionPayload::BlindedReceive(hop_data),
44344434
_ => unreachable!()
44354435
};
44364436

@@ -4450,14 +4450,14 @@ where
44504450
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44514451
}
44524452
},
4453-
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
4453+
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
44544454
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::Forward(next_hop_data), next_hop_hmac,
44554455
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
44564456
Ok(info) => PendingHTLCStatus::Forward(info),
44574457
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44584458
}
44594459
},
4460-
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
4460+
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
44614461
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::BlindedForward(next_hop_data), next_hop_hmac,
44624462
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
44634463
Ok(info) => PendingHTLCStatus::Forward(info),
@@ -5685,7 +5685,7 @@ where
56855685
let mut htlc_forwards = Vec::new();
56865686
let mut htlc_fails = Vec::new();
56875687
for update_add_htlc in &update_add_htlcs {
5688-
let (next_hop, shared_secret, next_packet_details_opt) = match decode_incoming_update_add_htlc_onion(
5688+
let (next_hop, next_packet_details_opt) = match decode_incoming_update_add_htlc_onion(
56895689
&update_add_htlc, &*self.node_signer, &*self.logger, &self.secp_ctx
56905690
) {
56915691
Ok(decoded_onion) => decoded_onion,
@@ -5697,6 +5697,7 @@ where
56975697

56985698
let is_intro_node_blinded_forward = next_hop.is_intro_node_blinded_forward();
56995699
let outgoing_scid_opt = next_packet_details_opt.as_ref().map(|d| d.outgoing_scid);
5700+
let shared_secret = next_hop.shared_secret().secret_bytes();
57005701

57015702
// Process the HTLC on the incoming channel.
57025703
match self.do_funded_channel_callback(incoming_scid, |chan: &mut FundedChannel<SP>| {
@@ -5855,10 +5856,9 @@ where
58555856
if let PendingHTLCRouting::Forward { ref onion_packet, .. } = routing {
58565857
let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode);
58575858
if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.chain_hash) {
5858-
let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
58595859
let next_hop = match onion_utils::decode_next_payment_hop(
5860-
phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac,
5861-
payment_hash, None, &*self.node_signer
5860+
Recipient::PhantomNode, &onion_packet.public_key.unwrap(), &onion_packet.hop_data,
5861+
onion_packet.hmac, payment_hash, None, &*self.node_signer
58625862
) {
58635863
Ok(res) => res,
58645864
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
@@ -5869,15 +5869,17 @@ where
58695869
// of the onion.
58705870
failed_payment!(err_msg, err_code, sha256_of_onion.to_vec(), None);
58715871
},
5872-
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code }) => {
5872+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret }) => {
5873+
let phantom_shared_secret = shared_secret.secret_bytes();
58735874
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
58745875
},
58755876
};
5876-
let inbound_onion_payload = match next_hop {
5877-
onion_utils::Hop::Receive(hop_data) => msgs::InboundOnionPayload::Receive(hop_data),
5878-
onion_utils::Hop::BlindedReceive(hop_data) => msgs::InboundOnionPayload::BlindedReceive(hop_data),
5877+
let (inbound_onion_payload, shared_secret) = match next_hop {
5878+
onion_utils::Hop::Receive { hop_data, shared_secret } => (msgs::InboundOnionPayload::Receive(hop_data), shared_secret),
5879+
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => (msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret),
58795880
_ => panic!()
58805881
};
5882+
let phantom_shared_secret = shared_secret.secret_bytes();
58815883
let current_height: u32 = self.best_block.read().unwrap().height;
58825884
match create_recv_pending_htlc_info(inbound_onion_payload,
58835885
incoming_shared_secret, payment_hash, outgoing_amt_msat,

lightning/src/ln/onion_payment.rs

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
//! Primarily features [`peel_payment_onion`], which allows the decoding of an onion statelessly
44
//! and can be used to predict whether we'd accept a payment.
55
6-
use bitcoin::hashes::{Hash, HashEngine};
7-
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
6+
use bitcoin::hashes::Hash;
87
use bitcoin::hashes::sha256::Hash as Sha256;
9-
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1};
8+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
109

1110
use crate::blinded_path;
1211
use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
@@ -285,7 +284,7 @@ where
285284
NS::Target: NodeSigner,
286285
L::Target: Logger,
287286
{
288-
let (hop, shared_secret, next_packet_details_opt) =
287+
let (hop, next_packet_details_opt) =
289288
decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx
290289
).map_err(|e| {
291290
let (err_code, err_data) = match e {
@@ -296,7 +295,8 @@ where
296295
InboundHTLCErr { msg, err_code, err_data }
297296
})?;
298297
Ok(match hop {
299-
onion_utils::Hop::Forward { next_hop_hmac, new_packet_bytes, .. } | onion_utils::Hop::BlindedForward { next_hop_hmac, new_packet_bytes, .. } => {
298+
onion_utils::Hop::Forward { shared_secret, next_hop_hmac, new_packet_bytes, .. } |
299+
onion_utils::Hop::BlindedForward { shared_secret, next_hop_hmac, new_packet_bytes, .. } => {
300300
let inbound_onion_payload = match hop {
301301
onion_utils::Hop::Forward { next_hop_data, .. } => msgs::InboundOnionPayload::Forward(next_hop_data),
302302
onion_utils::Hop::BlindedForward { next_hop_data, .. } => msgs::InboundOnionPayload::BlindedForward(next_hop_data),
@@ -328,19 +328,19 @@ where
328328
// TODO: If this is potentially a phantom payment we should decode the phantom payment
329329
// onion here and check it.
330330
create_fwd_pending_htlc_info(
331-
msg, inbound_onion_payload, next_hop_hmac, new_packet_bytes, shared_secret,
331+
msg, inbound_onion_payload, next_hop_hmac, new_packet_bytes, shared_secret.secret_bytes(),
332332
Some(next_packet_pubkey),
333333
)?
334334
},
335-
onion_utils::Hop::Receive(received_data) => {
335+
onion_utils::Hop::Receive { hop_data, shared_secret } => {
336336
create_recv_pending_htlc_info(
337-
msgs::InboundOnionPayload::Receive(received_data), shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
337+
msgs::InboundOnionPayload::Receive(hop_data), shared_secret.secret_bytes(), msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
338338
None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height,
339339
)?
340340
},
341-
onion_utils::Hop::BlindedReceive(received_data) => {
341+
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => {
342342
create_recv_pending_htlc_info(
343-
msgs::InboundOnionPayload::BlindedReceive(received_data), shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
343+
msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret.secret_bytes(), msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
344344
None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height,
345345
)?
346346
}
@@ -356,7 +356,7 @@ pub(super) struct NextPacketDetails {
356356

357357
pub(super) fn decode_incoming_update_add_htlc_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
358358
msg: &msgs::UpdateAddHTLC, node_signer: NS, logger: L, secp_ctx: &Secp256k1<T>,
359-
) -> Result<(onion_utils::Hop, [u8; 32], Option<NextPacketDetails>), HTLCFailureMsg>
359+
) -> Result<(onion_utils::Hop, Option<NextPacketDetails>), HTLCFailureMsg>
360360
where
361361
NS::Target: NodeSigner,
362362
L::Target: Logger,
@@ -384,16 +384,6 @@ where
384384
return_malformed_err!("invalid ephemeral pubkey", 0x8000 | 0x4000 | 6);
385385
}
386386

387-
let blinded_node_id_tweak = msg.blinding_point.map(|bp| {
388-
let blinded_tlvs_ss = node_signer.ecdh(Recipient::Node, &bp, None).unwrap().secret_bytes();
389-
let mut hmac = HmacEngine::<Sha256>::new(b"blinded_node_id");
390-
hmac.input(blinded_tlvs_ss.as_ref());
391-
Scalar::from_be_bytes(Hmac::from_engine(hmac).to_byte_array()).unwrap()
392-
});
393-
let shared_secret = node_signer.ecdh(
394-
Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), blinded_node_id_tweak.as_ref()
395-
).unwrap().secret_bytes();
396-
397387
if msg.onion_routing_packet.version != 0 {
398388
//TODO: Spec doesn't indicate if we should only hash hop_data here (and in other
399389
//sha256_of_onion error data packets), or the entire onion_routing_packet. Either way,
@@ -403,58 +393,55 @@ where
403393
//node knows the HMAC matched, so they already know what is there...
404394
return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4);
405395
}
406-
macro_rules! return_err {
407-
($msg: expr, $err_code: expr, $data: expr) => {
408-
{
409-
if msg.blinding_point.is_some() {
410-
return_malformed_err!($msg, INVALID_ONION_BLINDING)
411-
}
412396

413-
log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
414-
return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
415-
channel_id: msg.channel_id,
416-
htlc_id: msg.htlc_id,
417-
reason: HTLCFailReason::reason($err_code, $data.to_vec())
418-
.get_encrypted_failure_packet(&shared_secret, &None),
419-
}));
420-
}
397+
let encode_relay_error = |message: &str, err_code: u16, shared_secret: [u8; 32], data: &[u8]| {
398+
if msg.blinding_point.is_some() {
399+
return_malformed_err!(message, INVALID_ONION_BLINDING)
421400
}
422-
}
401+
402+
log_info!(logger, "Failed to accept/forward incoming HTLC: {}", message);
403+
return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
404+
channel_id: msg.channel_id,
405+
htlc_id: msg.htlc_id,
406+
reason: HTLCFailReason::reason(err_code, data.to_vec())
407+
.get_encrypted_failure_packet(&shared_secret, &None),
408+
}));
409+
};
423410

424411
let next_hop = match onion_utils::decode_next_payment_hop(
425-
shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac,
412+
Recipient::Node, &msg.onion_routing_packet.public_key.unwrap(), &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac,
426413
msg.payment_hash, msg.blinding_point, node_signer
427414
) {
428415
Ok(res) => res,
429416
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
430417
return_malformed_err!(err_msg, err_code);
431418
},
432-
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code }) => {
433-
return_err!(err_msg, err_code, &[0; 0]);
419+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret }) => {
420+
return encode_relay_error(err_msg, err_code, shared_secret.secret_bytes(), &[0; 0]);
434421
},
435422
};
436423

437424
let next_packet_details = match next_hop {
438-
Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, .. } => {
425+
Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, shared_secret, .. } => {
439426
let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
440-
msg.onion_routing_packet.public_key.unwrap(), &shared_secret);
427+
msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes());
441428
Some(NextPacketDetails {
442429
next_packet_pubkey, outgoing_scid: short_channel_id,
443430
outgoing_amt_msat: amt_to_forward, outgoing_cltv_value
444431
})
445432
}
446-
Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, .. } => {
433+
Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, shared_secret, .. } => {
447434
let (amt_to_forward, outgoing_cltv_value) = match check_blinded_forward(
448435
msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
449436
) {
450437
Ok((amt, cltv)) => (amt, cltv),
451438
Err(()) => {
452-
return_err!("Underflow calculating outbound amount or cltv value for blinded forward",
453-
INVALID_ONION_BLINDING, &[0; 32]);
439+
return encode_relay_error("Underflow calculating outbound amount or cltv value for blinded forward",
440+
INVALID_ONION_BLINDING, shared_secret.secret_bytes(), &[0; 32]);
454441
}
455442
};
456443
let next_packet_pubkey = onion_utils::next_hop_pubkey(&secp_ctx,
457-
msg.onion_routing_packet.public_key.unwrap(), &shared_secret);
444+
msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes());
458445
Some(NextPacketDetails {
459446
next_packet_pubkey, outgoing_scid: short_channel_id, outgoing_amt_msat: amt_to_forward,
460447
outgoing_cltv_value
@@ -463,7 +450,7 @@ where
463450
_ => None
464451
};
465452

466-
Ok((next_hop, shared_secret, next_packet_details))
453+
Ok((next_hop, next_packet_details))
467454
}
468455

469456
pub(super) fn check_incoming_htlc_cltv(

0 commit comments

Comments
 (0)