Skip to content

Commit 7d6bbbc

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 47f02f1 commit 7d6bbbc

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
@@ -4451,38 +4451,24 @@ where
44514451
}
44524452
match decoded_hop {
44534453
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => {
4454-
let inbound_onion_payload = match decoded_hop {
4455-
onion_utils::Hop::Receive { hop_data, .. } => msgs::InboundOnionPayload::Receive(hop_data),
4456-
onion_utils::Hop::BlindedReceive { hop_data, .. } => msgs::InboundOnionPayload::BlindedReceive(hop_data),
4457-
_ => unreachable!()
4458-
};
4459-
44604454
// OUR PAYMENT!
44614455
let current_height: u32 = self.best_block.read().unwrap().height;
4462-
match create_recv_pending_htlc_info(inbound_onion_payload, shared_secret, msg.payment_hash,
4456+
match create_recv_pending_htlc_info(decoded_hop, shared_secret, msg.payment_hash,
44634457
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
44644458
current_height)
44654459
{
44664460
Ok(info) => {
44674461
// Note that we could obviously respond immediately with an update_fulfill_htlc
44684462
// message, however that would leak that we are the recipient of this payment, so
44694463
// instead we stay symmetric with the forwarding case, only responding (after a
4470-
// delay) once they've send us a commitment_signed!
4464+
// delay) once they've sent us a commitment_signed!
44714465
PendingHTLCStatus::Forward(info)
44724466
},
44734467
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44744468
}
44754469
},
4476-
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4477-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::Forward(next_hop_data), next_hop_hmac,
4478-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4479-
Ok(info) => PendingHTLCStatus::Forward(info),
4480-
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4481-
}
4482-
},
4483-
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4484-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::BlindedForward(next_hop_data), next_hop_hmac,
4485-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4470+
onion_utils::Hop::Forward { .. } | onion_utils::Hop::BlindedForward { .. } => {
4471+
match create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) {
44864472
Ok(info) => PendingHTLCStatus::Forward(info),
44874473
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44884474
}
@@ -5897,14 +5883,9 @@ where
58975883
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
58985884
},
58995885
};
5900-
let (inbound_onion_payload, shared_secret) = match next_hop {
5901-
onion_utils::Hop::Receive { hop_data, shared_secret } => (msgs::InboundOnionPayload::Receive(hop_data), shared_secret),
5902-
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => (msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret),
5903-
_ => panic!()
5904-
};
5905-
let phantom_shared_secret = shared_secret.secret_bytes();
5886+
let phantom_shared_secret = next_hop.shared_secret().secret_bytes();
59065887
let current_height: u32 = self.best_block.read().unwrap().height;
5907-
match create_recv_pending_htlc_info(inbound_onion_payload,
5888+
match create_recv_pending_htlc_info(next_hop,
59085889
incoming_shared_secret, payment_hash, outgoing_amt_msat,
59095890
outgoing_cltv_value, Some(phantom_shared_secret), false, None,
59105891
current_height)
@@ -14832,13 +14813,15 @@ where
1483214813
mod tests {
1483314814
use bitcoin::hashes::Hash;
1483414815
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
14816+
use bitcoin::secp256k1::ecdh::SharedSecret;
1483514817
use core::sync::atomic::Ordering;
1483614818
use crate::events::{Event, HTLCDestination, ClosureReason};
1483714819
use crate::ln::types::ChannelId;
1483814820
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
1483914821
use crate::ln::channelmanager::{create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, InterceptId, PaymentId, RecipientOnionFields};
1484014822
use crate::ln::functional_test_utils::*;
1484114823
use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, AcceptChannel, ErrorAction, MessageSendEvent};
14824+
use crate::ln::onion_utils;
1484214825
use crate::ln::outbound_payment::Retry;
1484314826
use crate::prelude::*;
1484414827
use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
@@ -15929,17 +15912,20 @@ mod tests {
1592915912
let node = create_network(1, &node_cfg, &node_chanmgr);
1593015913
let sender_intended_amt_msat = 100;
1593115914
let extra_fee_msat = 10;
15932-
let hop_data = msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
15933-
sender_intended_htlc_amt_msat: 100,
15934-
cltv_expiry_height: 42,
15935-
payment_metadata: None,
15936-
keysend_preimage: None,
15937-
payment_data: Some(msgs::FinalOnionHopData {
15938-
payment_secret: PaymentSecret([0; 32]),
15939-
total_msat: sender_intended_amt_msat,
15940-
}),
15941-
custom_tlvs: Vec::new(),
15942-
});
15915+
let hop_data = onion_utils::Hop::Receive {
15916+
hop_data: msgs::InboundOnionReceivePayload {
15917+
sender_intended_htlc_amt_msat: 100,
15918+
cltv_expiry_height: 42,
15919+
payment_metadata: None,
15920+
keysend_preimage: None,
15921+
payment_data: Some(msgs::FinalOnionHopData {
15922+
payment_secret: PaymentSecret([0; 32]),
15923+
total_msat: sender_intended_amt_msat,
15924+
}),
15925+
custom_tlvs: Vec::new(),
15926+
},
15927+
shared_secret: SharedSecret::from_bytes([0; 32]),
15928+
};
1594315929
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1594415930
// intended amount, we fail the payment.
1594515931
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
@@ -15952,17 +15938,20 @@ mod tests {
1595215938
} else { panic!(); }
1595315939

1595415940
// If amt_received + extra_fee is equal to the sender intended amount, we're fine.
15955-
let hop_data = msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
15956-
sender_intended_htlc_amt_msat: 100,
15957-
cltv_expiry_height: 42,
15958-
payment_metadata: None,
15959-
keysend_preimage: None,
15960-
payment_data: Some(msgs::FinalOnionHopData {
15961-
payment_secret: PaymentSecret([0; 32]),
15962-
total_msat: sender_intended_amt_msat,
15963-
}),
15964-
custom_tlvs: Vec::new(),
15965-
});
15941+
let hop_data = onion_utils::Hop::Receive {
15942+
hop_data: msgs::InboundOnionReceivePayload { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
15943+
sender_intended_htlc_amt_msat: 100,
15944+
cltv_expiry_height: 42,
15945+
payment_metadata: None,
15946+
keysend_preimage: None,
15947+
payment_data: Some(msgs::FinalOnionHopData {
15948+
payment_secret: PaymentSecret([0; 32]),
15949+
total_msat: sender_intended_amt_msat,
15950+
}),
15951+
custom_tlvs: Vec::new(),
15952+
},
15953+
shared_secret: SharedSecret::from_bytes([0; 32]),
15954+
};
1596615955
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
1596715956
assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
1596815957
sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat),
@@ -15977,17 +15966,20 @@ mod tests {
1597715966
let node = create_network(1, &node_cfg, &node_chanmgr);
1597815967

1597915968
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
15980-
let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
15981-
sender_intended_htlc_amt_msat: 100,
15982-
cltv_expiry_height: 22,
15983-
payment_metadata: None,
15984-
keysend_preimage: None,
15985-
payment_data: Some(msgs::FinalOnionHopData {
15986-
payment_secret: PaymentSecret([0; 32]),
15987-
total_msat: 100,
15988-
}),
15989-
custom_tlvs: Vec::new(),
15990-
}), [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height);
15969+
let result = create_recv_pending_htlc_info(onion_utils::Hop::Receive {
15970+
hop_data: msgs::InboundOnionReceivePayload {
15971+
sender_intended_htlc_amt_msat: 100,
15972+
cltv_expiry_height: 22,
15973+
payment_metadata: None,
15974+
keysend_preimage: None,
15975+
payment_data: Some(msgs::FinalOnionHopData {
15976+
payment_secret: PaymentSecret([0; 32]),
15977+
total_msat: 100,
15978+
}),
15979+
custom_tlvs: Vec::new(),
15980+
},
15981+
shared_secret: SharedSecret::from_bytes([0; 32]),
15982+
}, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height);
1599115983

1599215984
// Should not return an error as this condition:
1599315985
// 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)