Skip to content

Commit 69ed894

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 98a5db3 commit 69ed894

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
@@ -4453,38 +4453,24 @@ where
44534453
}
44544454
match decoded_hop {
44554455
onion_utils::Hop::Receive { .. } | onion_utils::Hop::BlindedReceive { .. } => {
4456-
let inbound_onion_payload = match decoded_hop {
4457-
onion_utils::Hop::Receive { hop_data, .. } => msgs::InboundOnionPayload::Receive(hop_data),
4458-
onion_utils::Hop::BlindedReceive { hop_data, .. } => msgs::InboundOnionPayload::BlindedReceive(hop_data),
4459-
_ => unreachable!()
4460-
};
4461-
44624456
// OUR PAYMENT!
44634457
let current_height: u32 = self.best_block.read().unwrap().height;
4464-
match create_recv_pending_htlc_info(inbound_onion_payload, shared_secret, msg.payment_hash,
4458+
match create_recv_pending_htlc_info(decoded_hop, shared_secret, msg.payment_hash,
44654459
msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat,
44664460
current_height)
44674461
{
44684462
Ok(info) => {
44694463
// Note that we could obviously respond immediately with an update_fulfill_htlc
44704464
// message, however that would leak that we are the recipient of this payment, so
44714465
// instead we stay symmetric with the forwarding case, only responding (after a
4472-
// delay) once they've send us a commitment_signed!
4466+
// delay) once they've sent us a commitment_signed!
44734467
PendingHTLCStatus::Forward(info)
44744468
},
44754469
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44764470
}
44774471
},
4478-
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4479-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::Forward(next_hop_data), next_hop_hmac,
4480-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4481-
Ok(info) => PendingHTLCStatus::Forward(info),
4482-
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
4483-
}
4484-
},
4485-
onion_utils::Hop::BlindedForward { next_hop_data, next_hop_hmac, new_packet_bytes, .. } => {
4486-
match create_fwd_pending_htlc_info(msg, msgs::InboundOnionPayload::BlindedForward(next_hop_data), next_hop_hmac,
4487-
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
4472+
onion_utils::Hop::Forward { .. } | onion_utils::Hop::BlindedForward { .. } => {
4473+
match create_fwd_pending_htlc_info(msg, decoded_hop, shared_secret, next_packet_pubkey_opt) {
44884474
Ok(info) => PendingHTLCStatus::Forward(info),
44894475
Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
44904476
}
@@ -5899,14 +5885,9 @@ where
58995885
failed_payment!(err_msg, err_code, Vec::new(), Some(phantom_shared_secret));
59005886
},
59015887
};
5902-
let (inbound_onion_payload, shared_secret) = match next_hop {
5903-
onion_utils::Hop::Receive { hop_data, shared_secret } => (msgs::InboundOnionPayload::Receive(hop_data), shared_secret),
5904-
onion_utils::Hop::BlindedReceive { hop_data, shared_secret } => (msgs::InboundOnionPayload::BlindedReceive(hop_data), shared_secret),
5905-
_ => panic!()
5906-
};
5907-
let phantom_shared_secret = shared_secret.secret_bytes();
5888+
let phantom_shared_secret = next_hop.shared_secret().secret_bytes();
59085889
let current_height: u32 = self.best_block.read().unwrap().height;
5909-
match create_recv_pending_htlc_info(inbound_onion_payload,
5890+
match create_recv_pending_htlc_info(next_hop,
59105891
incoming_shared_secret, payment_hash, outgoing_amt_msat,
59115892
outgoing_cltv_value, Some(phantom_shared_secret), false, None,
59125893
current_height)
@@ -14853,13 +14834,15 @@ mod tests {
1485314834
use bitcoin::hashes::Hash;
1485414835
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1485514836
use core::sync::atomic::Ordering;
14837+
use bitcoin::secp256k1::ecdh::SharedSecret;
1485614838
use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
1485714839
use crate::ln::types::ChannelId;
1485814840
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
1485914841
use crate::ln::channelmanager::{create_recv_pending_htlc_info, inbound_payment, ChannelConfigOverrides, HTLCForwardInfo, InterceptId, PaymentId, RecipientOnionFields};
1486014842
use crate::ln::functional_test_utils::*;
1486114843
use crate::ln::msgs::{self, AcceptChannel, ErrorAction};
1486214844
use crate::ln::msgs::ChannelMessageHandler;
14845+
use crate::ln::onion_utils;
1486314846
use crate::ln::outbound_payment::Retry;
1486414847
use crate::prelude::*;
1486514848
use crate::routing::router::{PaymentParameters, RouteParameters, find_route};
@@ -15950,17 +15933,20 @@ mod tests {
1595015933
let node = create_network(1, &node_cfg, &node_chanmgr);
1595115934
let sender_intended_amt_msat = 100;
1595215935
let extra_fee_msat = 10;
15953-
let hop_data = msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
15954-
sender_intended_htlc_amt_msat: 100,
15955-
cltv_expiry_height: 42,
15956-
payment_metadata: None,
15957-
keysend_preimage: None,
15958-
payment_data: Some(msgs::FinalOnionHopData {
15959-
payment_secret: PaymentSecret([0; 32]),
15960-
total_msat: sender_intended_amt_msat,
15961-
}),
15962-
custom_tlvs: Vec::new(),
15963-
});
15936+
let hop_data = onion_utils::Hop::Receive {
15937+
hop_data: msgs::InboundOnionReceivePayload {
15938+
sender_intended_htlc_amt_msat: 100,
15939+
cltv_expiry_height: 42,
15940+
payment_metadata: None,
15941+
keysend_preimage: None,
15942+
payment_data: Some(msgs::FinalOnionHopData {
15943+
payment_secret: PaymentSecret([0; 32]),
15944+
total_msat: sender_intended_amt_msat,
15945+
}),
15946+
custom_tlvs: Vec::new(),
15947+
},
15948+
shared_secret: SharedSecret::from_bytes([0; 32]),
15949+
};
1596415950
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1596515951
// intended amount, we fail the payment.
1596615952
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
@@ -15973,17 +15959,20 @@ mod tests {
1597315959
} else { panic!(); }
1597415960

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

1600015989
let current_height: u32 = node[0].node.best_block.read().unwrap().height;
16001-
let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive(msgs::InboundOnionReceivePayload {
16002-
sender_intended_htlc_amt_msat: 100,
16003-
cltv_expiry_height: 22,
16004-
payment_metadata: None,
16005-
keysend_preimage: None,
16006-
payment_data: Some(msgs::FinalOnionHopData {
16007-
payment_secret: PaymentSecret([0; 32]),
16008-
total_msat: 100,
16009-
}),
16010-
custom_tlvs: Vec::new(),
16011-
}), [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height);
15990+
let result = create_recv_pending_htlc_info(onion_utils::Hop::Receive {
15991+
hop_data: msgs::InboundOnionReceivePayload {
15992+
sender_intended_htlc_amt_msat: 100,
15993+
cltv_expiry_height: 22,
15994+
payment_metadata: None,
15995+
keysend_preimage: None,
15996+
payment_data: Some(msgs::FinalOnionHopData {
15997+
payment_secret: PaymentSecret([0; 32]),
15998+
total_msat: 100,
15999+
}),
16000+
custom_tlvs: Vec::new(),
16001+
},
16002+
shared_secret: SharedSecret::from_bytes([0; 32]),
16003+
}, [0; 32], PaymentHash([0; 32]), 100, 23, None, true, None, current_height);
1601216004

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