Replace OnionHopData with OutboundPayload for outbound onions
authorValentine Wallace <vwallace@protonmail.com>
Fri, 24 Mar 2023 18:35:52 +0000 (14:35 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Wed, 2 Aug 2023 19:54:41 +0000 (12:54 -0700)
Follows on from the previous commit, see its message

lightning/src/ln/functional_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/ln/onion_utils.rs

index 271ff541a84981733090b30600956886c2845d40..474735f253a9077708b4532bf54cd1a32d723330 100644 (file)
@@ -8039,7 +8039,9 @@ fn test_onion_value_mpp_set_calculation() {
                                RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap();
                        // Edit amt_to_forward to simulate the sender having set
                        // the final amount and the routing node taking less fee
-                       onion_payloads[1].amt_to_forward = 99_000;
+                       if let msgs::OutboundOnionPayload::Receive { ref mut amt_msat, .. } = onion_payloads[1] {
+                               *amt_msat = 99_000;
+                       } else { panic!() }
                        let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap();
                        payment_event.msgs[0].onion_routing_packet = new_onion_packet;
                }
index 590b26632fbe9216b632d33844a1e5121b5cef64..0635dafd7dbc8987d222c1be59268629fcb8cca8 100644 (file)
@@ -1442,24 +1442,22 @@ mod fuzzy_internal_msgs {
                },
        }
 
-       pub(crate) enum OnionHopDataFormat {
-               NonFinalNode {
+       pub(crate) enum OutboundOnionPayload {
+               Forward {
                        short_channel_id: u64,
+                       /// The value, in msat, of the payment after this hop's fee is deducted.
+                       amt_to_forward: u64,
+                       outgoing_cltv_value: u32,
                },
-               FinalNode {
+               Receive {
                        payment_data: Option<FinalOnionHopData>,
                        payment_metadata: Option<Vec<u8>>,
                        keysend_preimage: Option<PaymentPreimage>,
+                       amt_msat: u64,
+                       outgoing_cltv_value: u32,
                },
        }
 
-       pub struct OnionHopData {
-               pub(crate) format: OnionHopDataFormat,
-               /// The value, in msat, of the payment after this hop's fee is deducted.
-               pub(crate) amt_to_forward: u64,
-               pub(crate) outgoing_cltv_value: u32,
-       }
-
        pub struct DecodedOnionErrorPacket {
                pub(crate) hmac: [u8; 32],
                pub(crate) failuremsg: Vec<u8>,
@@ -1966,20 +1964,22 @@ impl Readable for FinalOnionHopData {
        }
 }
 
-impl Writeable for OnionHopData {
+impl Writeable for OutboundOnionPayload {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
-               match self.format {
-                       OnionHopDataFormat::NonFinalNode { short_channel_id } => {
+               match self {
+                       Self::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } => {
                                _encode_varint_length_prefixed_tlv!(w, {
-                                       (2, HighZeroBytesDroppedBigSize(self.amt_to_forward), required),
-                                       (4, HighZeroBytesDroppedBigSize(self.outgoing_cltv_value), required),
+                                       (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required),
+                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
                                        (6, short_channel_id, required)
                                });
                        },
-                       OnionHopDataFormat::FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
+                       Self::Receive {
+                               ref payment_data, ref payment_metadata, ref keysend_preimage, amt_msat, outgoing_cltv_value
+                       } => {
                                _encode_varint_length_prefixed_tlv!(w, {
-                                       (2, HighZeroBytesDroppedBigSize(self.amt_to_forward), required),
-                                       (4, HighZeroBytesDroppedBigSize(self.outgoing_cltv_value), required),
+                                       (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
+                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
                                        (8, payment_data, option),
                                        (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option),
                                        (5482373484, keysend_preimage, option)
@@ -2454,7 +2454,7 @@ mod tests {
        use hex;
        use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
-       use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, OnionHopDataFormat};
+       use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket};
        use crate::routing::gossip::{NodeAlias, NodeId};
        use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited};
 
@@ -3537,14 +3537,12 @@ mod tests {
 
        #[test]
        fn encoding_nonfinal_onion_hop_data() {
-               let msg = msgs::OnionHopData {
-                       format: OnionHopDataFormat::NonFinalNode {
-                               short_channel_id: 0xdeadbeef1bad1dea,
-                       },
+               let outbound_msg = msgs::OutboundOnionPayload::Forward {
+                       short_channel_id: 0xdeadbeef1bad1dea,
                        amt_to_forward: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
                };
-               let encoded_value = msg.encode();
+               let encoded_value = outbound_msg.encode();
                let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
                assert_eq!(encoded_value, target_value);
 
@@ -3558,16 +3556,14 @@ mod tests {
 
        #[test]
        fn encoding_final_onion_hop_data() {
-               let msg = msgs::OnionHopData {
-                       format: OnionHopDataFormat::FinalNode {
-                               payment_data: None,
-                               payment_metadata: None,
-                               keysend_preimage: None,
-                       },
-                       amt_to_forward: 0x0badf00d01020304,
+               let outbound_msg = msgs::OutboundOnionPayload::Receive {
+                       payment_data: None,
+                       payment_metadata: None,
+                       keysend_preimage: None,
+                       amt_msat: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
                };
-               let encoded_value = msg.encode();
+               let encoded_value = outbound_msg.encode();
                let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
 
@@ -3581,19 +3577,17 @@ mod tests {
        #[test]
        fn encoding_final_onion_hop_data_with_secret() {
                let expected_payment_secret = PaymentSecret([0x42u8; 32]);
-               let msg = msgs::OnionHopData {
-                       format: OnionHopDataFormat::FinalNode {
-                               payment_data: Some(FinalOnionHopData {
-                                       payment_secret: expected_payment_secret,
-                                       total_msat: 0x1badca1f
-                               }),
-                               payment_metadata: None,
-                               keysend_preimage: None,
-                       },
-                       amt_to_forward: 0x0badf00d01020304,
+               let outbound_msg = msgs::OutboundOnionPayload::Receive {
+                       payment_data: Some(FinalOnionHopData {
+                               payment_secret: expected_payment_secret,
+                               total_msat: 0x1badca1f
+                       }),
+                       payment_metadata: None,
+                       keysend_preimage: None,
+                       amt_msat: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
                };
-               let encoded_value = msg.encode();
+               let encoded_value = outbound_msg.encode();
                let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
                assert_eq!(encoded_value, target_value);
 
@@ -3765,20 +3759,18 @@ mod tests {
        // see above test, needs to be a separate method for use of the serialization macros.
        fn encode_big_payload() -> Result<Vec<u8>, io::Error> {
                use crate::util::ser::HighZeroBytesDroppedBigSize;
-               let payload = msgs::OnionHopData {
-                       format: OnionHopDataFormat::NonFinalNode {
-                               short_channel_id: 0xdeadbeef1bad1dea,
-                       },
+               let payload = msgs::OutboundOnionPayload::Forward {
+                       short_channel_id: 0xdeadbeef1bad1dea,
                        amt_to_forward: 1000,
                        outgoing_cltv_value: 0xffffffff,
                };
                let mut encoded_payload = Vec::new();
                let test_bytes = vec![42u8; 1000];
-               if let OnionHopDataFormat::NonFinalNode { short_channel_id } = payload.format {
+               if let msgs::OutboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = payload {
                        _encode_varint_length_prefixed_tlv!(&mut encoded_payload, {
                                (1, test_bytes, required_vec),
-                               (2, HighZeroBytesDroppedBigSize(payload.amt_to_forward), required),
-                               (4, HighZeroBytesDroppedBigSize(payload.outgoing_cltv_value), required),
+                               (2, HighZeroBytesDroppedBigSize(amt_to_forward), required),
+                               (4, HighZeroBytesDroppedBigSize(outgoing_cltv_value), required),
                                (6, short_channel_id, required)
                        });
                }
index e5faedfe7fc39c958cc52f1c40fbcbc09bcebf27..9945b8c490f0d831e64948967ac024c4c2b53518 100644 (file)
@@ -252,7 +252,7 @@ struct BogusOnionHopData {
        data: Vec<u8>
 }
 impl BogusOnionHopData {
-       fn new(orig: msgs::OnionHopData) -> Self {
+       fn new(orig: msgs::OutboundOnionPayload) -> Self {
                Self { data: orig.encode() }
        }
 }
@@ -875,15 +875,15 @@ fn test_always_create_tlv_format_onion_payloads() {
        let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(
                &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap();
 
-       match onion_payloads[0].format {
-               msgs::OnionHopDataFormat::NonFinalNode {..} => {},
+       match onion_payloads[0] {
+               msgs::OutboundOnionPayload::Forward {..} => {},
                _ => { panic!(
                        "Should have generated a `msgs::OnionHopDataFormat::NonFinalNode` payload for `hops[0]`,
                        despite that the features signals no support for variable length onions"
                )}
        }
-       match onion_payloads[1].format {
-               msgs::OnionHopDataFormat::FinalNode {..} => {},
+       match onion_payloads[1] {
+               msgs::OutboundOnionPayload::Receive {..} => {},
                _ => {panic!(
                        "Should have generated a `msgs::OnionHopDataFormat::FinalNode` payload for `hops[1]`,
                        despite that the features signals no support for variable length onions"
index a915cf29d51b385246690a40038b3ba49929909a..f3579a56b8d80330cb540bc5acfb643f41555262 100644 (file)
@@ -149,11 +149,11 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T
 }
 
 /// 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, starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(Vec<msgs::OnionHopData>, u64, u32), APIError> {
+pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(Vec<msgs::OutboundOnionPayload>, u64, u32), APIError> {
        let mut cur_value_msat = 0u64;
        let mut cur_cltv = starting_htlc_offset;
        let mut last_short_channel_id = 0;
-       let mut res: Vec<msgs::OnionHopData> = Vec::with_capacity(path.hops.len());
+       let mut res: Vec<msgs::OutboundOnionPayload> = Vec::with_capacity(path.hops.len());
 
        for (idx, hop) in path.hops.iter().rev().enumerate() {
                // First hop gets special values so that it can check, on receipt, that everything is
@@ -161,25 +161,25 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
                // the intended recipient).
                let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
                let cltv = if cur_cltv == starting_htlc_offset { hop.cltv_expiry_delta + starting_htlc_offset } else { cur_cltv };
-               res.insert(0, msgs::OnionHopData {
-                       format: if idx == 0 {
-                               msgs::OnionHopDataFormat::FinalNode {
-                                       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(),
-                                       keysend_preimage: *keysend_preimage,
-                               }
-                       } else {
-                               msgs::OnionHopDataFormat::NonFinalNode {
-                                       short_channel_id: last_short_channel_id,
-                               }
-                       },
-                       amt_to_forward: value_msat,
-                       outgoing_cltv_value: cltv,
+               res.insert(0, if idx == 0 {
+                       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(),
+                               keysend_preimage: *keysend_preimage,
+                               amt_msat: value_msat,
+                               outgoing_cltv_value: cltv,
+                       }
+               } else {
+                       msgs::OutboundOnionPayload::Forward {
+                               short_channel_id: last_short_channel_id,
+                               amt_to_forward: value_msat,
+                               outgoing_cltv_value: cltv,
+                       }
                });
                cur_value_msat += hop.fee_msat;
                if cur_value_msat >= 21000000 * 100000000 * 1000 {
@@ -208,7 +208,10 @@ fn shift_slice_right(arr: &mut [u8], amt: usize) {
        }
 }
 
-pub(super) fn construct_onion_packet(payloads: Vec<msgs::OnionHopData>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32], associated_data: &PaymentHash) -> Result<msgs::OnionPacket, ()> {
+pub(super) fn construct_onion_packet(
+       payloads: Vec<msgs::OutboundOnionPayload>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32],
+       associated_data: &PaymentHash
+) -> Result<msgs::OnionPacket, ()> {
        let mut packet_data = [0; ONION_DATA_LEN];
 
        let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
@@ -988,10 +991,8 @@ mod tests {
                // with raw hex instead of our in-memory enums, as the payloads contains custom types, and
                // we have no way of representing that with our enums.
                let payloads = vec!(
-                       RawOnionHopData::new(msgs::OnionHopData {
-                               format: msgs::OnionHopDataFormat::NonFinalNode {
-                                       short_channel_id: 1,
-                               },
+                       RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
+                               short_channel_id: 1,
                                amt_to_forward: 15000,
                                outgoing_cltv_value: 1500,
                        }),
@@ -1013,17 +1014,13 @@ mod tests {
                        RawOnionHopData {
                                data: hex::decode("52020236b00402057806080000000000000002fd02013c0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f").unwrap(),
                        },
-                       RawOnionHopData::new(msgs::OnionHopData {
-                               format: msgs::OnionHopDataFormat::NonFinalNode {
-                                       short_channel_id: 3,
-                               },
+                       RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
+                               short_channel_id: 3,
                                amt_to_forward: 12500,
                                outgoing_cltv_value: 1250,
                        }),
-                       RawOnionHopData::new(msgs::OnionHopData {
-                               format: msgs::OnionHopDataFormat::NonFinalNode {
-                                       short_channel_id: 4,
-                               },
+                       RawOnionHopData::new(msgs::OutboundOnionPayload::Forward {
+                               short_channel_id: 4,
                                amt_to_forward: 10000,
                                outgoing_cltv_value: 1000,
                        }),
@@ -1101,7 +1098,7 @@ mod tests {
                data: Vec<u8>
        }
        impl RawOnionHopData {
-               fn new(orig: msgs::OnionHopData) -> Self {
+               fn new(orig: msgs::OutboundOnionPayload) -> Self {
                        Self { data: orig.encode() }
                }
        }