Move BogusHopData generation into test instead of OnionHopData.
authorMatt Corallo <git@bluematt.me>
Thu, 26 Dec 2019 18:45:44 +0000 (13:45 -0500)
committerMatt Corallo <git@bluematt.me>
Tue, 11 Feb 2020 18:48:56 +0000 (13:48 -0500)
This, as it should be, restricts OnionHopData to only being able to
represent valid states, while still allowing for tests to generate
bogus hop data fields to test deserialization.

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

index b9a2dde8732d20a2e0dede06304d657fdb4ec29d..936e785f562f9c77815fa57aa4b54b231da3d7fb 100644 (file)
@@ -18,7 +18,7 @@ use util::enforcing_trait_impls::EnforcingChannelKeys;
 use util::test_utils;
 use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
 use util::errors::APIError;
-use util::ser::{Writeable, ReadableArgs};
+use util::ser::{Writeable, Writer, ReadableArgs};
 use util::config::UserConfig;
 use util::logger::Logger;
 
@@ -44,7 +44,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
 use std::default::Default;
 use std::sync::{Arc, Mutex};
 use std::sync::atomic::Ordering;
-use std::mem;
+use std::{mem, io};
 
 use rand::{thread_rng, Rng};
 
@@ -5007,6 +5007,20 @@ impl msgs::ChannelUpdate {
        }
 }
 
+struct BogusOnionHopData {
+       data: Vec<u8>
+}
+impl BogusOnionHopData {
+       fn new(orig: msgs::OnionHopData) -> Self {
+               Self { data: orig.encode() }
+       }
+}
+impl Writeable for BogusOnionHopData {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               writer.write_all(&self.data[..])
+       }
+}
+
 #[test]
 fn test_onion_failure() {
        use ln::msgs::ChannelUpdate;
@@ -5036,8 +5050,14 @@ fn test_onion_failure() {
                let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
                let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
                let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
-               onion_payloads[0].format = msgs::OnionHopDataFormat::BogusRealm(3);
-               msg.onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
+               let mut new_payloads = Vec::new();
+               for payload in onion_payloads.drain(..) {
+                       new_payloads.push(BogusOnionHopData::new(payload));
+               }
+               // break the first (non-final) hop payload by swapping the realm (0) byte for a byte
+               // describing a length-1 TLV payload, which is obviously bogus.
+               new_payloads[0].data[0] = 1;
+               msg.onion_routing_packet = onion_utils::construct_onion_packet_bogus_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash);
        }, ||{}, true, Some(PERM|1), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));//XXX incremented channels idx here
 
        // final node failure
@@ -5046,8 +5066,14 @@ fn test_onion_failure() {
                let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
                let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
                let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
-               onion_payloads[1].format = msgs::OnionHopDataFormat::BogusRealm(3);
-               msg.onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
+               let mut new_payloads = Vec::new();
+               for payload in onion_payloads.drain(..) {
+                       new_payloads.push(BogusOnionHopData::new(payload));
+               }
+               // break the last-hop payload by swapping the realm (0) byte for a byte describing a
+               // length-1 TLV payload, which is obviously bogus.
+               new_payloads[1].data[0] = 1;
+               msg.onion_routing_packet = onion_utils::construct_onion_packet_bogus_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash);
        }, ||{}, false, Some(PERM|1), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
 
        // the following three with run_onion_failure_test_with_fail_intercept() test only the origin node
index 4518dd72203825b0addd36f9daee2d2d18e5729e..09636cef16019239c83061796fe6686abbed9b2b 100644 (file)
@@ -614,11 +614,6 @@ mod fuzzy_internal_msgs {
 
        pub(crate) enum OnionHopDataFormat {
                Legacy, // aka Realm-0
-               // Some tests expect to be able to generate bogus non-deserializable OnionHopDatas. In the
-               // future we can use bogus TLV attributes, but for now we have to expose a "bogus realm"
-               // option.
-               #[cfg(test)]
-               BogusRealm(u8),
        }
 
        pub struct OnionHopData {
@@ -968,8 +963,6 @@ impl Writeable for OnionHopData {
                w.size_hint(33);
                match self.format {
                        OnionHopDataFormat::Legacy => 0u8.write(w)?,
-                       #[cfg(test)]
-                       OnionHopDataFormat::BogusRealm(v) => v.write(w)?,
                }
                self.short_channel_id.write(w)?;
                self.amt_to_forward.write(w)?;
index fb9684886e6d5e92b36e62b5154fba61baab6802..84e8d9794e0097eadc4d08c1bf292354a9867390 100644 (file)
@@ -169,7 +169,19 @@ pub(super) fn construct_onion_packet(payloads: Vec<msgs::OnionHopData>, onion_ke
        construct_onion_packet_with_init_noise(payloads, onion_keys, packet_data, associated_data)
 }
 
-fn construct_onion_packet_with_init_noise(mut payloads: Vec<msgs::OnionHopData>, onion_keys: Vec<OnionKeys>, mut packet_data: [u8; 20*65], associated_data: &PaymentHash) -> msgs::OnionPacket {
+#[cfg(test)]
+// Used in testing to write bogus OnionHopDatas, which is otherwise not representable in
+// msgs::OnionHopData.
+pub(super) fn construct_onion_packet_bogus_hopdata<HD: Writeable>(payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32], associated_data: &PaymentHash) -> msgs::OnionPacket {
+       let mut packet_data = [0; 20*65];
+
+       let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
+       chacha.process(&[0; 20*65], &mut packet_data);
+
+       construct_onion_packet_with_init_noise(payloads, onion_keys, packet_data, associated_data)
+}
+
+fn construct_onion_packet_with_init_noise<HD: Writeable>(mut payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, mut packet_data: [u8; 20*65], associated_data: &PaymentHash) -> msgs::OnionPacket {
        let mut buf = Vec::with_capacity(21*65);
        buf.resize(21*65, 0);