Skip to content

Commit ee1514a

Browse files
committed
Use Hop instead of InboundOnionPayload
For pending HTLC info processing, we will later need to access both the outer and the Trampoline payloads. Thanks to the refactor eliminating invalid Hop states, this is now possible by accessing the Hop struct, which will carry both outer and Trampoline payload data when applicable.
1 parent 56caad8 commit ee1514a

File tree

2 files changed

+84
-104
lines changed

2 files changed

+84
-104
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 50 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4466,38 +4466,24 @@ where
44664466
}
44674467
match decoded_hop {
44684468
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => {
4469-
let inbound_onion_payload = match decoded_hop {
4470-
onion_utils::Hop::Receive { hop_data, .. } => msgs::InboundOnionPayload::Receive(hop_data),
4471-
onion_utils::Hop::BlindedReceive { hop_data, .. } => msgs::InboundOnionPayload::BlindedReceive(hop_data),
4472-
_ => unreachable!()
4473-
};
4474-
44754469
// OUR PAYMENT!
44764470
let current_height: u32 = self.best_block.read().unwrap().height;
4477-
match create_recv_pending_htlc_info(inbound_onion_payload, shared_secret, msg.payment_hash,
4471+
match create_recv_pending_htlc_info(decoded_hop, shared_secret, msg.payment_hash,
44784472
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
44794473
current_height)
44804474
{
44814475
Ok(info) => {
44824476
// Note that we could obviously respond immediately with an update_fulfill_htlc
44834477
// message, however that would leak that we are the recipient of this payment, so
44844478
// instead we stay symmetric with the forwarding case, only responding (after a
4485-
// delay) once they've send us a commitment_signed!
4479+
// delay) once they've sent us a commitment_signed!
44864480
PendingHTLCStatus::Forward(info)
44874481
},
44884482
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44894483
}
44904484
},
4491-
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4492-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::Forward(next_hop_data), next_hop_hmac,
4493-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4494-
Ok(info) => PendingHTLCStatus::Forward(info),
4495-
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4496-
}
4497-
},
4498-
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4499-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::BlindedForward(next_hop_data), next_hop_hmac,
4500-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4485+
onion_utils::Hop::Forward { .. } | onion_utils::Hop::BlindedForward { .. } => {
4486+
match create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) {
45014487
Ok(info) => PendingHTLCStatus::Forward(info),
45024488
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
45034489
}
@@ -5912,14 +5898,9 @@ where
59125898
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
59135899
},
59145900
};
5915-
let (inbound_onion_payload, shared_secret) = match next_hop {
5916-
onion_utils::Hop::Receive { hop_data, shared_secret } => (msgs::InboundOnionPayload::Receive(hop_data), shared_secret),
5917-
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => (msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret),
5918-
_ => panic!()
5919-
};
5920-
let phantom_shared_secret = shared_secret.secret_bytes();
5901+
let phantom_shared_secret = next_hop.shared_secret().secret_bytes();
59215902
let current_height: u32 = self.best_block.read().unwrap().height;
5922-
match create_recv_pending_htlc_info(inbound_onion_payload,
5903+
match create_recv_pending_htlc_info(next_hop,
59235904
incoming_shared_secret, payment_hash, outgoing_amt_msat,
59245905
outgoing_cltv_value, Some(phantom_shared_secret), false, None,
59255906
current_height)
@@ -14847,13 +14828,15 @@ where
1484714828
mod tests {
1484814829
use bitcoin::hashes::Hash;
1484914830
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
14831+
use bitcoin::secp256k1::ecdh::SharedSecret;
1485014832
use core::sync::atomic::Ordering;
1485114833
use crate::events::{Event, HTLCDestination, ClosureReason};
1485214834
use crate::ln::types::ChannelId;
1485314835
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
1485414836
use crate::ln::channelmanager::{create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, InterceptId, PaymentId, RecipientOnionFields};
1485514837
use crate::ln::functional_test_utils::*;
1485614838
use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, AcceptChannel, ErrorAction, MessageSendEvent};
14839+
use crate::ln::onion_utils;
1485714840
use crate::ln::outbound_payment::Retry;
1485814841
use crate::prelude::*;
1485914842
use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
@@ -15944,17 +15927,20 @@ mod tests {
1594415927
let node = create_network(1, &node_cfg, &node_chanmgr);
1594515928
let sender_intended_amt_msat = 100;
1594615929
let extra_fee_msat = 10;
15947-
let hop_data = msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
15948-
sender_intended_htlc_amt_msat: 100,
15949-
cltv_expiry_height: 42,
15950-
payment_metadata: None,
15951-
keysend_preimage: None,
15952-
payment_data: Some(msgs::FinalOnionHopData {
15953-
payment_secret: PaymentSecret([0; 32]),
15954-
total_msat: sender_intended_amt_msat,
15955-
}),
15956-
custom_tlvs: Vec::new(),
15957-
});
15930+
let hop_data = onion_utils::Hop::Receive {
15931+
hop_data: msgs::InboundOnionReceivePayload {
15932+
sender_intended_htlc_amt_msat: 100,
15933+
cltv_expiry_height: 42,
15934+
payment_metadata: None,
15935+
keysend_preimage: None,
15936+
payment_data: Some(msgs::FinalOnionHopData {
15937+
payment_secret: PaymentSecret([0; 32]),
15938+
total_msat: sender_intended_amt_msat,
15939+
}),
15940+
custom_tlvs: Vec::new(),
15941+
},
15942+
shared_secret: SharedSecret::from_bytes([0; 32]),
15943+
};
1595815944
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1595915945
// intended amount, we fail the payment.
1596015946
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
@@ -15967,17 +15953,20 @@ mod tests {
1596715953
} else { panic!(); }
1596815954

1596915955
// If amt_received + extra_fee is equal to the sender intended amount, we're fine.
15970-
let hop_data = msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
15971-
sender_intended_htlc_amt_msat: 100,
15972-
cltv_expiry_height: 42,
15973-
payment_metadata: None,
15974-
keysend_preimage: None,
15975-
payment_data: Some(msgs::FinalOnionHopData {
15976-
payment_secret: PaymentSecret([0; 32]),
15977-
total_msat: sender_intended_amt_msat,
15978-
}),
15979-
custom_tlvs: Vec::new(),
15980-
});
15956+
let hop_data = onion_utils::Hop::Receive {
15957+
hop_data: msgs::InboundOnionReceivePayload { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
15958+
sender_intended_htlc_amt_msat: 100,
15959+
cltv_expiry_height: 42,
15960+
payment_metadata: None,
15961+
keysend_preimage: None,
15962+
payment_data: Some(msgs::FinalOnionHopData {
15963+
payment_secret: PaymentSecret([0; 32]),
15964+
total_msat: sender_intended_amt_msat,
15965+
}),
15966+
custom_tlvs: Vec::new(),
15967+
},
15968+
shared_secret: SharedSecret::from_bytes([0; 32]),
15969+
};
1598115970
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1598215971
assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
1598315972
sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat),
@@ -15992,17 +15981,20 @@ mod tests {
1599215981
let node = create_network(1, &node_cfg, &node_chanmgr);
1599315982

1599415983
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
15995-
let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
15996-
sender_intended_htlc_amt_msat: 100,
15997-
cltv_expiry_height: TEST_FINAL_CLTV,
15998-
payment_metadata: None,
15999-
keysend_preimage: None,
16000-
payment_data: Some(msgs::FinalOnionHopData {
16001-
payment_secret: PaymentSecret([0; 32]),
16002-
total_msat: 100,
16003-
}),
16004-
custom_tlvs: Vec::new(),
16005-
}), [0; 32], PaymentHash([0; 32]), 100, TEST_FINAL_CLTV + 1, None, true, None, current_height);
15984+
let result = create_recv_pending_htlc_info(onion_utils::Hop::Receive {
15985+
hop_data: msgs::InboundOnionReceivePayload {
15986+
sender_intended_htlc_amt_msat: 100,
15987+
cltv_expiry_height: TEST_FINAL_CLTV,
15988+
payment_metadata: None,
15989+
keysend_preimage: None,
15990+
payment_data: Some(msgs::FinalOnionHopData {
15991+
payment_secret: PaymentSecret([0; 32]),
15992+
total_msat: 100,
15993+
}),
15994+
custom_tlvs: Vec::new(),
15995+
},
15996+
shared_secret: SharedSecret::from_bytes([0; 32]),
15997+
}, [0; 32], PaymentHash([0; 32]), 100, TEST_FINAL_CLTV + 1, None, true, None, current_height);
1600615998

1600715999
// Should not return an error as this condition:
1600816000
// https://github.com/lightning/bolts/blob/4dcc377209509b13cf89a4b91fde7d478f5b46d8/04-onion-routing.md?plain=1#L334

lightning/src/ln/onion_payment.rs

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWA
1515
use crate::types::features::BlindedHopFeatures;
1616
use crate::ln::msgs;
1717
use crate::ln::onion_utils;
18-
use crate::ln::onion_utils::{Hop, HTLCFailReason, INVALID_ONION_BLINDING};
18+
use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
1919
use crate::sign::{NodeSigner, Recipient};
2020
use crate::util::logger::Logger;
2121

@@ -61,28 +61,23 @@ fn check_blinded_forward(
6161
}
6262

6363
pub(super) fn create_fwd_pending_htlc_info(
64-
msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32],
65-
new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
64+
msg: &msgs::UpdateAddHTLC, hop_data: onion_utils::Hop, shared_secret: [u8; 32],
6665
next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
6766
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
6867
debug_assert!(next_packet_pubkey_opt.is_some());
69-
let outgoing_packet = msgs::OnionPacket {
70-
version: 0,
71-
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
72-
hop_data: new_packet_bytes,
73-
hmac: hop_hmac,
74-
};
7568

7669
let (
7770
short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
78-
next_blinding_override
71+
next_blinding_override, new_packet_bytes, next_hop_hmac
7972
) = match hop_data {
80-
msgs::InboundOnionPayload::Forward(msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }) =>
81-
(short_channel_id, amt_to_forward, outgoing_cltv_value, None, None),
82-
msgs::InboundOnionPayload::BlindedForward(msgs::InboundOnionBlindedForwardPayload {
73+
onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload {
74+
short_channel_id, amt_to_forward, outgoing_cltv_value
75+
}, new_packet_bytes, next_hop_hmac, .. } =>
76+
(short_channel_id, amt_to_forward, outgoing_cltv_value, None, None, new_packet_bytes, next_hop_hmac),
77+
onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload {
8378
short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
8479
next_blinding_override,
85-
}) => {
80+
}, new_packet_bytes, next_hop_hmac, .. } => {
8681
let (amt_to_forward, outgoing_cltv_value) = check_blinded_forward(
8782
msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
8883
).map_err(|()| {
@@ -95,16 +90,23 @@ pub(super) fn create_fwd_pending_htlc_info(
9590
}
9691
})?;
9792
(short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
98-
next_blinding_override)
93+
next_blinding_override, new_packet_bytes, next_hop_hmac)
9994
},
100-
msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } =>
95+
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } =>
10196
return Err(InboundHTLCErr {
10297
msg: "Final Node OnionHopData provided for us as an intermediary node",
10398
err_code: 0x4000 | 22,
10499
err_data: Vec::new(),
105100
}),
106101
};
107102

103+
let outgoing_packet = msgs::OnionPacket {
104+
version: 0,
105+
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
106+
hop_data: new_packet_bytes,
107+
hmac: next_hop_hmac,
108+
};
109+
108110
Ok(PendingHTLCInfo {
109111
routing: PendingHTLCRouting::Forward {
110112
onion_packet: outgoing_packet,
@@ -129,7 +131,7 @@ pub(super) fn create_fwd_pending_htlc_info(
129131
}
130132

131133
pub(super) fn create_recv_pending_htlc_info(
132-
hop_data: msgs::InboundOnionPayload, shared_secret: [u8; 32], payment_hash: PaymentHash,
134+
hop_data: onion_utils::Hop, shared_secret: [u8; 32], payment_hash: PaymentHash,
133135
amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
134136
counterparty_skimmed_fee_msat: Option<u64>, current_height: u32
135137
) -> Result<PendingHTLCInfo, InboundHTLCErr> {
@@ -138,17 +140,17 @@ pub(super) fn create_recv_pending_htlc_info(
138140
payment_metadata, payment_context, requires_blinded_error, has_recipient_created_payment_secret,
139141
invoice_request
140142
) = match hop_data {
141-
msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
143+
onion_utils::Hop::Receive { hop_data: msgs::InboundOnionReceivePayload {
142144
payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
143145
cltv_expiry_height, payment_metadata, ..
144-
}) =>
146+
}, .. } =>
145147
(payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
146148
cltv_expiry_height, payment_metadata, None, false, keysend_preimage.is_none(), None),
147-
msgs::InboundOnionPayload::BlindedReceive(msgs::InboundOnionBlindedReceivePayload {
149+
onion_utils::Hop::BlindedReceive { hop_data: msgs::InboundOnionBlindedReceivePayload {
148150
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
149151
intro_node_blinding_point, payment_constraints, payment_context, keysend_preimage,
150152
custom_tlvs, invoice_request
151-
}) => {
153+
}, .. } => {
152154
check_blinded_payment_constraints(
153155
sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints
154156
)
@@ -164,20 +166,20 @@ pub(super) fn create_recv_pending_htlc_info(
164166
sender_intended_htlc_amt_msat, cltv_expiry_height, None, Some(payment_context),
165167
intro_node_blinding_point.is_none(), true, invoice_request)
166168
}
167-
msgs::InboundOnionPayload::Forward { .. } => {
169+
onion_utils::Hop::Forward { .. } => {
168170
return Err(InboundHTLCErr {
169171
err_code: 0x4000|22,
170172
err_data: Vec::new(),
171173
msg: "Got non final data with an HMAC of 0",
172174
})
173175
},
174-
msgs::InboundOnionPayload::BlindedForward { .. } => {
176+
onion_utils::Hop::BlindedForward { .. } => {
175177
return Err(InboundHTLCErr {
176178
err_code: INVALID_ONION_BLINDING,
177179
err_data: vec![0; 32],
178180
msg: "Got blinded non final data with an HMAC of 0",
179181
})
180-
}
182+
},
181183
};
182184
// final_incorrect_cltv_expiry
183185
if onion_cltv_expiry > cltv_expiry {
@@ -295,14 +297,8 @@ where
295297
InboundHTLCErr { msg, err_code, err_data }
296298
})?;
297299
Ok(match hop {
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, .. } => {
300-
let inbound_onion_payload = match hop {
301-
onion_utils::Hop::Forward { next_hop_data, .. } => msgs::InboundOnionPayload::Forward(next_hop_data),
302-
onion_utils::Hop::BlindedForward { next_hop_data, .. } => msgs::InboundOnionPayload::BlindedForward(next_hop_data),
303-
_ => unreachable!()
304-
};
305-
300+
onion_utils::Hop::Forward { shared_secret, .. } |
301+
onion_utils::Hop::BlindedForward { shared_secret, .. } => {
306302
let NextPacketDetails {
307303
next_packet_pubkey, outgoing_amt_msat: _, outgoing_scid: _, outgoing_cltv_value
308304
} = match next_packet_details_opt {
@@ -327,20 +323,12 @@ where
327323

328324
// TODO: If this is potentially a phantom payment we should decode the phantom payment
329325
// onion here and check it.
330-
create_fwd_pending_htlc_info(
331-
msg, inbound_onion_payload, next_hop_hmac, new_packet_bytes, shared_secret.secret_bytes(),
332-
Some(next_packet_pubkey),
333-
)?
334-
},
335-
onion_utils::Hop::Receive { hop_data, shared_secret } => {
336-
create_recv_pending_htlc_info(
337-
msgs::InboundOnionPayload::Receive(hop_data), shared_secret.secret_bytes(), msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
338-
None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height,
339-
)?
326+
create_fwd_pending_htlc_info(msg, hop, shared_secret.secret_bytes(), Some(next_packet_pubkey))?
340327
},
341-
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => {
328+
_ => {
329+
let shared_secret = hop.shared_secret().secret_bytes();
342330
create_recv_pending_htlc_info(
343-
msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret.secret_bytes(), msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
331+
hop, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
344332
None, allow_skimmed_fees, msg.skimmed_fee_msat, cur_height,
345333
)?
346334
}
@@ -422,15 +410,15 @@ where
422410
};
423411

424412
let next_packet_details = match next_hop {
425-
Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, shared_secret, .. } => {
413+
onion_utils::Hop::Forward { next_hop_data: msgs::InboundOnionForwardPayload { short_channel_id, amt_to_forward, outgoing_cltv_value }, shared_secret, .. } => {
426414
let next_packet_pubkey = onion_utils::next_hop_pubkey(secp_ctx,
427415
msg.onion_routing_packet.public_key.unwrap(), &shared_secret.secret_bytes());
428416
Some(NextPacketDetails {
429417
next_packet_pubkey, outgoing_scid: short_channel_id,
430418
outgoing_amt_msat: amt_to_forward, outgoing_cltv_value
431419
})
432420
}
433-
Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, shared_secret, .. } => {
421+
onion_utils::Hop::BlindedForward { next_hop_data: msgs::InboundOnionBlindedForwardPayload { short_channel_id, ref payment_relay, ref payment_constraints, ref features, .. }, shared_secret, .. } => {
434422
let (amt_to_forward, outgoing_cltv_value) = match check_blinded_forward(
435423
msg.amount_msat, msg.cltv_expiry, &payment_relay, &payment_constraints, &features
436424
) {

0 commit comments

Comments
 (0)