Skip to content

Commit ef8868b

Browse files
authored
Merge pull request #3607 from arik-so/arik/trampoline/inbound-prefactors-03
Move shared secret calculation into decode_next_payment_hop
2 parents cdc8e21 + 5291445 commit ef8868b

File tree

5 files changed

+146
-102
lines changed

5 files changed

+146
-102
lines changed

lightning/src/ln/blinded_payment_tests.rs

+6-6
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

+20-29
Original file line numberDiff line numberDiff line change
@@ -4436,27 +4436,16 @@ where
44364436
}
44374437
}
44384438
match decoded_hop {
4439-
onion_utils::Hop::Receive(next_hop_data) => {
4440-
// OUR PAYMENT!
4441-
let current_height: u32 = self.best_block.read().unwrap().height;
4442-
match create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive(next_hop_data), shared_secret, msg.payment_hash,
4443-
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
4444-
current_height)
4445-
{
4446-
Ok(info) => {
4447-
// Note that we could obviously respond immediately with an update_fulfill_htlc
4448-
// message, however that would leak that we are the recipient of this payment, so
4449-
// instead we stay symmetric with the forwarding case, only responding (after a
4450-
// delay) once they've send us a commitment_signed!
4451-
PendingHTLCStatus::Forward(info)
4452-
},
4453-
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4454-
}
4455-
},
4456-
onion_utils::Hop::BlindedReceive(next_hop_data) => {
4439+
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => {
4440+
let inbound_onion_payload = match decoded_hop {
4441+
onion_utils::Hop::Receive { hop_data, .. } => msgs::InboundOnionPayload::Receive(hop_data),
4442+
onion_utils::Hop::BlindedReceive { hop_data, .. } => msgs::InboundOnionPayload::BlindedReceive(hop_data),
4443+
_ => unreachable!()
4444+
};
4445+
44574446
// OUR PAYMENT!
44584447
let current_height: u32 = self.best_block.read().unwrap().height;
4459-
match create_recv_pending_htlc_info(msgs::InboundOnionPayload::BlindedReceive(next_hop_data), shared_secret, msg.payment_hash,
4448+
match create_recv_pending_htlc_info(inbound_onion_payload, shared_secret, msg.payment_hash,
44604449
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
44614450
current_height)
44624451
{
@@ -4470,14 +4459,14 @@ where
44704459
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44714460
}
44724461
},
4473-
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
4462+
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
44744463
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::Forward(next_hop_data), next_hop_hmac,
44754464
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
44764465
Ok(info) => PendingHTLCStatus::Forward(info),
44774466
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44784467
}
44794468
},
4480-
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
4469+
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
44814470
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::BlindedForward(next_hop_data), next_hop_hmac,
44824471
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
44834472
Ok(info) => PendingHTLCStatus::Forward(info),
@@ -5705,7 +5694,7 @@ where
57055694
let mut htlc_forwards = Vec::new();
57065695
let mut htlc_fails = Vec::new();
57075696
for update_add_htlc in &update_add_htlcs {
5708-
let (next_hop, shared_secret, next_packet_details_opt) = match decode_incoming_update_add_htlc_onion(
5697+
let (next_hop, next_packet_details_opt) = match decode_incoming_update_add_htlc_onion(
57095698
&update_add_htlc, &*self.node_signer, &*self.logger, &self.secp_ctx
57105699
) {
57115700
Ok(decoded_onion) => decoded_onion,
@@ -5717,6 +5706,7 @@ where
57175706

57185707
let is_intro_node_blinded_forward = next_hop.is_intro_node_blinded_forward();
57195708
let outgoing_scid_opt = next_packet_details_opt.as_ref().map(|d| d.outgoing_scid);
5709+
let shared_secret = next_hop.shared_secret().secret_bytes();
57205710

57215711
// Process the HTLC on the incoming channel.
57225712
match self.do_funded_channel_callback(incoming_scid, |chan: &mut FundedChannel<SP>| {
@@ -5875,10 +5865,9 @@ where
58755865
if let PendingHTLCRouting::Forward { ref onion_packet, .. } = routing {
58765866
let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode);
58775867
if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.chain_hash) {
5878-
let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
58795868
let next_hop = match onion_utils::decode_next_payment_hop(
5880-
phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac,
5881-
payment_hash, None, &*self.node_signer
5869+
Recipient::PhantomNode, &onion_packet.public_key.unwrap(), &onion_packet.hop_data,
5870+
onion_packet.hmac, payment_hash, None, &*self.node_signer
58825871
) {
58835872
Ok(res) => res,
58845873
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
@@ -5889,15 +5878,17 @@ where
58895878
// of the onion.
58905879
failed_payment!(err_msg, err_code, sha256_of_onion.to_vec(), None);
58915880
},
5892-
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code }) => {
5881+
Err(onion_utils::OnionDecodeErr::Relay { err_msg, err_code, shared_secret }) => {
5882+
let phantom_shared_secret = shared_secret.secret_bytes();
58935883
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
58945884
},
58955885
};
5896-
let inbound_onion_payload = match next_hop {
5897-
onion_utils::Hop::Receive(hop_data) => msgs::InboundOnionPayload::Receive(hop_data),
5898-
onion_utils::Hop::BlindedReceive(hop_data) => msgs::InboundOnionPayload::BlindedReceive(hop_data),
5886+
let (inbound_onion_payload, shared_secret) = match next_hop {
5887+
onion_utils::Hop::Receive { hop_data, shared_secret } => (msgs::InboundOnionPayload::Receive(hop_data), shared_secret),
5888+
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => (msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret),
58995889
_ => panic!()
59005890
};
5891+
let phantom_shared_secret = shared_secret.secret_bytes();
59015892
let current_height: u32 = self.best_block.read().unwrap().height;
59025893
match create_recv_pending_htlc_info(inbound_onion_payload,
59035894
incoming_shared_secret, payment_hash, outgoing_amt_msat,

lightning/src/ln/onion_payment.rs

+33-46
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)