Skip to content

Commit a166eca

Browse files
committed
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.
1 parent 0b40b0c commit a166eca

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use util::enforcing_trait_impls::EnforcingChannelKeys;
1818
use util::test_utils;
1919
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
2020
use util::errors::APIError;
21-
use util::ser::{Writeable, ReadableArgs};
21+
use util::ser::{Writeable, Writer, ReadableArgs};
2222
use util::config::UserConfig;
2323
use util::logger::Logger;
2424

@@ -44,7 +44,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
4444
use std::default::Default;
4545
use std::sync::{Arc, Mutex};
4646
use std::sync::atomic::Ordering;
47-
use std::mem;
47+
use std::{mem, io};
4848

4949
use rand::{thread_rng, Rng};
5050

@@ -4972,6 +4972,20 @@ impl msgs::ChannelUpdate {
49724972
}
49734973
}
49744974

4975+
struct BogusOnionHopData {
4976+
data: Vec<u8>
4977+
}
4978+
impl BogusOnionHopData {
4979+
fn new(orig: msgs::OnionHopData) -> Self {
4980+
Self { data: orig.encode() }
4981+
}
4982+
}
4983+
impl Writeable for BogusOnionHopData {
4984+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
4985+
writer.write_all(&self.data[..])
4986+
}
4987+
}
4988+
49754989
#[test]
49764990
fn test_onion_failure() {
49774991
use ln::msgs::ChannelUpdate;
@@ -5001,8 +5015,14 @@ fn test_onion_failure() {
50015015
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
50025016
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
50035017
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
5004-
onion_payloads[0].format = msgs::OnionHopDataFormat::BogusRealm(3);
5005-
msg.onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
5018+
let mut new_payloads = Vec::new();
5019+
for payload in onion_payloads.drain(..) {
5020+
new_payloads.push(BogusOnionHopData::new(payload));
5021+
}
5022+
// break the first (non-final) hop payload by swapping the realm (0) byte for a byte
5023+
// describing a length-1 TLV payload, which is obviously bogus.
5024+
new_payloads[0].data[0] = 1;
5025+
msg.onion_routing_packet = onion_utils::construct_onion_packet_bogus_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash);
50065026
}, ||{}, 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
50075027

50085028
// final node failure
@@ -5011,8 +5031,14 @@ fn test_onion_failure() {
50115031
let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
50125032
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
50135033
let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, cur_height).unwrap();
5014-
onion_payloads[1].format = msgs::OnionHopDataFormat::BogusRealm(3);
5015-
msg.onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
5034+
let mut new_payloads = Vec::new();
5035+
for payload in onion_payloads.drain(..) {
5036+
new_payloads.push(BogusOnionHopData::new(payload));
5037+
}
5038+
// break the last-hop payload by swapping the realm (0) byte for a byte describing a
5039+
// length-1 TLV payload, which is obviously bogus.
5040+
new_payloads[1].data[0] = 1;
5041+
msg.onion_routing_packet = onion_utils::construct_onion_packet_bogus_hopdata(new_payloads, onion_keys, [0; 32], &payment_hash);
50165042
}, ||{}, false, Some(PERM|1), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
50175043

50185044
// the following three with run_onion_failure_test_with_fail_intercept() test only the origin node

lightning/src/ln/msgs.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -612,11 +612,6 @@ mod fuzzy_internal_msgs {
612612

613613
pub(crate) enum OnionHopDataFormat {
614614
Legacy, // aka Realm-0
615-
// Some tests expect to be able to generate bogus non-deserializable OnionHopDatas. In the
616-
// future we can use bogus TLV attributes, but for now we have to expose a "bogus realm"
617-
// option.
618-
#[cfg(test)]
619-
BogusRealm(u8),
620615
}
621616

622617
pub struct OnionHopData {
@@ -966,8 +961,6 @@ impl Writeable for OnionHopData {
966961
w.size_hint(33);
967962
match self.format {
968963
OnionHopDataFormat::Legacy => 0u8.write(w)?,
969-
#[cfg(test)]
970-
OnionHopDataFormat::BogusRealm(v) => v.write(w)?,
971964
}
972965
self.short_channel_id.write(w)?;
973966
self.amt_to_forward.write(w)?;

lightning/src/ln/onion_utils.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,19 @@ pub(super) fn construct_onion_packet(payloads: Vec<msgs::OnionHopData>, onion_ke
169169
construct_onion_packet_with_init_noise(payloads, onion_keys, packet_data, associated_data)
170170
}
171171

172-
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 {
172+
#[cfg(test)]
173+
// Used in testing to write bogus OnionHopDatas, which is otherwise not representable in
174+
// msgs::OnionHopData.
175+
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 {
176+
let mut packet_data = [0; 20*65];
177+
178+
let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
179+
chacha.process(&[0; 20*65], &mut packet_data);
180+
181+
construct_onion_packet_with_init_noise(payloads, onion_keys, packet_data, associated_data)
182+
}
183+
184+
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 {
173185
let mut buf = Vec::with_capacity(21*65);
174186
buf.resize(21*65, 0);
175187

0 commit comments

Comments
 (0)