From 32c245b08fca6330a3a8373184d025332feab157 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 26 Dec 2019 13:45:44 -0500 Subject: [PATCH] Move BogusHopData generation into test instead of OnionHopData. 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 | 34 +++++++++++++++++++++++----- lightning/src/ln/msgs.rs | 7 ------ lightning/src/ln/onion_utils.rs | 14 +++++++++++- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 6d6a13bb5..d1f836063 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -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}; @@ -4972,6 +4972,20 @@ impl msgs::ChannelUpdate { } } +struct BogusOnionHopData { + data: Vec +} +impl BogusOnionHopData { + fn new(orig: msgs::OnionHopData) -> Self { + Self { data: orig.encode() } + } +} +impl Writeable for BogusOnionHopData { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + writer.write_all(&self.data[..]) + } +} + #[test] fn test_onion_failure() { use ln::msgs::ChannelUpdate; @@ -5001,8 +5015,12 @@ 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)); + } + 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 @@ -5011,8 +5029,12 @@ 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)); + } + 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 diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index b42efcd5f..ec2c98cb9 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -612,11 +612,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 { @@ -966,8 +961,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)?; diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index fb9684886..84e8d9794 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -169,7 +169,19 @@ pub(super) fn construct_onion_packet(payloads: Vec, 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, onion_keys: Vec, 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(payloads: Vec, onion_keys: Vec, 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(mut payloads: Vec, onion_keys: Vec, mut packet_data: [u8; 20*65], associated_data: &PaymentHash) -> msgs::OnionPacket { let mut buf = Vec::with_capacity(21*65); buf.resize(21*65, 0); -- 2.39.5