From e4e6e09b672dc929b4d8571975bd923a7a4486be Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Mon, 15 Apr 2024 14:02:45 -0400 Subject: [PATCH 1/1] OutboundOnionPayload: hold Vec fields as references. Will be useful when we reuse this enum to calculate the maximum path length, to avoid cloning the vecs. --- lightning/src/ln/blinded_payment_tests.rs | 6 +++-- lightning/src/ln/functional_tests.rs | 18 +++++++++----- lightning/src/ln/msgs.rs | 30 +++++++++++------------ lightning/src/ln/onion_payment.rs | 2 +- lightning/src/ln/onion_route_tests.rs | 15 ++++++++---- lightning/src/ln/onion_utils.rs | 26 +++++++++----------- 6 files changed, 54 insertions(+), 43 deletions(-) diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index 12e91b421..998c7a33d 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -298,11 +298,12 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) { $update_add.cltv_expiry = 10; // causes outbound CLTV expiry to underflow }, ForwardCheckFail::ForwardPayloadEncodedAsReceive => { + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); let cur_height = nodes[0].best_block_info().1; let (mut onion_payloads, ..) = onion_utils::build_onion_payloads( - &route.paths[0], amt_msat, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], amt_msat, &recipient_onion_fields, cur_height, &None).unwrap(); // Remove the receive payload so the blinded forward payload is encoded as a final payload // (i.e. next_hop_hmac == [0; 32]) onion_payloads.pop(); @@ -875,8 +876,9 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) { let session_priv = SecretKey::from_slice(&session_priv).unwrap(); let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); let cur_height = nodes[0].best_block_info().1; + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (mut onion_payloads, ..) = onion_utils::build_onion_payloads( - &route.paths[0], amt_msat, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], amt_msat, &recipient_onion_fields, cur_height, &None).unwrap(); let update_add = &mut payment_event_1_2.msgs[0]; onion_payloads.last_mut().map(|p| { diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index df55430d7..5b1420e3d 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -1401,8 +1401,9 @@ fn test_fee_spike_violation_fails_htlc() { let cur_height = nodes[1].node.best_block.read().unwrap().height + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 3460001, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); + 3460001, &recipient_onion_fields, cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -1598,8 +1599,9 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[1].node.best_block.read().unwrap().height + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], - 700_000, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); + 700_000, &recipient_onion_fields, cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -1777,8 +1779,9 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[0].node.best_block.read().unwrap().height + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route_2.paths[0], recv_value_2, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route_2.paths[0], recv_value_2, &recipient_onion_fields, cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash_1).unwrap(); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -3501,8 +3504,9 @@ fn fail_backward_pending_htlc_upon_channel_failure() { let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let current_height = nodes[1].node.best_block.read().unwrap().height + 1; + let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads( - &route.paths[0], 50_000, RecipientOnionFields::secret_only(payment_secret), current_height, &None).unwrap(); + &route.paths[0], 50_000, &recipient_onion_fields, current_height, &None).unwrap(); let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); @@ -6487,8 +6491,9 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[0].node.best_block.read().unwrap().height + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret); let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], send_amt, RecipientOnionFields::secret_only(our_payment_secret), cur_height, &None).unwrap(); + &route.paths[0], send_amt, &recipient_onion_fields, cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap(); let mut msg = msgs::UpdateAddHTLC { @@ -8222,8 +8227,9 @@ fn test_onion_value_mpp_set_calculation() { let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret); let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, - RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap(); + &recipient_onion_fields, height + 1, &None).unwrap(); // Edit amt_to_forward to simulate the sender having set // the final amount and the routing node taking less fee if let msgs::OutboundOnionPayload::Receive { diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 87e8a814d..6cfc55069 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1723,7 +1723,7 @@ mod fuzzy_internal_msgs { } } - pub(crate) enum OutboundOnionPayload { + pub(crate) enum OutboundOnionPayload<'a> { Forward { short_channel_id: u64, /// The value, in msat, of the payment after this hop's fee is deducted. @@ -1739,24 +1739,24 @@ mod fuzzy_internal_msgs { }, Receive { payment_data: Option, - payment_metadata: Option>, + payment_metadata: Option<&'a Vec>, keysend_preimage: Option, - custom_tlvs: Vec<(u64, Vec)>, + custom_tlvs: &'a Vec<(u64, Vec)>, sender_intended_htlc_amt_msat: u64, cltv_expiry_height: u32, }, BlindedForward { - encrypted_tlvs: Vec, + encrypted_tlvs: &'a Vec, intro_node_blinding_point: Option, }, BlindedReceive { sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32, - encrypted_tlvs: Vec, + encrypted_tlvs: &'a Vec, intro_node_blinding_point: Option, // Set if the introduction node of the blinded path is the final node keysend_preimage: Option, - custom_tlvs: Vec<(u64, Vec)>, + custom_tlvs: &'a Vec<(u64, Vec)>, } } @@ -2569,7 +2569,7 @@ impl Readable for FinalOnionHopData { } } -impl Writeable for OutboundOnionPayload { +impl<'a> Writeable for OutboundOnionPayload<'a> { fn write(&self, w: &mut W) -> Result<(), io::Error> { match self { Self::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } => { @@ -2604,12 +2604,12 @@ impl Writeable for OutboundOnionPayload { (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required), (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required), (8, payment_data, option), - (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option) + (16, payment_metadata.map(|m| WithoutLength(m)), option) }, custom_tlvs.iter()); }, Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point } => { _encode_varint_length_prefixed_tlv!(w, { - (10, *encrypted_tlvs, required_vec), + (10, **encrypted_tlvs, required_vec), (12, intro_node_blinding_point, option) }); }, @@ -2626,7 +2626,7 @@ impl Writeable for OutboundOnionPayload { _encode_varint_length_prefixed_tlv!(w, { (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required), (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required), - (10, *encrypted_tlvs, required_vec), + (10, **encrypted_tlvs, required_vec), (12, intro_node_blinding_point, option), (18, HighZeroBytesDroppedBigSize(*total_msat), required) }, custom_tlvs.iter()); @@ -4359,7 +4359,7 @@ mod tests { keysend_preimage: None, sender_intended_htlc_amt_msat: 0x0badf00d01020304, cltv_expiry_height: 0xffffffff, - custom_tlvs: vec![], + custom_tlvs: &vec![], }; let encoded_value = outbound_msg.encode(); let target_value = >::from_hex("1002080badf00d010203040404ffffffff").unwrap(); @@ -4387,7 +4387,7 @@ mod tests { keysend_preimage: None, sender_intended_htlc_amt_msat: 0x0badf00d01020304, cltv_expiry_height: 0xffffffff, - custom_tlvs: vec![], + custom_tlvs: &vec![], }; let encoded_value = outbound_msg.encode(); let target_value = >::from_hex("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap(); @@ -4424,7 +4424,7 @@ mod tests { payment_data: None, payment_metadata: None, keysend_preimage: None, - custom_tlvs: bad_type_range_tlvs, + custom_tlvs: &bad_type_range_tlvs, sender_intended_htlc_amt_msat: 0x0badf00d01020304, cltv_expiry_height: 0xffffffff, }; @@ -4436,7 +4436,7 @@ mod tests { ((1 << 16) - 1, vec![42; 32]), ]; if let msgs::OutboundOnionPayload::Receive { ref mut custom_tlvs, .. } = msg { - *custom_tlvs = good_type_range_tlvs.clone(); + *custom_tlvs = &good_type_range_tlvs; } let encoded_value = msg.encode(); let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), (None, &&node_signer)).unwrap(); @@ -4456,7 +4456,7 @@ mod tests { payment_data: None, payment_metadata: None, keysend_preimage: None, - custom_tlvs: expected_custom_tlvs.clone(), + custom_tlvs: &expected_custom_tlvs, sender_intended_htlc_amt_msat: 0x0badf00d01020304, cltv_expiry_height: 0xffffffff, }; diff --git a/lightning/src/ln/onion_payment.rs b/lightning/src/ln/onion_payment.rs index 20a1e1dbb..0886bf8f2 100644 --- a/lightning/src/ln/onion_payment.rs +++ b/lightning/src/ln/onion_payment.rs @@ -536,7 +536,7 @@ mod tests { let path = Path { hops, blinded_tail: None, }; let onion_keys = super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv).unwrap(); let (onion_payloads, ..) = super::onion_utils::build_onion_payloads( - &path, total_amt_msat, recipient_onion, cur_height + 1, &Some(keysend_preimage) + &path, total_amt_msat, &recipient_onion, cur_height + 1, &Some(keysend_preimage) ).unwrap(); assert!(super::onion_utils::construct_onion_packet( diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index f49847300..c5ce3e051 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -357,8 +357,9 @@ fn test_onion_failure() { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); let cur_height = nodes[0].best_block_info().1 + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None).unwrap(); let mut new_payloads = Vec::new(); for payload in onion_payloads.drain(..) { new_payloads.push(BogusOnionHopData::new(payload)); @@ -375,8 +376,9 @@ fn test_onion_failure() { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); let cur_height = nodes[0].best_block_info().1 + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None).unwrap(); let mut new_payloads = Vec::new(); for payload in onion_payloads.drain(..) { new_payloads.push(BogusOnionHopData::new(payload)); @@ -612,8 +614,9 @@ fn test_onion_failure() { let height = nodes[2].best_block_info().1; route.paths[0].hops[1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0].hops[0].cltv_expiry_delta + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), height, &None).unwrap(); + &route.paths[0], 40000, &recipient_onion_fields, height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash).unwrap(); msg.cltv_expiry = htlc_cltv; msg.onion_routing_packet = onion_packet; @@ -948,8 +951,9 @@ fn test_always_create_tlv_format_onion_payloads() { assert!(!hops[1].node_features.supports_variable_length_onion()); let cur_height = nodes[0].best_block_info().1 + 1; + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( - &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); + &route.paths[0], 40000, &recipient_onion_fields, cur_height, &None).unwrap(); match onion_payloads[0] { msgs::OutboundOnionPayload::Forward {..} => {}, @@ -1203,9 +1207,10 @@ fn test_phantom_invalid_onion_payload() { let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret); let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( &route.paths[0], msgs::MAX_VALUE_MSAT + 1, - RecipientOnionFields::secret_only(payment_secret), height + 1, &None).unwrap(); + &recipient_onion_fields, height + 1, &None).unwrap(); // We only want to construct the onion packet for the last hop, not the entire route, so // remove the first hop's payload and its keys. onion_keys.remove(0); diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 0abcb7de2..9b96726f8 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -174,10 +174,10 @@ pub(super) fn construct_onion_keys( } /// returns the hop data, as well as the first-hop value_msat and CLTV value we should send. -pub(super) fn build_onion_payloads( - path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, +pub(super) fn build_onion_payloads<'a>( + path: &'a Path, total_msat: u64, recipient_onion: &'a RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option, -) -> Result<(Vec, u64, u32), APIError> { +) -> Result<(Vec>, u64, u32), APIError> { let mut cur_value_msat = 0u64; let mut cur_cltv = starting_htlc_offset; let mut last_short_channel_id = 0; @@ -212,28 +212,26 @@ pub(super) fn build_onion_payloads( sender_intended_htlc_amt_msat: *final_value_msat, total_msat, cltv_expiry_height: cur_cltv + excess_final_cltv_expiry_delta, - encrypted_tlvs: blinded_hop.encrypted_payload.clone(), + encrypted_tlvs: &blinded_hop.encrypted_payload, intro_node_blinding_point: blinding_point.take(), keysend_preimage: *keysend_preimage, - custom_tlvs: recipient_onion.custom_tlvs.clone(), + custom_tlvs: &recipient_onion.custom_tlvs, }); } else { res.push(msgs::OutboundOnionPayload::BlindedForward { - encrypted_tlvs: blinded_hop.encrypted_payload.clone(), + encrypted_tlvs: &blinded_hop.encrypted_payload, intro_node_blinding_point: blinding_point.take(), }); } } } else { res.push(msgs::OutboundOnionPayload::Receive { - payment_data: if let Some(secret) = recipient_onion.payment_secret.take() { - Some(msgs::FinalOnionHopData { payment_secret: secret, total_msat }) - } else { - None - }, - payment_metadata: recipient_onion.payment_metadata.take(), + payment_data: recipient_onion.payment_secret.map(|payment_secret| { + msgs::FinalOnionHopData { payment_secret, total_msat } + }), + payment_metadata: recipient_onion.payment_metadata.as_ref(), keysend_preimage: *keysend_preimage, - custom_tlvs: recipient_onion.custom_tlvs.clone(), + custom_tlvs: &recipient_onion.custom_tlvs, sender_intended_htlc_amt_msat: value_msat, cltv_expiry_height: cltv, }); @@ -1133,7 +1131,7 @@ pub fn create_payment_onion( let (onion_payloads, htlc_msat, htlc_cltv) = build_onion_payloads( &path, total_msat, - recipient_onion, + &recipient_onion, cur_block_height, keysend_preimage, )?; -- 2.39.5