X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=fuzz%2Fsrc%2Frouter.rs;h=ef7669f1eafd7f477182452fb9006610bd95f2e0;hb=fc7df54f8dc3baf710371e2ad2beb862946d5b1c;hp=fbb629220112a63f543135c1be2537908c6ad017;hpb=c9916437468a130718ab83baa2f346b301b674ba;p=rust-lightning diff --git a/fuzz/src/router.rs b/fuzz/src/router.rs index fbb62922..ef7669f1 100644 --- a/fuzz/src/router.rs +++ b/fuzz/src/router.rs @@ -1,21 +1,32 @@ -use bitcoin_hashes::sha256d::Hash as Sha256dHash; -use bitcoin::blockdata::script::{Script, Builder}; -use bitcoin::blockdata::block::Block; -use bitcoin::blockdata::transaction::Transaction; - -use lightning::chain::chaininterface::{ChainError,ChainWatchInterface}; +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +use bitcoin::blockdata::script::Builder; +use bitcoin::blockdata::transaction::TxOut; +use bitcoin::hash_types::BlockHash; + +use bitcoin::secp256k1; + +use lightning::chain; use lightning::ln::channelmanager::ChannelDetails; use lightning::ln::features::InitFeatures; use lightning::ln::msgs; -use lightning::ln::msgs::RoutingMessageHandler; -use lightning::ln::router::{Router, RouteHint}; +use lightning::routing::router::{get_route, RouteHint}; use lightning::util::logger::Logger; use lightning::util::ser::Readable; +use lightning::routing::network_graph::{NetworkGraph, RoutingFees}; -use secp256k1::key::PublicKey; +use bitcoin::secp256k1::key::PublicKey; use utils::test_logger; +use std::collections::HashSet; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -67,33 +78,23 @@ impl InputData { } } -struct DummyChainWatcher { +struct FuzzChainSource { input: Arc, } - -impl ChainWatchInterface for DummyChainWatcher { - fn install_watch_tx(&self, _txid: &Sha256dHash, _script_pub_key: &Script) { } - fn install_watch_outpoint(&self, _outpoint: (Sha256dHash, u32), _out_script: &Script) { } - fn watch_all_txn(&self) { } - fn filter_block<'a>(&self, _block: &'a Block) -> (Vec<&'a Transaction>, Vec) { - (Vec::new(), Vec::new()) - } - fn reentered(&self) -> usize { 0 } - - fn get_chain_utxo(&self, _genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> { +impl chain::Access for FuzzChainSource { + fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> Result { match self.input.get_slice(2) { - Some(&[0, _]) => Err(ChainError::NotSupported), - Some(&[1, _]) => Err(ChainError::NotWatched), - Some(&[2, _]) => Err(ChainError::UnknownTx), - Some(&[_, x]) => Ok((Builder::new().push_int(x as i64).into_script().to_v0_p2wsh(), 0)), - None => Err(ChainError::UnknownTx), + Some(&[0, _]) => Err(chain::AccessError::UnknownChain), + Some(&[1, _]) => Err(chain::AccessError::UnknownTx), + Some(&[_, x]) => Ok(TxOut { value: 0, script_pubkey: Builder::new().push_int(x as i64).into_script().to_v0_p2wsh() }), + None => Err(chain::AccessError::UnknownTx), _ => unreachable!(), } } } #[inline] -pub fn do_test(data: &[u8]) { +pub fn do_test(data: &[u8], out: Out) { let input = Arc::new(InputData { data: data.to_vec(), read_pos: AtomicUsize::new(0), @@ -118,13 +119,12 @@ pub fn do_test(data: &[u8]) { macro_rules! decode_msg { ($MsgType: path, $len: expr) => {{ let mut reader = ::std::io::Cursor::new(get_slice!($len)); - match <($MsgType)>::read(&mut reader) { + match <$MsgType>::read(&mut reader) { Ok(msg) => msg, Err(e) => match e { msgs::DecodeError::UnknownVersion => return, msgs::DecodeError::UnknownRequiredFeature => return, msgs::DecodeError::InvalidValue => return, - msgs::DecodeError::ExtraAddressesPerType => return, msgs::DecodeError::BadLengthDescriptor => return, msgs::DecodeError::ShortRead => panic!("We picked the length..."), msgs::DecodeError::Io(e) => panic!(format!("{}", e)), @@ -151,13 +151,13 @@ pub fn do_test(data: &[u8]) { } } - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - let chain_monitor = Arc::new(DummyChainWatcher { - input: Arc::clone(&input), - }); + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned(), out)); let our_pubkey = get_pubkey!(); - let router = Router::new(our_pubkey.clone(), chain_monitor, Arc::clone(&logger)); + let mut net_graph = NetworkGraph::new(); + + let mut node_pks = HashSet::new(); + let mut scid = 42; loop { match get_slice!(1)[0] { @@ -167,39 +167,44 @@ pub fn do_test(data: &[u8]) { if addr_len > (37+1)*4 { return; } - let _ = router.handle_node_announcement(&decode_msg_with_len16!(msgs::NodeAnnouncement, 64, 288)); + let msg = decode_msg_with_len16!(msgs::NodeAnnouncement, 64, 288); + node_pks.insert(msg.contents.node_id); + let _ = net_graph.update_node_from_announcement::(&msg, None); }, 1 => { - let _ = router.handle_channel_announcement(&decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4)); + let msg = decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4); + node_pks.insert(msg.contents.node_id_1); + node_pks.insert(msg.contents.node_id_2); + let _ = net_graph.update_channel_from_announcement::(&msg, None, None); }, 2 => { - let _ = router.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 128)); + let msg = decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4); + node_pks.insert(msg.contents.node_id_1); + node_pks.insert(msg.contents.node_id_2); + let val = slice_to_be64(get_slice!(8)); + let _ = net_graph.update_channel_from_announcement::(&msg, Some(val), None); }, 3 => { - match get_slice!(1)[0] { - 0 => { - router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {msg: decode_msg!(msgs::ChannelUpdate, 128)}); - }, - 1 => { - let short_channel_id = slice_to_be64(get_slice!(8)); - router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed {short_channel_id, is_permanent: false}); - }, - _ => return, - } + let _ = net_graph.update_channel(&decode_msg!(msgs::ChannelUpdate, 136), None); }, 4 => { - let target = get_pubkey!(); + let short_channel_id = slice_to_be64(get_slice!(8)); + net_graph.close_channel_from_update(short_channel_id, false); + }, + _ if node_pks.is_empty() => {}, + _ => { let mut first_hops_vec = Vec::new(); let first_hops = match get_slice!(1)[0] { 0 => None, - 1 => { - let count = slice_to_be16(get_slice!(2)); + count => { for _ in 0..count { + scid += 1; + let rnid = node_pks.iter().skip(slice_to_be16(get_slice!(2))as usize % node_pks.len()).next().unwrap(); first_hops_vec.push(ChannelDetails { channel_id: [0; 32], - short_channel_id: Some(slice_to_be64(get_slice!(8))), - remote_network_id: get_pubkey!(), - counterparty_features: InitFeatures::empty(), + short_channel_id: Some(scid), + remote_network_id: *rnid, + counterparty_features: InitFeatures::known(), channel_value_satoshis: slice_to_be64(get_slice!(8)), user_id: 0, inbound_capacity_msat: 0, @@ -209,39 +214,42 @@ pub fn do_test(data: &[u8]) { } Some(&first_hops_vec[..]) }, - _ => return, }; let mut last_hops_vec = Vec::new(); - let last_hops = { - let count = slice_to_be16(get_slice!(2)); + { + let count = get_slice!(1)[0]; for _ in 0..count { + scid += 1; + let rnid = node_pks.iter().skip(slice_to_be16(get_slice!(2))as usize % node_pks.len()).next().unwrap(); last_hops_vec.push(RouteHint { - src_node_id: get_pubkey!(), - short_channel_id: slice_to_be64(get_slice!(8)), - fee_base_msat: slice_to_be32(get_slice!(4)), - fee_proportional_millionths: slice_to_be32(get_slice!(4)), + src_node_id: *rnid, + short_channel_id: scid, + fees: RoutingFees { + base_msat: slice_to_be32(get_slice!(4)), + proportional_millionths: slice_to_be32(get_slice!(4)), + }, cltv_expiry_delta: slice_to_be16(get_slice!(2)), htlc_minimum_msat: slice_to_be64(get_slice!(8)), }); } - &last_hops_vec[..] - }; - let _ = router.get_route(&target, first_hops, last_hops, slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4))); + } + let last_hops = &last_hops_vec[..]; + for target in node_pks.iter() { + let _ = get_route(&our_pubkey, &net_graph, target, + first_hops.map(|c| c.iter().collect::>()).as_ref().map(|a| a.as_slice()), + &last_hops.iter().collect::>(), + slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4)), Arc::clone(&logger)); + } }, - _ => return, } } } -#[no_mangle] -pub extern "C" fn router_run(data: *const u8, datalen: usize) { - do_test(unsafe { std::slice::from_raw_parts(data, datalen) }); +pub fn router_test(data: &[u8], out: Out) { + do_test(data, out); } -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } +#[no_mangle] +pub extern "C" fn router_run(data: *const u8, datalen: usize) { + do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, test_logger::DevNull {}); }