From: RJ Rybarczyk Date: Fri, 15 Nov 2019 02:44:30 +0000 (+0000) Subject: Use workspaces to separate crates X-Git-Tag: v0.0.12~178^2~3 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=88fef649b15fa030cb91de76d58346a0bc408834;p=rust-lightning Use workspaces to separate crates --- diff --git a/.travis.yml b/.travis.yml index ef0aa839c..e4b831db4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ script: - RUSTFLAGS="-C link-dead-code" cargo build --verbose - rm -f target/debug/lightning-* # Make sure we drop old test binaries - RUSTFLAGS="-C link-dead-code" cargo test --verbose - - if [ "$(rustup show | grep default | grep 1.34.2)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi - - if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd net-tokio && cargo build --verbose && cd ..; fi + - if [ "$(rustup show | grep default | grep 1.34.2)" != "" ]; then cd lightning/fuzz && cargo test --verbose && ./travis-fuzz.sh; fi + - if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd lightning-net-tokio && cargo build --verbose && cd ..; fi - if [ "$(rustup show | grep default | grep stable)" != "" ]; then wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && diff --git a/Cargo.toml b/Cargo.toml index 004e6d25b..6ec1776c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,38 +1,6 @@ -[package] -name = "lightning" -version = "0.0.9" -authors = ["Matt Corallo"] -license = "Apache-2.0" -repository = "https://github.com/rust-bitcoin/rust-lightning/" -description = """ -A Bitcoin Lightning library in Rust. -Does most of the hard work, without implying a specific runtime, requiring clients implement basic network logic, chain interactions and disk storage. -Still missing tons of error-handling. See GitHub issues for suggested projects if you want to contribute. Don't have to bother telling you not to use this for anything serious, because you'd have to build a client around it to even try. -""" +[workspace] -[features] -# Supports tracking channels with a non-bitcoin chain hashes. Currently enables all kinds of fun DoS attacks. -non_bitcoin_chain_hash_routing = [] -fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget", "bitcoin_hashes/fuzztarget"] -# Unlog messages superior at targeted level. -max_level_off = [] -max_level_error = [] -max_level_warn = [] -max_level_info = [] -max_level_debug = [] - -[dependencies] -bitcoin = "0.20" -bitcoin_hashes = "0.7" -secp256k1 = "0.15" - -[dev-dependencies.bitcoin] -version = "0.20" -features = ["bitcoinconsensus"] - -[dev-dependencies] -hex = "0.3" -rand = "0.4" - -[profile.dev] -opt-level = 1 +members = [ + "lightning", + "lightning-net-tokio", +] diff --git a/fuzz/.gitignore b/fuzz/.gitignore deleted file mode 100644 index 8bf27ec5d..000000000 --- a/fuzz/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -hfuzz_target -target -hfuzz_workspace diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml deleted file mode 100644 index 19d832e87..000000000 --- a/fuzz/Cargo.toml +++ /dev/null @@ -1,158 +0,0 @@ -[package] -name = "lightning-fuzz" -version = "0.0.1" -authors = ["Automatically generated"] -publish = false -# Because the function is unused it gets dropped before we link lightning, so -# we have to duplicate build.rs here. Note that this is only required for -# fuzztarget mode. - -[package.metadata] -cargo-fuzz = true - -[features] -afl_fuzz = ["afl"] -honggfuzz_fuzz = ["honggfuzz"] -libfuzzer_fuzz = ["libfuzzer-sys"] - -[dependencies] -afl = { version = "0.4", optional = true } -lightning = { path = "..", features = ["fuzztarget"] } -bitcoin = { version = "0.20", features = ["fuzztarget"] } -bitcoin_hashes = { version = "0.7", features = ["fuzztarget"] } -hex = "0.3" -honggfuzz = { version = "0.5", optional = true } -secp256k1 = { version = "0.15", features=["fuzztarget"] } -libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git", optional = true } - -[build-dependencies] -cc = "1.0" - -# Prevent this from interfering with workspaces -[workspace] -members = ["."] - -[profile.release] -lto = true -codegen-units = 1 - -[[bin]] -name = "peer_crypt_target" -path = "fuzz_targets/peer_crypt_target.rs" - -[[bin]] -name = "full_stack_target" -path = "fuzz_targets/full_stack_target.rs" - -[[bin]] -name = "chanmon_fail_consistency" -path = "fuzz_targets/chanmon_fail_consistency.rs" - -[[bin]] -name = "router_target" -path = "fuzz_targets/router_target.rs" - -[[bin]] -name = "chanmon_deser_target" -path = "fuzz_targets/chanmon_deser_target.rs" - -# message fuzz targets -[[bin]] -name = "msg_ping_target" -path = "fuzz_targets/msg_targets/msg_ping_target.rs" - -[[bin]] -name = "msg_pong_target" -path = "fuzz_targets/msg_targets/msg_pong_target.rs" - -[[bin]] -name = "msg_error_message_target" -path = "fuzz_targets/msg_targets/msg_error_message_target.rs" - -[[bin]] -name = "msg_update_add_htlc_target" -path = "fuzz_targets/msg_targets/msg_update_add_htlc_target.rs" - -[[bin]] -name = "msg_accept_channel_target" -path = "fuzz_targets/msg_targets/msg_accept_channel_target.rs" - -[[bin]] -name = "msg_closing_signed_target" -path = "fuzz_targets/msg_targets/msg_closing_signed_target.rs" - -[[bin]] -name = "msg_commitment_signed_target" -path = "fuzz_targets/msg_targets/msg_commitment_signed_target.rs" - -[[bin]] -name = "msg_funding_created_target" -path = "fuzz_targets/msg_targets/msg_funding_created_target.rs" - -[[bin]] -name = "msg_funding_locked_target" -path = "fuzz_targets/msg_targets/msg_funding_locked_target.rs" - -[[bin]] -name = "msg_funding_signed_target" -path = "fuzz_targets/msg_targets/msg_funding_signed_target.rs" - -[[bin]] -name = "msg_open_channel_target" -path = "fuzz_targets/msg_targets/msg_open_channel_target.rs" - -[[bin]] -name = "msg_revoke_and_ack_target" -path = "fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs" - -[[bin]] -name = "msg_shutdown_target" -path = "fuzz_targets/msg_targets/msg_shutdown_target.rs" - -[[bin]] -name = "msg_update_fail_malformed_htlc_target" -path = "fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs" - -[[bin]] -name = "msg_update_fee_target" -path = "fuzz_targets/msg_targets/msg_update_fee_target.rs" - -[[bin]] -name = "msg_update_fulfill_htlc_target" -path = "fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs" - -[[bin]] -name = "msg_update_fail_htlc_target" -path = "fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs" - -[[bin]] -name = "msg_channel_reestablish_target" -path = "fuzz_targets/msg_targets/msg_channel_reestablish_target.rs" - -[[bin]] -name = "msg_announcement_signatures_target" -path = "fuzz_targets/msg_targets/msg_announcement_signatures_target.rs" - -[[bin]] -name = "msg_channel_announcement_target" -path = "fuzz_targets/msg_targets/msg_channel_announcement_target.rs" - -[[bin]] -name = "msg_channel_update_target" -path = "fuzz_targets/msg_targets/msg_channel_update_target.rs" - -[[bin]] -name = "msg_decoded_onion_error_packet_target" -path = "fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs" - -[[bin]] -name = "msg_init_target" -path = "fuzz_targets/msg_targets/msg_init_target.rs" - -[[bin]] -name = "msg_node_announcement_target" -path = "fuzz_targets/msg_targets/msg_node_announcement_target.rs" - -[[bin]] -name = "msg_onion_hop_data_target" -path = "fuzz_targets/msg_targets/msg_onion_hop_data_target.rs" diff --git a/fuzz/fuzz_targets/chanmon_deser_target.rs b/fuzz/fuzz_targets/chanmon_deser_target.rs deleted file mode 100644 index f74183258..000000000 --- a/fuzz/fuzz_targets/chanmon_deser_target.rs +++ /dev/null @@ -1,72 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate bitcoin; -extern crate bitcoin_hashes; -extern crate lightning; - -use bitcoin_hashes::sha256d::Hash as Sha256dHash; - -use lightning::ln::channelmonitor; -use lightning::util::ser::{ReadableArgs, Writer}; - -mod utils; -use utils::test_logger; - -use std::io::Cursor; -use std::sync::Arc; - -struct VecWriter(Vec); -impl Writer for VecWriter { - fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { - self.0.extend_from_slice(buf); - Ok(()) - } - fn size_hint(&mut self, size: usize) { - self.0.reserve_exact(size); - } -} - -#[inline] -pub fn do_test(data: &[u8]) { - let logger = Arc::new(test_logger::TestLogger::new("".to_owned())); - if let Ok((latest_block_hash, monitor)) = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), logger.clone()) { - let mut w = VecWriter(Vec::new()); - monitor.write_for_disk(&mut w).unwrap(); - let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap(); - assert!(latest_block_hash == deserialized_copy.0); - assert!(monitor == deserialized_copy.1); - w.0.clear(); - monitor.write_for_watchtower(&mut w).unwrap(); - } -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/chanmon_fail_consistency.rs b/fuzz/fuzz_targets/chanmon_fail_consistency.rs deleted file mode 100644 index 3610b1ca6..000000000 --- a/fuzz/fuzz_targets/chanmon_fail_consistency.rs +++ /dev/null @@ -1,783 +0,0 @@ -//! Test that monitor update failures don't get our channel state out of sync. -//! One of the biggest concern with the monitor update failure handling code is that messages -//! resent after monitor updating is restored are delivered out-of-order, resulting in -//! commitment_signed messages having "invalid signatures". -//! To test this we stand up a network of three nodes and read bytes from the fuzz input to denote -//! actions such as sending payments, handling events, or changing monitor update return values on -//! a per-node basis. This should allow it to find any cases where the ordering of actions results -//! in us getting out of sync with ourselves, and, assuming at least one of our recieve- or -//! send-side handling is correct, other peers. We consider it a failure if any action results in a -//! channel being force-closed. - -//Uncomment this for libfuzzer builds: -//#![no_main] - -extern crate bitcoin; -extern crate bitcoin_hashes; -extern crate lightning; -extern crate secp256k1; - -use bitcoin::BitcoinHash; -use bitcoin::blockdata::block::BlockHeader; -use bitcoin::blockdata::transaction::{Transaction, TxOut}; -use bitcoin::blockdata::script::{Builder, Script}; -use bitcoin::blockdata::opcodes; -use bitcoin::network::constants::Network; - -use bitcoin_hashes::Hash as TraitImport; -use bitcoin_hashes::hash160::Hash as Hash160; -use bitcoin_hashes::sha256::Hash as Sha256; -use bitcoin_hashes::sha256d::Hash as Sha256d; - -use lightning::chain::chaininterface; -use lightning::chain::transaction::OutPoint; -use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; -use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; -use lightning::ln::channelmonitor; -use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate}; -use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs}; -use lightning::ln::router::{Route, RouteHop}; -use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, HandleError, UpdateAddHTLC, LocalFeatures}; -use lightning::util::events; -use lightning::util::logger::Logger; -use lightning::util::config::UserConfig; -use lightning::util::events::{EventsProvider, MessageSendEventsProvider}; -use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer}; - -mod utils; -use utils::test_logger; - -use secp256k1::key::{PublicKey,SecretKey}; -use secp256k1::Secp256k1; - -use std::mem; -use std::cmp::Ordering; -use std::collections::{HashSet, hash_map, HashMap}; -use std::sync::{Arc,Mutex}; -use std::sync::atomic; -use std::io::Cursor; - -struct FuzzEstimator {} -impl FeeEstimator for FuzzEstimator { - fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u64 { - 253 - } -} - -pub struct TestBroadcaster {} -impl BroadcasterInterface for TestBroadcaster { - fn broadcast_transaction(&self, _tx: &Transaction) { } -} - -pub struct VecWriter(pub Vec); -impl Writer for VecWriter { - fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { - self.0.extend_from_slice(buf); - Ok(()) - } - fn size_hint(&mut self, size: usize) { - self.0.reserve_exact(size); - } -} - -static mut IN_RESTORE: bool = false; -pub struct TestChannelMonitor { - pub simple_monitor: Arc>, - pub update_ret: Mutex>, - pub latest_good_update: Mutex>>, - pub latest_update_good: Mutex>, - pub latest_updates_good_at_last_ser: Mutex>, - pub should_update_manager: atomic::AtomicBool, -} -impl TestChannelMonitor { - pub fn new(chain_monitor: Arc, broadcaster: Arc, logger: Arc, feeest: Arc) -> Self { - Self { - simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest), - update_ret: Mutex::new(Ok(())), - latest_good_update: Mutex::new(HashMap::new()), - latest_update_good: Mutex::new(HashMap::new()), - latest_updates_good_at_last_ser: Mutex::new(HashMap::new()), - should_update_manager: atomic::AtomicBool::new(false), - } - } -} -impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { - fn add_update_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { - let ret = self.update_ret.lock().unwrap().clone(); - if let Ok(()) = ret { - let mut ser = VecWriter(Vec::new()); - monitor.write_for_disk(&mut ser).unwrap(); - self.latest_good_update.lock().unwrap().insert(funding_txo, ser.0); - match self.latest_update_good.lock().unwrap().entry(funding_txo) { - hash_map::Entry::Vacant(mut e) => { e.insert(true); }, - hash_map::Entry::Occupied(mut e) => { - if !e.get() && unsafe { IN_RESTORE } { - // Technically we can't consider an update to be "good" unless we're doing - // it in response to a test_restore_channel_monitor as the channel may - // still be waiting on such a call, so only set us to good if we're in the - // middle of a restore call. - e.insert(true); - } - }, - } - self.should_update_manager.store(true, atomic::Ordering::Relaxed); - } else { - self.latest_update_good.lock().unwrap().insert(funding_txo, false); - } - assert!(self.simple_monitor.add_update_monitor(funding_txo, monitor).is_ok()); - ret - } - - fn fetch_pending_htlc_updated(&self) -> Vec { - return self.simple_monitor.fetch_pending_htlc_updated(); - } -} - -struct KeyProvider { - node_id: u8, - session_id: atomic::AtomicU8, - channel_id: atomic::AtomicU8, -} -impl KeysInterface for KeyProvider { - fn get_node_secret(&self) -> SecretKey { - SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id]).unwrap() - } - - fn get_destination_script(&self) -> Script { - let secp_ctx = Secp256k1::signing_only(); - let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_id]).unwrap(); - let our_channel_monitor_claim_key_hash = Hash160::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() - } - - fn get_shutdown_pubkey(&self) -> PublicKey { - let secp_ctx = Secp256k1::signing_only(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap()) - } - - fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { - ChannelKeys { - funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, self.node_id]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, self.node_id]).unwrap(), - payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, self.node_id]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(), - commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id], - } - } - - fn get_session_key(&self) -> SecretKey { - let id = self.session_id.fetch_add(1, atomic::Ordering::Relaxed); - SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 10, self.node_id]).unwrap() - } - - fn get_channel_id(&self) -> [u8; 32] { - let id = self.channel_id.fetch_add(1, atomic::Ordering::Relaxed); - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 11, self.node_id] - } -} - -#[inline] -pub fn do_test(data: &[u8]) { - let fee_est = Arc::new(FuzzEstimator{}); - let broadcast = Arc::new(TestBroadcaster{}); - - macro_rules! make_node { - ($node_id: expr) => { { - let logger: Arc = Arc::new(test_logger::TestLogger::new($node_id.to_string())); - let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); - let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone())); - - let keys_manager = Arc::new(KeyProvider { node_id: $node_id, session_id: atomic::AtomicU8::new(0), channel_id: atomic::AtomicU8::new(0) }); - let mut config = UserConfig::new(); - config.channel_options.fee_proportional_millionths = 0; - config.channel_options.announced_channel = true; - config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - (ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap(), - monitor) - } } - } - - macro_rules! reload_node { - ($ser: expr, $node_id: expr, $old_monitors: expr) => { { - let logger: Arc = Arc::new(test_logger::TestLogger::new($node_id.to_string())); - let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); - let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone())); - - let keys_manager = Arc::new(KeyProvider { node_id: $node_id, session_id: atomic::AtomicU8::new(0), channel_id: atomic::AtomicU8::new(0) }); - let mut config = UserConfig::new(); - config.channel_options.fee_proportional_millionths = 0; - config.channel_options.announced_channel = true; - config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - - let mut monitors = HashMap::new(); - let mut old_monitors = $old_monitors.latest_good_update.lock().unwrap(); - for (outpoint, monitor_ser) in old_monitors.drain() { - monitors.insert(outpoint, <(Sha256d, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), Arc::clone(&logger)).expect("Failed to read monitor").1); - monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser); - } - let mut monitor_refs = HashMap::new(); - for (outpoint, monitor) in monitors.iter() { - monitor_refs.insert(*outpoint, monitor); - } - - let read_args = ChannelManagerReadArgs { - keys_manager, - fee_estimator: fee_est.clone(), - monitor: monitor.clone(), - chain_monitor: watch, - tx_broadcaster: broadcast.clone(), - logger, - default_config: config, - channel_monitors: &monitor_refs, - }; - - let res = (<(Sha256d, ChannelManager)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor); - for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() { - if !was_good { - // If the last time we updated a monitor we didn't successfully update (and we - // have sense updated our serialized copy of the ChannelManager) we may - // force-close the channel on our counterparty cause we know we're missing - // something. Thus, we just return here since we can't continue to test. - return; - } - } - res - } } - } - - - let mut channel_txn = Vec::new(); - macro_rules! make_channel { - ($source: expr, $dest: expr, $chan_id: expr) => { { - $source.create_channel($dest.get_our_node_id(), 10000000, 42, 0).unwrap(); - let open_channel = { - let events = $source.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - if let events::MessageSendEvent::SendOpenChannel { ref msg, .. } = events[0] { - msg.clone() - } else { panic!("Wrong event type"); } - }; - - $dest.handle_open_channel(&$source.get_our_node_id(), LocalFeatures::new(), &open_channel).unwrap(); - let accept_channel = { - let events = $dest.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - if let events::MessageSendEvent::SendAcceptChannel { ref msg, .. } = events[0] { - msg.clone() - } else { panic!("Wrong event type"); } - }; - - $source.handle_accept_channel(&$dest.get_our_node_id(), LocalFeatures::new(), &accept_channel).unwrap(); - { - let events = $source.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - if let events::Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, .. } = events[0] { - let tx = Transaction { version: $chan_id, lock_time: 0, input: Vec::new(), output: vec![TxOut { - value: *channel_value_satoshis, script_pubkey: output_script.clone(), - }]}; - let funding_output = OutPoint::new(tx.txid(), 0); - $source.funding_transaction_generated(&temporary_channel_id, funding_output); - channel_txn.push(tx); - } else { panic!("Wrong event type"); } - } - - let funding_created = { - let events = $source.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - if let events::MessageSendEvent::SendFundingCreated { ref msg, .. } = events[0] { - msg.clone() - } else { panic!("Wrong event type"); } - }; - $dest.handle_funding_created(&$source.get_our_node_id(), &funding_created).unwrap(); - - let funding_signed = { - let events = $dest.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - if let events::MessageSendEvent::SendFundingSigned { ref msg, .. } = events[0] { - msg.clone() - } else { panic!("Wrong event type"); } - }; - $source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed).unwrap(); - - { - let events = $source.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - if let events::Event::FundingBroadcastSafe { .. } = events[0] { - } else { panic!("Wrong event type"); } - } - } } - } - - macro_rules! confirm_txn { - ($node: expr) => { { - let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - let mut txn = Vec::with_capacity(channel_txn.len()); - let mut posn = Vec::with_capacity(channel_txn.len()); - for i in 0..channel_txn.len() { - txn.push(&channel_txn[i]); - posn.push(i as u32 + 1); - } - $node.block_connected(&header, 1, &txn, &posn); - for i in 2..100 { - header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - $node.block_connected(&header, i, &Vec::new(), &[0; 0]); - } - } } - } - - macro_rules! lock_fundings { - ($nodes: expr) => { { - let mut node_events = Vec::new(); - for node in $nodes.iter() { - node_events.push(node.get_and_clear_pending_msg_events()); - } - for (idx, node_event) in node_events.iter().enumerate() { - for event in node_event { - if let events::MessageSendEvent::SendFundingLocked { ref node_id, ref msg } = event { - for node in $nodes.iter() { - if node.get_our_node_id() == *node_id { - node.handle_funding_locked(&$nodes[idx].get_our_node_id(), msg).unwrap(); - } - } - } else { panic!("Wrong event type"); } - } - } - - for node in $nodes.iter() { - let events = node.get_and_clear_pending_msg_events(); - for event in events { - if let events::MessageSendEvent::SendAnnouncementSignatures { .. } = event { - } else { panic!("Wrong event type"); } - } - } - } } - } - - // 3 nodes is enough to hit all the possible cases, notably unknown-source-unknown-dest - // forwarding. - let (mut node_a, mut monitor_a) = make_node!(0); - let (mut node_b, mut monitor_b) = make_node!(1); - let (mut node_c, mut monitor_c) = make_node!(2); - - let mut nodes = [node_a, node_b, node_c]; - - make_channel!(nodes[0], nodes[1], 0); - make_channel!(nodes[1], nodes[2], 1); - - for node in nodes.iter() { - confirm_txn!(node); - } - - lock_fundings!(nodes); - - let chan_a = nodes[0].list_usable_channels()[0].short_channel_id.unwrap(); - let chan_b = nodes[2].list_usable_channels()[0].short_channel_id.unwrap(); - - let mut payment_id = 0; - - let mut chan_a_disconnected = false; - let mut chan_b_disconnected = false; - let mut ba_events = Vec::new(); - let mut bc_events = Vec::new(); - - let mut node_a_ser = VecWriter(Vec::new()); - nodes[0].write(&mut node_a_ser).unwrap(); - let mut node_b_ser = VecWriter(Vec::new()); - nodes[1].write(&mut node_b_ser).unwrap(); - let mut node_c_ser = VecWriter(Vec::new()); - nodes[2].write(&mut node_c_ser).unwrap(); - - macro_rules! test_err { - ($res: expr) => { - match $res { - Ok(()) => {}, - Err(HandleError { action: Some(ErrorAction::IgnoreError), .. }) => { }, - _ => { $res.unwrap() }, - } - } - } - - macro_rules! test_return { - () => { { - assert_eq!(nodes[0].list_channels().len(), 1); - assert_eq!(nodes[1].list_channels().len(), 2); - assert_eq!(nodes[2].list_channels().len(), 1); - return; - } } - } - - let mut read_pos = 0; - macro_rules! get_slice { - ($len: expr) => { - { - let slice_len = $len as usize; - if data.len() < read_pos + slice_len { - test_return!(); - } - read_pos += slice_len; - &data[read_pos - slice_len..read_pos] - } - } - } - - loop { - macro_rules! send_payment { - ($source: expr, $dest: expr) => { { - let payment_hash = Sha256::hash(&[payment_id; 1]); - payment_id = payment_id.wrapping_add(1); - if let Err(_) = $source.send_payment(Route { - hops: vec![RouteHop { - pubkey: $dest.0.get_our_node_id(), - short_channel_id: $dest.1, - fee_msat: 5000000, - cltv_expiry_delta: 200, - }], - }, PaymentHash(payment_hash.into_inner())) { - // Probably ran out of funds - test_return!(); - } - } }; - ($source: expr, $middle: expr, $dest: expr) => { { - let payment_hash = Sha256::hash(&[payment_id; 1]); - payment_id = payment_id.wrapping_add(1); - if let Err(_) = $source.send_payment(Route { - hops: vec![RouteHop { - pubkey: $middle.0.get_our_node_id(), - short_channel_id: $middle.1, - fee_msat: 50000, - cltv_expiry_delta: 100, - },RouteHop { - pubkey: $dest.0.get_our_node_id(), - short_channel_id: $dest.1, - fee_msat: 5000000, - cltv_expiry_delta: 200, - }], - }, PaymentHash(payment_hash.into_inner())) { - // Probably ran out of funds - test_return!(); - } - } } - } - - macro_rules! process_msg_events { - ($node: expr, $corrupt_forward: expr) => { { - let events = if $node == 1 { - let mut new_events = Vec::new(); - mem::swap(&mut new_events, &mut ba_events); - new_events.extend_from_slice(&bc_events[..]); - bc_events.clear(); - new_events - } else { Vec::new() }; - for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) { - match event { - events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { - for dest in nodes.iter() { - if dest.get_our_node_id() == *node_id { - assert!(update_fee.is_none()); - for update_add in update_add_htlcs { - if !$corrupt_forward { - test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &update_add)); - } else { - // Corrupt the update_add_htlc message so that its HMAC - // check will fail and we generate a - // update_fail_malformed_htlc instead of an - // update_fail_htlc as we do when we reject a payment. - let mut msg_ser = update_add.encode(); - msg_ser[1000] ^= 0xff; - let new_msg = UpdateAddHTLC::read(&mut Cursor::new(&msg_ser)).unwrap(); - test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &new_msg)); - } - } - for update_fulfill in update_fulfill_htlcs { - test_err!(dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), &update_fulfill)); - } - for update_fail in update_fail_htlcs { - test_err!(dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), &update_fail)); - } - for update_fail_malformed in update_fail_malformed_htlcs { - test_err!(dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), &update_fail_malformed)); - } - test_err!(dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed)); - } - } - }, - events::MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { - for dest in nodes.iter() { - if dest.get_our_node_id() == *node_id { - test_err!(dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg)); - } - } - }, - events::MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => { - for dest in nodes.iter() { - if dest.get_our_node_id() == *node_id { - test_err!(dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg)); - } - } - }, - events::MessageSendEvent::SendFundingLocked { .. } => { - // Can be generated as a reestablish response - }, - events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => { - // Can be generated due to a payment forward being rejected due to a - // channel having previously failed a monitor update - }, - _ => panic!("Unhandled message event"), - } - } - } } - } - - macro_rules! drain_msg_events_on_disconnect { - ($counterparty_id: expr) => { { - if $counterparty_id == 0 { - for event in nodes[0].get_and_clear_pending_msg_events() { - match event { - events::MessageSendEvent::UpdateHTLCs { .. } => {}, - events::MessageSendEvent::SendRevokeAndACK { .. } => {}, - events::MessageSendEvent::SendChannelReestablish { .. } => {}, - events::MessageSendEvent::SendFundingLocked { .. } => {}, - events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, - _ => panic!("Unhandled message event"), - } - } - ba_events.clear(); - } else { - for event in nodes[2].get_and_clear_pending_msg_events() { - match event { - events::MessageSendEvent::UpdateHTLCs { .. } => {}, - events::MessageSendEvent::SendRevokeAndACK { .. } => {}, - events::MessageSendEvent::SendChannelReestablish { .. } => {}, - events::MessageSendEvent::SendFundingLocked { .. } => {}, - events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, - _ => panic!("Unhandled message event"), - } - } - bc_events.clear(); - } - let mut events = nodes[1].get_and_clear_pending_msg_events(); - let drop_node_id = if $counterparty_id == 0 { nodes[0].get_our_node_id() } else { nodes[2].get_our_node_id() }; - let msg_sink = if $counterparty_id == 0 { &mut bc_events } else { &mut ba_events }; - for event in events.drain(..) { - let push = match event { - events::MessageSendEvent::UpdateHTLCs { ref node_id, .. } => { - if *node_id != drop_node_id { true } else { false } - }, - events::MessageSendEvent::SendRevokeAndACK { ref node_id, .. } => { - if *node_id != drop_node_id { true } else { false } - }, - events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => { - if *node_id != drop_node_id { true } else { false } - }, - events::MessageSendEvent::SendFundingLocked { .. } => false, - events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => false, - _ => panic!("Unhandled message event"), - }; - if push { msg_sink.push(event); } - } - } } - } - - macro_rules! process_events { - ($node: expr, $fail: expr) => { { - // In case we get 256 payments we may have a hash collision, resulting in the - // second claim/fail call not finding the duplicate-hash HTLC, so we have to - // deduplicate the calls here. - let mut claim_set = HashSet::new(); - let mut events = nodes[$node].get_and_clear_pending_events(); - // Sort events so that PendingHTLCsForwardable get processed last. This avoids a - // case where we first process a PendingHTLCsForwardable, then claim/fail on a - // PaymentReceived, claiming/failing two HTLCs, but leaving a just-generated - // PaymentReceived event for the second HTLC in our pending_events (and breaking - // our claim_set deduplication). - events.sort_by(|a, b| { - if let events::Event::PaymentReceived { .. } = a { - if let events::Event::PendingHTLCsForwardable { .. } = b { - Ordering::Less - } else { Ordering::Equal } - } else if let events::Event::PendingHTLCsForwardable { .. } = a { - if let events::Event::PaymentReceived { .. } = b { - Ordering::Greater - } else { Ordering::Equal } - } else { Ordering::Equal } - }); - for event in events.drain(..) { - match event { - events::Event::PaymentReceived { payment_hash, .. } => { - if claim_set.insert(payment_hash.0) { - if $fail { - assert!(nodes[$node].fail_htlc_backwards(&payment_hash)); - } else { - assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0))); - } - } - }, - events::Event::PaymentSent { .. } => {}, - events::Event::PaymentFailed { .. } => {}, - events::Event::PendingHTLCsForwardable { .. } => { - nodes[$node].process_pending_htlc_forwards(); - }, - _ => panic!("Unhandled event"), - } - } - } } - } - - match get_slice!(1)[0] { - 0x00 => *monitor_a.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), - 0x01 => *monitor_b.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), - 0x02 => *monitor_c.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), - 0x03 => *monitor_a.update_ret.lock().unwrap() = Ok(()), - 0x04 => *monitor_b.update_ret.lock().unwrap() = Ok(()), - 0x05 => *monitor_c.update_ret.lock().unwrap() = Ok(()), - 0x06 => { unsafe { IN_RESTORE = true }; nodes[0].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, - 0x07 => { unsafe { IN_RESTORE = true }; nodes[1].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, - 0x08 => { unsafe { IN_RESTORE = true }; nodes[2].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, - 0x09 => send_payment!(nodes[0], (&nodes[1], chan_a)), - 0x0a => send_payment!(nodes[1], (&nodes[0], chan_a)), - 0x0b => send_payment!(nodes[1], (&nodes[2], chan_b)), - 0x0c => send_payment!(nodes[2], (&nodes[1], chan_b)), - 0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)), - 0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)), - 0x0f => { - if !chan_a_disconnected { - nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); - nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); - chan_a_disconnected = true; - drain_msg_events_on_disconnect!(0); - } - }, - 0x10 => { - if !chan_b_disconnected { - nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); - nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false); - chan_b_disconnected = true; - drain_msg_events_on_disconnect!(2); - } - }, - 0x11 => { - if chan_a_disconnected { - nodes[0].peer_connected(&nodes[1].get_our_node_id()); - nodes[1].peer_connected(&nodes[0].get_our_node_id()); - chan_a_disconnected = false; - } - }, - 0x12 => { - if chan_b_disconnected { - nodes[1].peer_connected(&nodes[2].get_our_node_id()); - nodes[2].peer_connected(&nodes[1].get_our_node_id()); - chan_b_disconnected = false; - } - }, - 0x13 => process_msg_events!(0, true), - 0x14 => process_msg_events!(0, false), - 0x15 => process_events!(0, true), - 0x16 => process_events!(0, false), - 0x17 => process_msg_events!(1, true), - 0x18 => process_msg_events!(1, false), - 0x19 => process_events!(1, true), - 0x1a => process_events!(1, false), - 0x1b => process_msg_events!(2, true), - 0x1c => process_msg_events!(2, false), - 0x1d => process_events!(2, true), - 0x1e => process_events!(2, false), - 0x1f => { - if !chan_a_disconnected { - nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); - chan_a_disconnected = true; - drain_msg_events_on_disconnect!(0); - } - let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a); - node_a = Arc::new(new_node_a); - nodes[0] = node_a.clone(); - monitor_a = new_monitor_a; - }, - 0x20 => { - if !chan_a_disconnected { - nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); - chan_a_disconnected = true; - nodes[0].get_and_clear_pending_msg_events(); - ba_events.clear(); - } - if !chan_b_disconnected { - nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false); - chan_b_disconnected = true; - nodes[2].get_and_clear_pending_msg_events(); - bc_events.clear(); - } - let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b); - node_b = Arc::new(new_node_b); - nodes[1] = node_b.clone(); - monitor_b = new_monitor_b; - }, - 0x21 => { - if !chan_b_disconnected { - nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); - chan_b_disconnected = true; - drain_msg_events_on_disconnect!(2); - } - let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c); - node_c = Arc::new(new_node_c); - nodes[2] = node_c.clone(); - monitor_c = new_monitor_c; - }, - _ => test_return!(), - } - - if monitor_a.should_update_manager.load(atomic::Ordering::Relaxed) { - node_a_ser.0.clear(); - nodes[0].write(&mut node_a_ser).unwrap(); - monitor_a.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_a.latest_updates_good_at_last_ser.lock().unwrap() = monitor_a.latest_update_good.lock().unwrap().clone(); - } - if monitor_b.should_update_manager.load(atomic::Ordering::Relaxed) { - node_b_ser.0.clear(); - nodes[1].write(&mut node_b_ser).unwrap(); - monitor_b.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_b.latest_updates_good_at_last_ser.lock().unwrap() = monitor_b.latest_update_good.lock().unwrap().clone(); - } - if monitor_c.should_update_manager.load(atomic::Ordering::Relaxed) { - node_c_ser.0.clear(); - nodes[2].write(&mut node_c_ser).unwrap(); - monitor_c.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_c.latest_updates_good_at_last_ser.lock().unwrap() = monitor_c.latest_update_good.lock().unwrap().clone(); - } - } -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -#[cfg(feature = "libfuzzer_fuzz")] -#[macro_use] extern crate libfuzzer_sys; -#[cfg(feature = "libfuzzer_fuzz")] -fuzz_target!(|data: &[u8]| { - do_test(data); -}); - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs deleted file mode 100644 index 6145d003b..000000000 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ /dev/null @@ -1,890 +0,0 @@ -//! Test that no series of bytes received over the wire/connections created/payments sent can -//! result in a crash. We do this by standing up a node and then reading bytes from input to denote -//! actions such as creating new inbound/outbound connections, bytes to be read from a connection, -//! or payments to send/ways to handle events generated. -//! This test has been very useful, though due to its complexity good starting inputs are critical. - -//Uncomment this for libfuzzer builds: -//#![no_main] - -extern crate bitcoin; -extern crate bitcoin_hashes; -extern crate lightning; -extern crate secp256k1; - -use bitcoin::blockdata::block::BlockHeader; -use bitcoin::blockdata::transaction::{Transaction, TxOut}; -use bitcoin::blockdata::script::{Builder, Script}; -use bitcoin::blockdata::opcodes; -use bitcoin::consensus::encode::deserialize; -use bitcoin::network::constants::Network; -use bitcoin::util::hash::BitcoinHash; - -use bitcoin_hashes::Hash as TraitImport; -use bitcoin_hashes::HashEngine as TraitImportEngine; -use bitcoin_hashes::sha256::Hash as Sha256; -use bitcoin_hashes::hash160::Hash as Hash160; -use bitcoin_hashes::sha256d::Hash as Sha256dHash; - -use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; -use lightning::chain::transaction::OutPoint; -use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; -use lightning::ln::channelmonitor; -use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage}; -use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; -use lightning::ln::router::Router; -use lightning::util::events::{EventsProvider,Event}; -use lightning::util::logger::Logger; -use lightning::util::config::UserConfig; - -mod utils; - -use utils::test_logger; - -use secp256k1::key::{PublicKey,SecretKey}; -use secp256k1::Secp256k1; - -use std::cell::RefCell; -use std::collections::{HashMap, hash_map}; -use std::cmp; -use std::hash::Hash; -use std::sync::Arc; -use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering}; - -#[inline] -pub fn slice_to_be16(v: &[u8]) -> u16 { - ((v[0] as u16) << 8*1) | - ((v[1] as u16) << 8*0) -} - -#[inline] -pub fn slice_to_be24(v: &[u8]) -> u32 { - ((v[0] as u32) << 8*2) | - ((v[1] as u32) << 8*1) | - ((v[2] as u32) << 8*0) -} - -#[inline] -pub fn slice_to_be32(v: &[u8]) -> u32 { - ((v[0] as u32) << 8*3) | - ((v[1] as u32) << 8*2) | - ((v[2] as u32) << 8*1) | - ((v[3] as u32) << 8*0) -} - -#[inline] -pub fn be64_to_array(u: u64) -> [u8; 8] { - let mut v = [0; 8]; - v[0] = ((u >> 8*7) & 0xff) as u8; - v[1] = ((u >> 8*6) & 0xff) as u8; - v[2] = ((u >> 8*5) & 0xff) as u8; - v[3] = ((u >> 8*4) & 0xff) as u8; - v[4] = ((u >> 8*3) & 0xff) as u8; - v[5] = ((u >> 8*2) & 0xff) as u8; - v[6] = ((u >> 8*1) & 0xff) as u8; - v[7] = ((u >> 8*0) & 0xff) as u8; - v -} - -struct InputData { - data: Vec, - read_pos: AtomicUsize, -} -impl InputData { - fn get_slice(&self, len: usize) -> Option<&[u8]> { - let old_pos = self.read_pos.fetch_add(len, Ordering::AcqRel); - if self.data.len() < old_pos + len { - return None; - } - Some(&self.data[old_pos..old_pos + len]) - } -} - -struct FuzzEstimator { - input: Arc, -} -impl FeeEstimator for FuzzEstimator { - fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u64 { - //TODO: We should actually be testing at least much more than 64k... - match self.input.get_slice(2) { - Some(slice) => cmp::max(slice_to_be16(slice) as u64, 253), - None => 0 - } - } -} - -struct TestBroadcaster {} -impl BroadcasterInterface for TestBroadcaster { - fn broadcast_transaction(&self, _tx: &Transaction) {} -} - -#[derive(Clone)] -struct Peer<'a> { - id: u8, - peers_connected: &'a RefCell<[bool; 256]>, -} -impl<'a> SocketDescriptor for Peer<'a> { - fn send_data(&mut self, data: &[u8], _resume_read: bool) -> usize { - data.len() - } - fn disconnect_socket(&mut self) { - assert!(self.peers_connected.borrow()[self.id as usize]); - self.peers_connected.borrow_mut()[self.id as usize] = false; - } -} -impl<'a> PartialEq for Peer<'a> { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} -impl<'a> Eq for Peer<'a> {} -impl<'a> Hash for Peer<'a> { - fn hash(&self, h: &mut H) { - self.id.hash(h) - } -} - -struct MoneyLossDetector<'a> { - manager: Arc, - monitor: Arc>, - handler: PeerManager>, - - peers: &'a RefCell<[bool; 256]>, - funding_txn: Vec, - txids_confirmed: HashMap, - header_hashes: Vec, - height: usize, - max_height: usize, - blocks_connected: u32, -} -impl<'a> MoneyLossDetector<'a> { - pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc, monitor: Arc>, handler: PeerManager>) -> Self { - MoneyLossDetector { - manager, - monitor, - handler, - - peers, - funding_txn: Vec::new(), - txids_confirmed: HashMap::new(), - header_hashes: vec![Default::default()], - height: 0, - max_height: 0, - blocks_connected: 0, - } - } - - fn connect_block(&mut self, all_txn: &[Transaction]) { - let mut txn = Vec::with_capacity(all_txn.len()); - let mut txn_idxs = Vec::with_capacity(all_txn.len()); - for (idx, tx) in all_txn.iter().enumerate() { - let txid = tx.txid(); - match self.txids_confirmed.entry(txid) { - hash_map::Entry::Vacant(e) => { - e.insert(self.height); - txn.push(tx); - txn_idxs.push(idx as u32 + 1); - }, - _ => {}, - } - } - - let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 }; - self.height += 1; - self.blocks_connected += 1; - self.manager.block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]); - (*self.monitor).block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]); - if self.header_hashes.len() > self.height { - self.header_hashes[self.height] = header.bitcoin_hash(); - } else { - assert_eq!(self.header_hashes.len(), self.height); - self.header_hashes.push(header.bitcoin_hash()); - } - self.max_height = cmp::max(self.height, self.max_height); - } - - fn disconnect_block(&mut self) { - if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) { - self.height -= 1; - let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - self.manager.block_disconnected(&header, self.height as u32); - self.monitor.block_disconnected(&header, self.height as u32); - let removal_height = self.height; - self.txids_confirmed.retain(|_, height| { - removal_height != *height - }); - } - } -} - -impl<'a> Drop for MoneyLossDetector<'a> { - fn drop(&mut self) { - if !::std::thread::panicking() { - // Disconnect all peers - for (idx, peer) in self.peers.borrow().iter().enumerate() { - if *peer { - self.handler.disconnect_event(&Peer{id: idx as u8, peers_connected: &self.peers}); - } - } - - // Force all channels onto the chain (and time out claim txn) - self.manager.force_close_all_channels(); - } - } -} - -struct KeyProvider { - node_secret: SecretKey, - counter: AtomicU64, -} -impl KeysInterface for KeyProvider { - fn get_node_secret(&self) -> SecretKey { - self.node_secret.clone() - } - - fn get_destination_script(&self) -> Script { - let secp_ctx = Secp256k1::signing_only(); - let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); - let our_channel_monitor_claim_key_hash = ::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() - } - - fn get_shutdown_pubkey(&self) -> PublicKey { - let secp_ctx = Secp256k1::signing_only(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()) - } - - fn get_channel_keys(&self, inbound: bool) -> ChannelKeys { - let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; - if inbound { - ChannelKeys { - funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ctr]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ctr]).unwrap(), - payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ctr]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ctr]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, ctr]).unwrap(), - commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr], - } - } else { - ChannelKeys { - funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, ctr]).unwrap(), - revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, ctr]).unwrap(), - payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, ctr]).unwrap(), - delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, ctr]).unwrap(), - htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, ctr]).unwrap(), - commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr], - } - } - } - - fn get_session_key(&self) -> SecretKey { - let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; - SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, ctr]).unwrap() - } - - fn get_channel_id(&self) -> [u8; 32] { - let ctr = self.counter.fetch_add(1, Ordering::Relaxed); - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8] - } -} - -#[inline] -pub fn do_test(data: &[u8], logger: &Arc) { - let input = Arc::new(InputData { - data: data.to_vec(), - read_pos: AtomicUsize::new(0), - }); - let fee_est = Arc::new(FuzzEstimator { - input: input.clone(), - }); - - macro_rules! get_slice { - ($len: expr) => { - match input.get_slice($len as usize) { - Some(slice) => slice, - None => return, - } - } - } - - macro_rules! get_pubkey { - () => { - match PublicKey::from_slice(get_slice!(33)) { - Ok(key) => key, - Err(_) => return, - } - } - } - - let our_network_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, - }; - - let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); - let broadcast = Arc::new(TestBroadcaster{}); - let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger), fee_est.clone()); - - let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), counter: AtomicU64::new(0) }); - let mut config = UserConfig::new(); - config.channel_options.fee_proportional_millionths = slice_to_be32(get_slice!(4)); - config.channel_options.announced_channel = get_slice!(1)[0] != 0; - config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - let channelmanager = ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap(); - let router = Arc::new(Router::new(PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret()), watch.clone(), Arc::clone(&logger))); - - let peers = RefCell::new([false; 256]); - let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler { - chan_handler: channelmanager.clone(), - route_handler: router.clone(), - }, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger))); - - let mut should_forward = false; - let mut payments_received: Vec = Vec::new(); - let mut payments_sent = 0; - let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new(); - let mut pending_funding_signatures = HashMap::new(); - let mut pending_funding_relay = Vec::new(); - - loop { - match get_slice!(1)[0] { - 0 => { - let mut new_id = 0; - for i in 1..256 { - if !peers.borrow()[i-1] { - new_id = i; - break; - } - } - if new_id == 0 { return; } - loss_detector.handler.new_outbound_connection(get_pubkey!(), Peer{id: (new_id - 1) as u8, peers_connected: &peers}).unwrap(); - peers.borrow_mut()[new_id - 1] = true; - }, - 1 => { - let mut new_id = 0; - for i in 1..256 { - if !peers.borrow()[i-1] { - new_id = i; - break; - } - } - if new_id == 0 { return; } - loss_detector.handler.new_inbound_connection(Peer{id: (new_id - 1) as u8, peers_connected: &peers}).unwrap(); - peers.borrow_mut()[new_id - 1] = true; - }, - 2 => { - let peer_id = get_slice!(1)[0]; - if !peers.borrow()[peer_id as usize] { return; } - loss_detector.handler.disconnect_event(&Peer{id: peer_id, peers_connected: &peers}); - peers.borrow_mut()[peer_id as usize] = false; - }, - 3 => { - let peer_id = get_slice!(1)[0]; - if !peers.borrow()[peer_id as usize] { return; } - match loss_detector.handler.read_event(&mut Peer{id: peer_id, peers_connected: &peers}, get_slice!(get_slice!(1)[0]).to_vec()) { - Ok(res) => assert!(!res), - Err(_) => { peers.borrow_mut()[peer_id as usize] = false; } - } - }, - 4 => { - let value = slice_to_be24(get_slice!(3)) as u64; - let route = match router.get_route(&get_pubkey!(), None, &Vec::new(), value, 42) { - Ok(route) => route, - Err(_) => return, - }; - let mut payment_hash = PaymentHash([0; 32]); - payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent)); - let mut sha = Sha256::engine(); - sha.input(&payment_hash.0[..]); - payment_hash.0 = Sha256::from_engine(sha).into_inner(); - payments_sent += 1; - match channelmanager.send_payment(route, payment_hash) { - Ok(_) => {}, - Err(_) => return, - } - }, - 5 => { - let peer_id = get_slice!(1)[0]; - if !peers.borrow()[peer_id as usize] { return; } - let their_key = get_pubkey!(); - let chan_value = slice_to_be24(get_slice!(3)) as u64; - let push_msat_value = slice_to_be24(get_slice!(3)) as u64; - if channelmanager.create_channel(their_key, chan_value, push_msat_value, 0).is_err() { return; } - }, - 6 => { - let mut channels = channelmanager.list_channels(); - let channel_id = get_slice!(1)[0] as usize; - if channel_id >= channels.len() { return; } - channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) }); - if channelmanager.close_channel(&channels[channel_id].channel_id).is_err() { return; } - }, - 7 => { - if should_forward { - channelmanager.process_pending_htlc_forwards(); - should_forward = false; - } - }, - 8 => { - for payment in payments_received.drain(..) { - // SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s - // for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot - // fulfill this HTLC, but if they are, we can just take the first byte and - // place that anywhere in our preimage. - if &payment.0[1..] != &[0; 31] { - channelmanager.fail_htlc_backwards(&payment); - } else { - let mut payment_preimage = PaymentPreimage([0; 32]); - payment_preimage.0[0] = payment.0[0]; - channelmanager.claim_funds(payment_preimage); - } - } - }, - 9 => { - for payment in payments_received.drain(..) { - channelmanager.fail_htlc_backwards(&payment); - } - }, - 10 => { - 'outer_loop: for funding_generation in pending_funding_generation.drain(..) { - let mut tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: vec![TxOut { - value: funding_generation.1, script_pubkey: funding_generation.2, - }] }; - let funding_output = 'search_loop: loop { - let funding_txid = tx.txid(); - if let None = loss_detector.txids_confirmed.get(&funding_txid) { - let outpoint = OutPoint::new(funding_txid, 0); - for chan in channelmanager.list_channels() { - if chan.channel_id == outpoint.to_channel_id() { - tx.version += 1; - continue 'search_loop; - } - } - break outpoint; - } - tx.version += 1; - if tx.version > 0xff { - continue 'outer_loop; - } - }; - channelmanager.funding_transaction_generated(&funding_generation.0, funding_output.clone()); - pending_funding_signatures.insert(funding_output, tx); - } - }, - 11 => { - if !pending_funding_relay.is_empty() { - loss_detector.connect_block(&pending_funding_relay[..]); - for _ in 2..100 { - loss_detector.connect_block(&[]); - } - } - for tx in pending_funding_relay.drain(..) { - loss_detector.funding_txn.push(tx); - } - }, - 12 => { - let txlen = slice_to_be16(get_slice!(2)); - if txlen == 0 { - loss_detector.connect_block(&[]); - } else { - let txres: Result = deserialize(get_slice!(txlen)); - if let Ok(tx) = txres { - loss_detector.connect_block(&[tx]); - } else { - return; - } - } - }, - 13 => { - loss_detector.disconnect_block(); - }, - 14 => { - let mut channels = channelmanager.list_channels(); - let channel_id = get_slice!(1)[0] as usize; - if channel_id >= channels.len() { return; } - channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) }); - channelmanager.force_close_channel(&channels[channel_id].channel_id); - }, - _ => return, - } - loss_detector.handler.process_events(); - for event in loss_detector.manager.get_and_clear_pending_events() { - match event { - Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => { - pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script)); - }, - Event::FundingBroadcastSafe { funding_txo, .. } => { - pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap()); - }, - Event::PaymentReceived { payment_hash, .. } => { - payments_received.push(payment_hash); - }, - Event::PaymentSent {..} => {}, - Event::PaymentFailed {..} => {}, - Event::PendingHTLCsForwardable {..} => { - should_forward = true; - }, - Event::SpendableOutputs {..} => {}, - } - } - } -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - do_test(data, &logger); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - do_test(data, &logger); - }); - } -} - -#[cfg(feature = "libfuzzer_fuzz")] -#[macro_use] extern crate libfuzzer_sys; -#[cfg(feature = "libfuzzer_fuzz")] -fuzz_target!(|data: &[u8]| { - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - do_test(data, &logger); -}); - -extern crate hex; -#[cfg(test)] -mod tests { - use utils::test_logger; - use lightning::util::logger::{Logger, Record}; - use std::collections::HashMap; - use std::sync::{Arc, Mutex}; - - #[test] - fn duplicate_crash() { - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - super::do_test(&::hex::decode("00").unwrap(), &logger); - } - - struct TrackingLogger { - /// (module, message) -> count - pub lines: Mutex>, - } - impl Logger for TrackingLogger { - fn log(&self, record: &Record) { - *self.lines.lock().unwrap().entry((record.module_path.to_string(), format!("{}", record.args))).or_insert(0) += 1; - println!("{:<5} [{} : {}, {}] {}", record.level.to_string(), record.module_path, record.file, record.line, record.args); - } - } - - #[test] - fn test_no_existing_test_breakage() { - // To avoid accidentally causing all existing fuzz test cases to be useless by making minor - // changes (such as requesting feerate info in a new place), we run a pretty full - // step-through with two peers and HTLC forwarding here. Obviously this is pretty finicky, - // so this should be updated pretty liberally, but at least we'll know when changes occur. - // If nothing else, this test serves as a pretty great initial full_stack_target seed. - - // What each byte represents is broken down below, and then everything is concatenated into - // one large test at the end (you want %s/ -.*//g %s/\n\| \|\t\|\///g). - - // Following BOLT 8, lightning message on the wire are: 2-byte encrypted message length + - // 16-byte MAC of the encrypted message length + encrypted Lightning message + 16-byte MAC - // of the Lightning message - // I.e 2nd inbound read, len 18 : 0006 (encrypted message length) + 03000000000000000000000000000000 (MAC of the encrypted message length) - // Len 22 : 0010 00000000 (encrypted lightning message) + 03000000000000000000000000000000 (MAC of the Lightning message) - - // 0000000000000000000000000000000000000000000000000000000000000000 - our network key - // 00000000 - fee_proportional_millionths - // 01 - announce_channels_publicly - // - // 00 - new outbound connection with id 0 - // 030000000000000000000000000000000000000000000000000000000000000000 - peer's pubkey - // 030032 - inbound read from peer id 0 of len 50 - // 00 030000000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - noise act two (0||pubkey||mac) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0006 03000000000000000000000000000000 - message header indicating message length 6 - // 030016 - inbound read from peer id 0 of len 22 - // 0010 00000000 03000000000000000000000000000000 - init message with no features (type 16) and mac - // - // 030012 - inbound read from peer id 0 of len 18 - // 0141 03000000000000000000000000000000 - message header indicating message length 321 - // 0300fe - inbound read from peer id 0 of len 254 - // 0020 7500000000000000000000000000000000000000000000000000000000000000 ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679 000000000000c350 0000000000000000 0000000000000222 ffffffffffffffff 0000000000000222 0000000000000000 000000fd 0006 01e3 030000000000000000000000000000000000000000000000000000000000000001 030000000000000000000000000000000000000000000000000000000000000002 030000000000000000000000000000000000000000000000000000000000000003 030000000000000000000000000000000000000000000000000000000000000004 - beginning of open_channel message - // 030053 - inbound read from peer id 0 of len 83 - // 030000000000000000000000000000000000000000000000000000000000000005 030000000000000000000000000000000000000000000000000000000000000000 01 03000000000000000000000000000000 - rest of open_channel and mac - // - // 00fd00fd00fd - Three feerate requests (all returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // - client should now respond with accept_channel (CHECK 1: type 33 to peer 03000000) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0084 03000000000000000000000000000000 - message header indicating message length 132 - // 030094 - inbound read from peer id 0 of len 148 - // 0022 ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679 3d00000000000000000000000000000000000000000000000000000000000000 0000 5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 03000000000000000000000000000000 - funding_created and mac - // - client should now respond with funding_signed (CHECK 2: type 35 to peer 03000000) - // - // 0c005e - connect a block with one transaction of len 94 - // 020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000 - the funding transaction - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // - by now client should have sent a funding_locked (CHECK 3: SendFundingLocked to 03000000 for chan 3d000000) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0043 03000000000000000000000000000000 - message header indicating message length 67 - // 030053 - inbound read from peer id 0 of len 83 - // 0024 3d00000000000000000000000000000000000000000000000000000000000000 030100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - funding_locked and mac - // - // 01 - new inbound connection with id 1 - // 030132 - inbound read from peer id 1 of len 50 - // 0003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000 - inbound noise act 1 - // 030142 - inbound read from peer id 1 of len 66 - // 000302000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003000000000000000000000000000000 - inbound noise act 3 - // - // 030112 - inbound read from peer id 1 of len 18 - // 0006 01000000000000000000000000000000 - message header indicating message length 6 - // 030116 - inbound read from peer id 1 of len 22 - // 0010 00000000 01000000000000000000000000000000 - init message with no features (type 16) - // - // 05 01 030200000000000000000000000000000000000000000000000000000000000000 00c350 0003e8 - create outbound channel to peer 1 for 50k sat - // 00fd00fd00fd - Three feerate requests (all returning min feerate) (gonna be ingested by FuzzEstimator) - // - // 030112 - inbound read from peer id 1 of len 18 - // 0110 01000000000000000000000000000000 - message header indicating message length 272 - // 0301ff - inbound read from peer id 1 of len 255 - // 0021 0000000000000000000000000000000000000000000000000000000000000e02 000000000000001a 00000000004c4b40 00000000000003e8 00000000000003e8 00000002 03f0 0005 030000000000000000000000000000000000000000000000000000000000000100 030000000000000000000000000000000000000000000000000000000000000200 030000000000000000000000000000000000000000000000000000000000000300 030000000000000000000000000000000000000000000000000000000000000400 030000000000000000000000000000000000000000000000000000000000000500 03000000000000000000000000000000 - beginning of accept_channel - // 030121 - inbound read from peer id 1 of len 33 - // 0000000000000000000000000000000000 01000000000000000000000000000000 - rest of accept_channel and mac - // - // 0a - create the funding transaction (client should send funding_created now) - // - // 030112 - inbound read from peer id 1 of len 18 - // 0062 01000000000000000000000000000000 - message header indicating message length 98 - // 030172 - inbound read from peer id 1 of len 114 - // 0023 3900000000000000000000000000000000000000000000000000000000000000 f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 01000000000000000000000000000000 - funding_signed message and mac - // - // 0b - broadcast funding transaction - // - by now client should have sent a funding_locked (CHECK 4: SendFundingLocked to 03020000 for chan 3f000000) - // - // 030112 - inbound read from peer id 1 of len 18 - // 0043 01000000000000000000000000000000 - message header indicating message length 67 - // 030153 - inbound read from peer id 1 of len 83 - // 0024 3900000000000000000000000000000000000000000000000000000000000000 030100000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - funding_locked and mac - // - // 030012 - inbound read from peer id 0 of len 18 - // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 - // 0300ff - inbound read from peer id 0 of len 255 - // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000000 0000000000003e80 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300c1 - inbound read from peer id 0 of len 193 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac - // - // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0064 03000000000000000000000000000000 - message header indicating message length 100 - // 030074 - inbound read from peer id 0 of len 116 - // 0084 3d00000000000000000000000000000000000000000000000000000000000000 4d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac - // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6: types 133 and 132 to peer 03000000) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0063 03000000000000000000000000000000 - message header indicating message length 99 - // 030073 - inbound read from peer id 0 of len 115 - // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 030200000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac - // - // 07 - process the now-pending HTLC forward - // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: SendHTLCs event for node 03020000 with 1 HTLCs for channel 3f000000) - // - // - we respond with commitment_signed then revoke_and_ack (a weird, but valid, order) - // 030112 - inbound read from peer id 1 of len 18 - // 0064 01000000000000000000000000000000 - message header indicating message length 100 - // 030174 - inbound read from peer id 1 of len 116 - // 0084 3900000000000000000000000000000000000000000000000000000000000000 f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 0063 01000000000000000000000000000000 - message header indicating message length 99 - // 030173 - inbound read from peer id 1 of len 115 - // 0085 3900000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 030200000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 004a 01000000000000000000000000000000 - message header indicating message length 74 - // 03015a - inbound read from peer id 1 of len 90 - // 0082 3900000000000000000000000000000000000000000000000000000000000000 0000000000000000 ff00888888888888888888888888888888888888888888888888888888888888 01000000000000000000000000000000 - update_fulfill_htlc and mac - // - client should immediately claim the pending HTLC from peer 0 (CHECK 8: SendFulfillHTLCs for node 03000000 with preimage ff00888888 for channel 3d000000) - // - // 030112 - inbound read from peer id 1 of len 18 - // 0064 01000000000000000000000000000000 - message header indicating message length 100 - // 030174 - inbound read from peer id 1 of len 116 - // 0084 3900000000000000000000000000000000000000000000000000000000000000 fd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 0063 01000000000000000000000000000000 - message header indicating message length 99 - // 030173 - inbound read from peer id 1 of len 115 - // 0085 3900000000000000000000000000000000000000000000000000000000000000 0100000000000000000000000000000000000000000000000000000000000000 030300000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac - // - // - before responding to the commitment_signed generated above, send a new HTLC - // 030012 - inbound read from peer id 0 of len 18 - // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 - // 0300ff - inbound read from peer id 0 of len 255 - // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000000000003e80 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300c1 - inbound read from peer id 0 of len 193 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac - // - // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // - // - now respond to the update_fulfill_htlc+commitment_signed messages the client sent to peer 0 - // 030012 - inbound read from peer id 0 of len 18 - // 0063 03000000000000000000000000000000 - message header indicating message length 99 - // 030073 - inbound read from peer id 0 of len 115 - // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0100000000000000000000000000000000000000000000000000000000000000 030300000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac - // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6 duplicates) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0064 03000000000000000000000000000000 - message header indicating message length 100 - // 030074 - inbound read from peer id 0 of len 116 - // 0084 3d00000000000000000000000000000000000000000000000000000000000000 be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac - // - // 030012 - inbound read from peer id 0 of len 18 - // 0063 03000000000000000000000000000000 - message header indicating message length 99 - // 030073 - inbound read from peer id 0 of len 115 - // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0200000000000000000000000000000000000000000000000000000000000000 030400000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac - // - // 07 - process the now-pending HTLC forward - // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) - // - we respond with revoke_and_ack, then commitment_signed, then update_fail_htlc - // - // 030112 - inbound read from peer id 1 of len 18 - // 0064 01000000000000000000000000000000 - message header indicating message length 100 - // 030174 - inbound read from peer id 1 of len 116 - // 0084 3900000000000000000000000000000000000000000000000000000000000000 fc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 0063 01000000000000000000000000000000 - message header indicating message length 99 - // 030173 - inbound read from peer id 1 of len 115 - // 0085 3900000000000000000000000000000000000000000000000000000000000000 0200000000000000000000000000000000000000000000000000000000000000 030400000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 002c 01000000000000000000000000000000 - message header indicating message length 44 - // 03013c - inbound read from peer id 1 of len 60 - // 0083 3900000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000 01000000000000000000000000000000 - update_fail_htlc and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 0064 01000000000000000000000000000000 - message header indicating message length 100 - // 030174 - inbound read from peer id 1 of len 116 - // 0084 3900000000000000000000000000000000000000000000000000000000000000 fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac - // - // 030112 - inbound read from peer id 1 of len 18 - // 0063 01000000000000000000000000000000 - message header indicating message length 99 - // 030173 - inbound read from peer id 1 of len 115 - // 0085 3900000000000000000000000000000000000000000000000000000000000000 0300000000000000000000000000000000000000000000000000000000000000 030500000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac - // - // 07 - process the now-pending HTLC forward - // - client now sends id 0 update_fail_htlc and commitment_signed (CHECK 9) - // - now respond to the update_fail_htlc+commitment_signed messages the client sent to peer 0 - // - // 030012 - inbound read from peer id 0 of len 18 - // 0063 03000000000000000000000000000000 - message header indicating message length 99 - // 030073 - inbound read from peer id 0 of len 115 - // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0300000000000000000000000000000000000000000000000000000000000000 030500000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac - // - // 030012 - inbound read from peer id 0 of len 18 - // 0064 03000000000000000000000000000000 - message header indicating message length 100 - // 030074 - inbound read from peer id 0 of len 116 - // 0084 3d00000000000000000000000000000000000000000000000000000000000000 4f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac - // - client should now respond with revoke_and_ack (CHECK 5 duplicate) - // - // 030012 - inbound read from peer id 0 of len 18 - // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 - // 0300ff - inbound read from peer id 0 of len 255 - // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000002 00000000000b0838 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300ff - inbound read from peer id 0 of len 255 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - // 0300c1 - inbound read from peer id 0 of len 193 - // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac - // - // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // - // 030012 - inbound read from peer id 0 of len 18 - // 00a4 03000000000000000000000000000000 - message header indicating message length 164 - // 0300b4 - inbound read from peer id 0 of len 180 - // 0084 3d00000000000000000000000000000000000000000000000000000000000000 07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0001 c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f00000000000000 03000000000000000000000000000000 - commitment_signed and mac - // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6 duplicates) - // - // 030012 - inbound read from peer id 0 of len 18 - // 0063 03000000000000000000000000000000 - message header indicating message length 99 - // 030073 - inbound read from peer id 0 of len 115 - // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0400000000000000000000000000000000000000000000000000000000000000 030600000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac - // - // 07 - process the now-pending HTLC forward - // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) - // - // 0c007d - connect a block with one transaction of len 125 - // 0200000001390000000000000000000000000000000000000000000000000000000000000000000000000000008002000100000000000022002090000000000000000000000000000000000000000000000000000000000000006cc10000000000001600145c0000000000000000000000000000000000000005000020 - the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000 - // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) - // 0c005e - connect a block with one transaction of len 94 - // 0200000001fd00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f60000000000000000000000000000000000000000000000000000000000000000000000 - the funding transaction - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // 0c0000 - connect a block with no transactions - // - // 07 - process the now-pending HTLC forward - // - client now fails the HTLC backwards as it was unable to extract the payment preimage (CHECK 9 duplicate and CHECK 10) - - let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) }); - super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000603000000000000000000000000000000030016001000000000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d0000000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001030132000300000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003014200030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000300000000000000000000000000000003011200060100000000000000000000000000000003011600100000000001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd00fd0301120110010000000000000000000000000000000301ff00210000000000000000000000000000000000000000000000000000000000000e02000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233900000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b030112004301000000000000000000000000000000030153002439000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a008239000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000301120063010000000000000000000000000000000301730085390000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833900000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000030112006301000000000000000000000000000000030173008539000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d0200000001390000000000000000000000000000000000000000000000000000000000000000000000000000008002000100000000000022002090000000000000000000000000000000000000000000000000000000000000006cc10000000000001600145c000000000000000000000000000000000000000500002000fd00fd0c005e0200000001fd00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f600000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c000007").unwrap(), &(Arc::clone(&logger) as Arc)); - - let log_entries = logger.lines.lock().unwrap(); - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 - assert_eq!(log_entries.get(&("lightning::ln::channelmonitor".to_string(), "Input spending remote commitment tx (00000000000000000000000000000000000000000000000000000000000000fd:0) in 0000000000000000000000000000000000000000000000000000000000000044 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10 - } -} diff --git a/fuzz/fuzz_targets/msg_targets/gen_target.sh b/fuzz/fuzz_targets/msg_targets/gen_target.sh deleted file mode 100755 index cfd100f3d..000000000 --- a/fuzz/fuzz_targets/msg_targets/gen_target.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -GEN_TEST() { - tn=$(echo $1 | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g') - fn=msg_$(echo $tn | tr '[:upper:]' '[:lower:]')_target.rs - cat msg_target_template.txt | sed s/MSG_TARGET/$1/ | sed "s/TEST_MSG/$2/" | sed "s/EXTRA_ARGS/$3/" > $fn -} - -GEN_TEST AcceptChannel test_msg "" -GEN_TEST AnnouncementSignatures test_msg "" -GEN_TEST ChannelReestablish test_msg "" -GEN_TEST ClosingSigned test_msg "" -GEN_TEST CommitmentSigned test_msg "" -GEN_TEST DecodedOnionErrorPacket test_msg "" -GEN_TEST FundingCreated test_msg "" -GEN_TEST FundingLocked test_msg "" -GEN_TEST FundingSigned test_msg "" -GEN_TEST Init test_msg "" -GEN_TEST OpenChannel test_msg "" -GEN_TEST RevokeAndACK test_msg "" -GEN_TEST Shutdown test_msg "" -GEN_TEST UpdateFailHTLC test_msg "" -GEN_TEST UpdateFailMalformedHTLC test_msg "" -GEN_TEST UpdateFee test_msg "" -GEN_TEST UpdateFulfillHTLC test_msg "" - -GEN_TEST ChannelAnnouncement test_msg_exact "" -GEN_TEST ChannelUpdate test_msg_exact "" -GEN_TEST NodeAnnouncement test_msg_exact "" - -GEN_TEST UpdateAddHTLC test_msg_hole ", 85, 33" -GEN_TEST ErrorMessage test_msg_hole ", 32, 2" -GEN_TEST OnionHopData test_msg_hole ", 1+8+8+4, 12" - -GEN_TEST Ping test_msg_simple "" -GEN_TEST Pong test_msg_simple "" diff --git a/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs deleted file mode 100644 index 0f18d0232..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::AcceptChannel, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs b/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs deleted file mode 100644 index 226028ea0..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::AnnouncementSignatures, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs deleted file mode 100644 index 0bdc10e85..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_exact!(msgs::ChannelAnnouncement, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs deleted file mode 100644 index 4af593759..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::ChannelReestablish, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs deleted file mode 100644 index 724dca412..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_exact!(msgs::ChannelUpdate, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs deleted file mode 100644 index faeeae3eb..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::ClosingSigned, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs deleted file mode 100644 index 97c4b3088..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::CommitmentSigned, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs b/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs deleted file mode 100644 index 9b190b086..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::DecodedOnionErrorPacket, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs b/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs deleted file mode 100644 index d749dc91f..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_hole!(msgs::ErrorMessage, data, 32, 2); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs deleted file mode 100644 index 45b257bb0..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::FundingCreated, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs deleted file mode 100644 index cd1e89741..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::FundingLocked, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs deleted file mode 100644 index 5992d6902..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::FundingSigned, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_init_target.rs b/fuzz/fuzz_targets/msg_targets/msg_init_target.rs deleted file mode 100644 index cdca84821..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_init_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::Init, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs b/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs deleted file mode 100644 index f0a7a4c0d..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_exact!(msgs::NodeAnnouncement, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs b/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs deleted file mode 100644 index 058c050c5..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_hole!(msgs::OnionHopData, data, 1+8+8+4, 12); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs deleted file mode 100644 index aa13e96dd..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::OpenChannel, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs b/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs deleted file mode 100644 index d2ea91335..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_simple!(msgs::Ping, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs b/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs deleted file mode 100644 index 18120e2d1..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_simple!(msgs::Pong, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs b/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs deleted file mode 100644 index d82268d93..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::RevokeAndACK, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs b/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs deleted file mode 100644 index 34d4d2003..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::Shutdown, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_target_template.txt b/fuzz/fuzz_targets/msg_targets/msg_target_template.txt deleted file mode 100644 index 2704bcdff..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_target_template.txt +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - TEST_MSG!(msgs::MSG_TARGET, dataEXTRA_ARGS); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs deleted file mode 100644 index e64a5c29f..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg_hole!(msgs::UpdateAddHTLC, data, 85, 33); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs deleted file mode 100644 index fedce568e..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::UpdateFailHTLC, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs deleted file mode 100644 index 377378fcc..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::UpdateFailMalformedHTLC, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs deleted file mode 100644 index 56b9ac424..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::UpdateFee, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs deleted file mode 100644 index f0c936d1e..000000000 --- a/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file is auto-generated by gen_target.sh based on msg_target_template.txt -// To modify it, modify msg_target_template.txt and run gen_target.sh instead. - -extern crate lightning; - -use lightning::ln::msgs; - -mod utils; -use utils::VecWriter; - -#[inline] -pub fn do_test(data: &[u8]) { - test_msg!(msgs::UpdateFulfillHTLC, data); -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/msg_targets/utils.rs b/fuzz/fuzz_targets/msg_targets/utils.rs deleted file mode 100644 index a5257ba0f..000000000 --- a/fuzz/fuzz_targets/msg_targets/utils.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![macro_use] - -use lightning::util::ser::Writer; -pub struct VecWriter(pub Vec); -impl Writer for VecWriter { - fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { - assert!(self.0.capacity() >= self.0.len() + buf.len()); - self.0.extend_from_slice(buf); - Ok(()) - } - fn size_hint(&mut self, size: usize) { - self.0.reserve_exact(size); - } -} - -#[macro_export] -macro_rules! test_msg { - ($MsgType: path, $data: ident) => { - { - use lightning::util::ser::{Writeable, Readable}; - let mut r = ::std::io::Cursor::new($data); - if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { - let p = r.position() as usize; - let mut w = VecWriter(Vec::new()); - msg.write(&mut w).unwrap(); - - assert_eq!(w.0.len(), p); - assert_eq!(&r.into_inner()[..p], &w.0[..p]); - } - } - } -} - -#[macro_export] -macro_rules! test_msg_simple { - ($MsgType: path, $data: ident) => { - { - use lightning::util::ser::{Writeable, Readable}; - let mut r = ::std::io::Cursor::new($data); - if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { - let mut w = VecWriter(Vec::new()); - msg.write(&mut w).unwrap(); - } - } - } -} - -#[macro_export] -macro_rules! test_msg_exact { - ($MsgType: path, $data: ident) => { - { - use lightning::util::ser::{Writeable, Readable}; - let mut r = ::std::io::Cursor::new($data); - if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { - let mut w = VecWriter(Vec::new()); - msg.write(&mut w).unwrap(); - - assert_eq!(&r.into_inner()[..], &w.0[..]); - } - } - } -} - -#[macro_export] -macro_rules! test_msg_hole { - ($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => { - { - use lightning::util::ser::{Writeable, Readable}; - let mut r = ::std::io::Cursor::new($data); - if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { - let mut w = VecWriter(Vec::new()); - msg.write(&mut w).unwrap(); - let p = w.0.len() as usize; - - assert_eq!(w.0.len(), p); - assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]); - assert_eq!(&r.get_ref()[$hole+$hole_len..p], &w.0[$hole+$hole_len..]); - } - } - } -} diff --git a/fuzz/fuzz_targets/peer_crypt_target.rs b/fuzz/fuzz_targets/peer_crypt_target.rs deleted file mode 100644 index 0b82303f8..000000000 --- a/fuzz/fuzz_targets/peer_crypt_target.rs +++ /dev/null @@ -1,109 +0,0 @@ -extern crate lightning; -extern crate secp256k1; - -use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor; - -use secp256k1::key::{PublicKey,SecretKey}; - -#[inline] -fn slice_to_be16(v: &[u8]) -> u16 { - ((v[0] as u16) << 8*1) | - ((v[1] as u16) << 8*0) -} - -#[inline] -pub fn do_test(data: &[u8]) { - let mut read_pos = 0; - macro_rules! get_slice { - ($len: expr) => { - { - let slice_len = $len as usize; - if data.len() < read_pos + slice_len { - return; - } - read_pos += slice_len; - &data[read_pos - slice_len..read_pos] - } - } - } - - let our_network_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, - }; - let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, - }; - - let mut crypter = if get_slice!(1)[0] != 0 { - let their_pubkey = match PublicKey::from_slice(get_slice!(33)) { - Ok(key) => key, - Err(_) => return, - }; - let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key); - crypter.get_act_one(); - match crypter.process_act_two(get_slice!(50), &our_network_key) { - Ok(_) => {}, - Err(_) => return, - } - assert!(crypter.is_ready_for_encryption()); - crypter - } else { - let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key); - match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key) { - Ok(_) => {}, - Err(_) => return, - } - match crypter.process_act_three(get_slice!(66)) { - Ok(_) => {}, - Err(_) => return, - } - assert!(crypter.is_ready_for_encryption()); - crypter - }; - loop { - if get_slice!(1)[0] == 0 { - crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2)))); - } else { - let len = match crypter.decrypt_length_header(get_slice!(16+2)) { - Ok(len) => len, - Err(_) => return, - }; - match crypter.decrypt_message(get_slice!(len as usize + 16)) { - Ok(_) => {}, - Err(_) => return, - } - } - } -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("01").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/router_target.rs b/fuzz/fuzz_targets/router_target.rs deleted file mode 100644 index 25bf38274..000000000 --- a/fuzz/fuzz_targets/router_target.rs +++ /dev/null @@ -1,264 +0,0 @@ -extern crate bitcoin; -extern crate bitcoin_hashes; -extern crate lightning; -extern crate secp256k1; - -use bitcoin_hashes::sha256d::Hash as Sha256dHash; -use bitcoin::blockdata::script::{Script, Builder}; - -use lightning::chain::chaininterface::{ChainError,ChainWatchInterface, ChainListener}; -use lightning::ln::channelmanager::ChannelDetails; -use lightning::ln::msgs; -use lightning::ln::msgs::{RoutingMessageHandler}; -use lightning::ln::router::{Router, RouteHint}; -use lightning::util::logger::Logger; -use lightning::util::ser::Readable; - -use secp256k1::key::PublicKey; - -mod utils; - -use utils::test_logger; - -use std::sync::{Weak, Arc}; -use std::sync::atomic::{AtomicUsize, Ordering}; - -#[inline] -pub fn slice_to_be16(v: &[u8]) -> u16 { - ((v[0] as u16) << 8*1) | - ((v[1] as u16) << 8*0) -} - -#[inline] -pub fn slice_to_be32(v: &[u8]) -> u32 { - ((v[0] as u32) << 8*3) | - ((v[1] as u32) << 8*2) | - ((v[2] as u32) << 8*1) | - ((v[3] as u32) << 8*0) -} - -#[inline] -pub fn slice_to_be64(v: &[u8]) -> u64 { - ((v[0] as u64) << 8*7) | - ((v[1] as u64) << 8*6) | - ((v[2] as u64) << 8*5) | - ((v[3] as u64) << 8*4) | - ((v[4] as u64) << 8*3) | - ((v[5] as u64) << 8*2) | - ((v[6] as u64) << 8*1) | - ((v[7] as u64) << 8*0) -} - - -struct InputData { - data: Vec, - read_pos: AtomicUsize, -} -impl InputData { - fn get_slice(&self, len: usize) -> Option<&[u8]> { - let old_pos = self.read_pos.fetch_add(len, Ordering::AcqRel); - if self.data.len() < old_pos + len { - return None; - } - Some(&self.data[old_pos..old_pos + len]) - } - fn get_slice_nonadvancing(&self, len: usize) -> Option<&[u8]> { - let old_pos = self.read_pos.load(Ordering::Acquire); - if self.data.len() < old_pos + len { - return None; - } - Some(&self.data[old_pos..old_pos + len]) - } -} - -struct DummyChainWatcher { - 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 register_listener(&self, _listener: Weak) { } - - fn get_chain_utxo(&self, _genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> { - 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), - _ => unreachable!(), - } - } -} - -#[inline] -pub fn do_test(data: &[u8]) { - let input = Arc::new(InputData { - data: data.to_vec(), - read_pos: AtomicUsize::new(0), - }); - macro_rules! get_slice_nonadvancing { - ($len: expr) => { - match input.get_slice_nonadvancing($len as usize) { - Some(slice) => slice, - None => return, - } - } - } - macro_rules! get_slice { - ($len: expr) => { - match input.get_slice($len as usize) { - Some(slice) => slice, - None => return, - } - } - } - - macro_rules! decode_msg { - ($MsgType: path, $len: expr) => {{ - let mut reader = ::std::io::Cursor::new(get_slice!($len)); - 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)), - } - } - }} - } - - macro_rules! decode_msg_with_len16 { - ($MsgType: path, $begin_len: expr, $excess: expr) => { - { - let extra_len = slice_to_be16(&get_slice_nonadvancing!($begin_len as usize + 2)[$begin_len..$begin_len + 2]); - decode_msg!($MsgType, $begin_len as usize + 2 + (extra_len as usize) + $excess) - } - } - } - - macro_rules! get_pubkey { - () => { - match PublicKey::from_slice(get_slice!(33)) { - Ok(key) => key, - Err(_) => return, - } - } - } - - let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); - let chain_monitor = Arc::new(DummyChainWatcher { - input: Arc::clone(&input), - }); - - let our_pubkey = get_pubkey!(); - let router = Router::new(our_pubkey.clone(), chain_monitor, Arc::clone(&logger)); - - loop { - match get_slice!(1)[0] { - 0 => { - let start_len = slice_to_be16(&get_slice_nonadvancing!(64 + 2)[64..64 + 2]) as usize; - let addr_len = slice_to_be16(&get_slice_nonadvancing!(64+start_len+2 + 74)[64+start_len+2 + 72..64+start_len+2 + 74]); - if addr_len > (37+1)*4 { - return; - } - let _ = router.handle_node_announcement(&decode_msg_with_len16!(msgs::NodeAnnouncement, 64, 288)); - }, - 1 => { - let _ = router.handle_channel_announcement(&decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4)); - }, - 2 => { - let _ = router.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 128)); - }, - 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, - } - }, - 4 => { - let target = get_pubkey!(); - 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)); - for _ in 0..count { - first_hops_vec.push(ChannelDetails { - channel_id: [0; 32], - short_channel_id: Some(slice_to_be64(get_slice!(8))), - remote_network_id: get_pubkey!(), - channel_value_satoshis: slice_to_be64(get_slice!(8)), - user_id: 0, - inbound_capacity_msat: 0, - is_live: true, - outbound_capacity_msat: 0, - }); - } - Some(&first_hops_vec[..]) - }, - _ => return, - }; - let mut last_hops_vec = Vec::new(); - let last_hops = { - let count = slice_to_be16(get_slice!(2)); - for _ in 0..count { - 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)), - 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))); - }, - _ => return, - } - } -} - -#[cfg(feature = "afl")] -#[macro_use] extern crate afl; -#[cfg(feature = "afl")] -fn main() { - fuzz!(|data| { - do_test(data); - }); -} - -#[cfg(feature = "honggfuzz")] -#[macro_use] extern crate honggfuzz; -#[cfg(feature = "honggfuzz")] -fn main() { - loop { - fuzz!(|data| { - do_test(data); - }); - } -} - -extern crate hex; -#[cfg(test)] -mod tests { - - #[test] - fn duplicate_crash() { - super::do_test(&::hex::decode("00").unwrap()); - } -} diff --git a/fuzz/fuzz_targets/utils/mod.rs b/fuzz/fuzz_targets/utils/mod.rs deleted file mode 100644 index a7d7c32d5..000000000 --- a/fuzz/fuzz_targets/utils/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod test_logger; diff --git a/fuzz/fuzz_targets/utils/test_logger.rs b/fuzz/fuzz_targets/utils/test_logger.rs deleted file mode 100644 index 097d001db..000000000 --- a/fuzz/fuzz_targets/utils/test_logger.rs +++ /dev/null @@ -1,23 +0,0 @@ -use lightning::util::logger::{Logger, Record}; -pub struct TestLogger { - #[cfg(test)] - id: String, -} - -impl TestLogger { - pub fn new(_id: String) -> TestLogger { - TestLogger { - #[cfg(test)] - id: _id - } - } -} - -impl Logger for TestLogger { - fn log(&self, record: &Record) { - #[cfg(test)] - println!("{:<5} {} [{} : {}, {}] {}", record.level.to_string(), self.id, record.module_path, record.file, record.line, record.args); - #[cfg(not(test))] - let _ = format!("{}", record.args); - } -} diff --git a/fuzz/travis-fuzz.sh b/fuzz/travis-fuzz.sh deleted file mode 100755 index e602e9518..000000000 --- a/fuzz/travis-fuzz.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -set -e - -pushd fuzz_targets/msg_targets -rm *_target.rs -./gen_target.sh -[ "$(git diff)" != "" ] && exit 1 -popd - -cargo install --force honggfuzz -for TARGET in fuzz_targets/*.rs fuzz_targets/msg_targets/*_target.rs; do - FILENAME=$(basename $TARGET) - FILE="${FILENAME%.*}" - HFUZZ_RUN_ARGS="--exit_upon_crash -v -n2" - if [ "$FILE" = "chanmon_fail_consistency" ]; then - HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -F 64 -N100000" - else - HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -N1000000" - fi - export HFUZZ_RUN_ARGS - HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" cargo hfuzz run $FILE - if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then - cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT - for CASE in hfuzz_workspace/$FILE/SIG*; do - cat $CASE | xxd -p - done - exit 1 - fi -done diff --git a/lightning-net-tokio/Cargo.toml b/lightning-net-tokio/Cargo.toml new file mode 100644 index 000000000..f6fa03bdf --- /dev/null +++ b/lightning-net-tokio/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "lightning-net-tokio" +version = "0.0.1" +authors = ["Matt Corallo"] +license = "Apache-2.0" +description = """ +Implementation of the rust-lightning network stack using Tokio. +For Rust-Lightning clients which wish to make direct connections to Lightning P2P nodes, this is a simple alternative to implementing the nerequired network stack, especially for those already using Tokio. +""" + +[dependencies] +bitcoin = "0.20" +bitcoin_hashes = "0.7" +lightning = { version = "0.0.9", path = "../lightning" } +secp256k1 = "0.15" +tokio-codec = "0.1" +futures = "0.1" +tokio = "0.1" +bytes = "0.4" diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs new file mode 100644 index 000000000..0bc36b280 --- /dev/null +++ b/lightning-net-tokio/src/lib.rs @@ -0,0 +1,270 @@ +extern crate bytes; +extern crate tokio; +extern crate tokio_codec; +extern crate futures; +extern crate lightning; +extern crate secp256k1; + +use bytes::BufMut; + +use futures::future; +use futures::future::Future; +use futures::{AsyncSink, Stream, Sink}; +use futures::sync::mpsc; + +use secp256k1::key::PublicKey; + +use tokio::timer::Delay; +use tokio::net::TcpStream; + +use lightning::ln::peer_handler; +use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; + +use std::mem; +use std::net::SocketAddr; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::time::{Duration, Instant}; +use std::vec::Vec; +use std::hash::Hash; + +static ID_COUNTER: AtomicU64 = AtomicU64::new(0); + +/// A connection to a remote peer. Can be constructed either as a remote connection using +/// Connection::setup_outbound o +pub struct Connection { + writer: Option>, + event_notify: mpsc::Sender<()>, + pending_read: Vec, + read_blocker: Option>>, + read_paused: bool, + need_disconnect: bool, + id: u64, +} +impl Connection { + fn schedule_read(peer_manager: Arc>, us: Arc>, reader: futures::stream::SplitStream>) { + let us_ref = us.clone(); + let us_close_ref = us.clone(); + let peer_manager_ref = peer_manager.clone(); + tokio::spawn(reader.for_each(move |b| { + let pending_read = b.to_vec(); + { + let mut lock = us_ref.lock().unwrap(); + assert!(lock.pending_read.is_empty()); + if lock.read_paused { + lock.pending_read = pending_read; + let (sender, blocker) = futures::sync::oneshot::channel(); + lock.read_blocker = Some(sender); + return future::Either::A(blocker.then(|_| { Ok(()) })); + } + } + //TODO: There's a race where we don't meet the requirements of disconnect_socket if its + //called right here, after we release the us_ref lock in the scope above, but before we + //call read_event! + match peer_manager.read_event(&mut SocketDescriptor::new(us_ref.clone(), peer_manager.clone()), pending_read) { + Ok(pause_read) => { + if pause_read { + let mut lock = us_ref.lock().unwrap(); + lock.read_paused = true; + } + }, + Err(e) => { + us_ref.lock().unwrap().need_disconnect = false; + return future::Either::B(future::result(Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e)))); + } + } + + if let Err(e) = us_ref.lock().unwrap().event_notify.try_send(()) { + // Ignore full errors as we just need them to poll after this point, so if the user + // hasn't received the last send yet, it doesn't matter. + assert!(e.is_full()); + } + + future::Either::B(future::result(Ok(()))) + }).then(move |_| { + if us_close_ref.lock().unwrap().need_disconnect { + peer_manager_ref.disconnect_event(&SocketDescriptor::new(us_close_ref, peer_manager_ref.clone())); + println!("Peer disconnected!"); + } else { + println!("We disconnected peer!"); + } + Ok(()) + })); + } + + fn new(event_notify: mpsc::Sender<()>, stream: TcpStream) -> (futures::stream::SplitStream>, Arc>) { + let (writer, reader) = tokio_codec::Framed::new(stream, tokio_codec::BytesCodec::new()).split(); + let (send_sink, send_stream) = mpsc::channel(3); + tokio::spawn(writer.send_all(send_stream.map_err(|_| -> std::io::Error { + unreachable!(); + })).then(|_| { + future::result(Ok(())) + })); + let us = Arc::new(Mutex::new(Self { writer: Some(send_sink), event_notify, pending_read: Vec::new(), read_blocker: None, read_paused: false, need_disconnect: true, id: ID_COUNTER.fetch_add(1, Ordering::AcqRel) })); + + (reader, us) + } + + /// Process incoming messages and feed outgoing messages on the provided socket generated by + /// accepting an incoming connection (by scheduling futures with tokio::spawn). + /// + /// You should poll the Receive end of event_notify and call get_and_clear_pending_events() on + /// ChannelManager and ChannelMonitor objects. + pub fn setup_inbound(peer_manager: Arc>, event_notify: mpsc::Sender<()>, stream: TcpStream) { + let (reader, us) = Self::new(event_notify, stream); + + if let Ok(_) = peer_manager.new_inbound_connection(SocketDescriptor::new(us.clone(), peer_manager.clone())) { + Self::schedule_read(peer_manager, us, reader); + } + } + + /// Process incoming messages and feed outgoing messages on the provided socket generated by + /// making an outbound connection which is expected to be accepted by a peer with the given + /// public key (by scheduling futures with tokio::spawn). + /// + /// You should poll the Receive end of event_notify and call get_and_clear_pending_events() on + /// ChannelManager and ChannelMonitor objects. + pub fn setup_outbound(peer_manager: Arc>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: TcpStream) { + let (reader, us) = Self::new(event_notify, stream); + + if let Ok(initial_send) = peer_manager.new_outbound_connection(their_node_id, SocketDescriptor::new(us.clone(), peer_manager.clone())) { + if SocketDescriptor::new(us.clone(), peer_manager.clone()).send_data(&initial_send, true) == initial_send.len() { + Self::schedule_read(peer_manager, us, reader); + } else { + println!("Failed to write first full message to socket!"); + } + } + } + + /// Process incoming messages and feed outgoing messages on a new connection made to the given + /// socket address which is expected to be accepted by a peer with the given public key (by + /// scheduling futures with tokio::spawn). + /// + /// You should poll the Receive end of event_notify and call get_and_clear_pending_events() on + /// ChannelManager and ChannelMonitor objects. + pub fn connect_outbound(peer_manager: Arc>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) { + let connect_timeout = Delay::new(Instant::now() + Duration::from_secs(10)).then(|_| { + future::err(std::io::Error::new(std::io::ErrorKind::TimedOut, "timeout reached")) + }); + tokio::spawn(TcpStream::connect(&addr).select(connect_timeout) + .and_then(move |stream| { + Connection::setup_outbound(peer_manager, event_notify, their_node_id, stream.0); + future::ok(()) + }).or_else(|_| { + //TODO: return errors somehow + future::ok(()) + })); + } +} + +#[derive(Clone)] +pub struct SocketDescriptor { + conn: Arc>, + id: u64, + peer_manager: Arc>, +} +impl SocketDescriptor { + fn new(conn: Arc>, peer_manager: Arc>) -> Self { + let id = conn.lock().unwrap().id; + Self { conn, id, peer_manager } + } +} +impl peer_handler::SocketDescriptor for SocketDescriptor { + fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize { + macro_rules! schedule_read { + ($us_ref: expr) => { + tokio::spawn(future::lazy(move || -> Result<(), ()> { + let mut read_data = Vec::new(); + { + let mut us = $us_ref.conn.lock().unwrap(); + mem::swap(&mut read_data, &mut us.pending_read); + } + if !read_data.is_empty() { + let mut us_clone = $us_ref.clone(); + match $us_ref.peer_manager.read_event(&mut us_clone, read_data) { + Ok(pause_read) => { + if pause_read { return Ok(()); } + }, + Err(_) => { + //TODO: Not actually sure how to do this + return Ok(()); + } + } + } + let mut us = $us_ref.conn.lock().unwrap(); + if let Some(sender) = us.read_blocker.take() { + sender.send(Ok(())).unwrap(); + } + us.read_paused = false; + if let Err(e) = us.event_notify.try_send(()) { + // Ignore full errors as we just need them to poll after this point, so if the user + // hasn't received the last send yet, it doesn't matter. + assert!(e.is_full()); + } + Ok(()) + })); + } + } + + let mut us = self.conn.lock().unwrap(); + if resume_read { + let us_ref = self.clone(); + schedule_read!(us_ref); + } + if data.is_empty() { return 0; } + if us.writer.is_none() { + us.read_paused = true; + return 0; + } + + let mut bytes = bytes::BytesMut::with_capacity(data.len()); + bytes.put(data); + let write_res = us.writer.as_mut().unwrap().start_send(bytes.freeze()); + match write_res { + Ok(res) => { + match res { + AsyncSink::Ready => { + data.len() + }, + AsyncSink::NotReady(_) => { + us.read_paused = true; + let us_ref = self.clone(); + tokio::spawn(us.writer.take().unwrap().flush().then(move |writer_res| -> Result<(), ()> { + if let Ok(writer) = writer_res { + { + let mut us = us_ref.conn.lock().unwrap(); + us.writer = Some(writer); + } + schedule_read!(us_ref); + } // we'll fire the disconnect event on the socket reader end + Ok(()) + })); + 0 + } + } + }, + Err(_) => { + // We'll fire the disconnected event on the socket reader end + 0 + }, + } + } + + fn disconnect_socket(&mut self) { + let mut us = self.conn.lock().unwrap(); + us.need_disconnect = true; + us.read_paused = true; + } +} +impl Eq for SocketDescriptor {} +impl PartialEq for SocketDescriptor { + fn eq(&self, o: &Self) -> bool { + self.id == o.id + } +} +impl Hash for SocketDescriptor { + fn hash(&self, state: &mut H) { + self.id.hash(state); + } +} + diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml new file mode 100644 index 000000000..004e6d25b --- /dev/null +++ b/lightning/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "lightning" +version = "0.0.9" +authors = ["Matt Corallo"] +license = "Apache-2.0" +repository = "https://github.com/rust-bitcoin/rust-lightning/" +description = """ +A Bitcoin Lightning library in Rust. +Does most of the hard work, without implying a specific runtime, requiring clients implement basic network logic, chain interactions and disk storage. +Still missing tons of error-handling. See GitHub issues for suggested projects if you want to contribute. Don't have to bother telling you not to use this for anything serious, because you'd have to build a client around it to even try. +""" + +[features] +# Supports tracking channels with a non-bitcoin chain hashes. Currently enables all kinds of fun DoS attacks. +non_bitcoin_chain_hash_routing = [] +fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget", "bitcoin_hashes/fuzztarget"] +# Unlog messages superior at targeted level. +max_level_off = [] +max_level_error = [] +max_level_warn = [] +max_level_info = [] +max_level_debug = [] + +[dependencies] +bitcoin = "0.20" +bitcoin_hashes = "0.7" +secp256k1 = "0.15" + +[dev-dependencies.bitcoin] +version = "0.20" +features = ["bitcoinconsensus"] + +[dev-dependencies] +hex = "0.3" +rand = "0.4" + +[profile.dev] +opt-level = 1 diff --git a/lightning/fuzz/.gitignore b/lightning/fuzz/.gitignore new file mode 100644 index 000000000..8bf27ec5d --- /dev/null +++ b/lightning/fuzz/.gitignore @@ -0,0 +1,3 @@ +hfuzz_target +target +hfuzz_workspace diff --git a/lightning/fuzz/Cargo.toml b/lightning/fuzz/Cargo.toml new file mode 100644 index 000000000..19d832e87 --- /dev/null +++ b/lightning/fuzz/Cargo.toml @@ -0,0 +1,158 @@ +[package] +name = "lightning-fuzz" +version = "0.0.1" +authors = ["Automatically generated"] +publish = false +# Because the function is unused it gets dropped before we link lightning, so +# we have to duplicate build.rs here. Note that this is only required for +# fuzztarget mode. + +[package.metadata] +cargo-fuzz = true + +[features] +afl_fuzz = ["afl"] +honggfuzz_fuzz = ["honggfuzz"] +libfuzzer_fuzz = ["libfuzzer-sys"] + +[dependencies] +afl = { version = "0.4", optional = true } +lightning = { path = "..", features = ["fuzztarget"] } +bitcoin = { version = "0.20", features = ["fuzztarget"] } +bitcoin_hashes = { version = "0.7", features = ["fuzztarget"] } +hex = "0.3" +honggfuzz = { version = "0.5", optional = true } +secp256k1 = { version = "0.15", features=["fuzztarget"] } +libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git", optional = true } + +[build-dependencies] +cc = "1.0" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +lto = true +codegen-units = 1 + +[[bin]] +name = "peer_crypt_target" +path = "fuzz_targets/peer_crypt_target.rs" + +[[bin]] +name = "full_stack_target" +path = "fuzz_targets/full_stack_target.rs" + +[[bin]] +name = "chanmon_fail_consistency" +path = "fuzz_targets/chanmon_fail_consistency.rs" + +[[bin]] +name = "router_target" +path = "fuzz_targets/router_target.rs" + +[[bin]] +name = "chanmon_deser_target" +path = "fuzz_targets/chanmon_deser_target.rs" + +# message fuzz targets +[[bin]] +name = "msg_ping_target" +path = "fuzz_targets/msg_targets/msg_ping_target.rs" + +[[bin]] +name = "msg_pong_target" +path = "fuzz_targets/msg_targets/msg_pong_target.rs" + +[[bin]] +name = "msg_error_message_target" +path = "fuzz_targets/msg_targets/msg_error_message_target.rs" + +[[bin]] +name = "msg_update_add_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_add_htlc_target.rs" + +[[bin]] +name = "msg_accept_channel_target" +path = "fuzz_targets/msg_targets/msg_accept_channel_target.rs" + +[[bin]] +name = "msg_closing_signed_target" +path = "fuzz_targets/msg_targets/msg_closing_signed_target.rs" + +[[bin]] +name = "msg_commitment_signed_target" +path = "fuzz_targets/msg_targets/msg_commitment_signed_target.rs" + +[[bin]] +name = "msg_funding_created_target" +path = "fuzz_targets/msg_targets/msg_funding_created_target.rs" + +[[bin]] +name = "msg_funding_locked_target" +path = "fuzz_targets/msg_targets/msg_funding_locked_target.rs" + +[[bin]] +name = "msg_funding_signed_target" +path = "fuzz_targets/msg_targets/msg_funding_signed_target.rs" + +[[bin]] +name = "msg_open_channel_target" +path = "fuzz_targets/msg_targets/msg_open_channel_target.rs" + +[[bin]] +name = "msg_revoke_and_ack_target" +path = "fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs" + +[[bin]] +name = "msg_shutdown_target" +path = "fuzz_targets/msg_targets/msg_shutdown_target.rs" + +[[bin]] +name = "msg_update_fail_malformed_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs" + +[[bin]] +name = "msg_update_fee_target" +path = "fuzz_targets/msg_targets/msg_update_fee_target.rs" + +[[bin]] +name = "msg_update_fulfill_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs" + +[[bin]] +name = "msg_update_fail_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs" + +[[bin]] +name = "msg_channel_reestablish_target" +path = "fuzz_targets/msg_targets/msg_channel_reestablish_target.rs" + +[[bin]] +name = "msg_announcement_signatures_target" +path = "fuzz_targets/msg_targets/msg_announcement_signatures_target.rs" + +[[bin]] +name = "msg_channel_announcement_target" +path = "fuzz_targets/msg_targets/msg_channel_announcement_target.rs" + +[[bin]] +name = "msg_channel_update_target" +path = "fuzz_targets/msg_targets/msg_channel_update_target.rs" + +[[bin]] +name = "msg_decoded_onion_error_packet_target" +path = "fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs" + +[[bin]] +name = "msg_init_target" +path = "fuzz_targets/msg_targets/msg_init_target.rs" + +[[bin]] +name = "msg_node_announcement_target" +path = "fuzz_targets/msg_targets/msg_node_announcement_target.rs" + +[[bin]] +name = "msg_onion_hop_data_target" +path = "fuzz_targets/msg_targets/msg_onion_hop_data_target.rs" diff --git a/lightning/fuzz/fuzz_targets/chanmon_deser_target.rs b/lightning/fuzz/fuzz_targets/chanmon_deser_target.rs new file mode 100644 index 000000000..f74183258 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/chanmon_deser_target.rs @@ -0,0 +1,72 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate bitcoin; +extern crate bitcoin_hashes; +extern crate lightning; + +use bitcoin_hashes::sha256d::Hash as Sha256dHash; + +use lightning::ln::channelmonitor; +use lightning::util::ser::{ReadableArgs, Writer}; + +mod utils; +use utils::test_logger; + +use std::io::Cursor; +use std::sync::Arc; + +struct VecWriter(Vec); +impl Writer for VecWriter { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + self.0.extend_from_slice(buf); + Ok(()) + } + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); + } +} + +#[inline] +pub fn do_test(data: &[u8]) { + let logger = Arc::new(test_logger::TestLogger::new("".to_owned())); + if let Ok((latest_block_hash, monitor)) = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(data), logger.clone()) { + let mut w = VecWriter(Vec::new()); + monitor.write_for_disk(&mut w).unwrap(); + let deserialized_copy = <(Sha256dHash, channelmonitor::ChannelMonitor)>::read(&mut Cursor::new(&w.0), logger.clone()).unwrap(); + assert!(latest_block_hash == deserialized_copy.0); + assert!(monitor == deserialized_copy.1); + w.0.clear(); + monitor.write_for_watchtower(&mut w).unwrap(); + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/chanmon_fail_consistency.rs b/lightning/fuzz/fuzz_targets/chanmon_fail_consistency.rs new file mode 100644 index 000000000..3610b1ca6 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/chanmon_fail_consistency.rs @@ -0,0 +1,783 @@ +//! Test that monitor update failures don't get our channel state out of sync. +//! One of the biggest concern with the monitor update failure handling code is that messages +//! resent after monitor updating is restored are delivered out-of-order, resulting in +//! commitment_signed messages having "invalid signatures". +//! To test this we stand up a network of three nodes and read bytes from the fuzz input to denote +//! actions such as sending payments, handling events, or changing monitor update return values on +//! a per-node basis. This should allow it to find any cases where the ordering of actions results +//! in us getting out of sync with ourselves, and, assuming at least one of our recieve- or +//! send-side handling is correct, other peers. We consider it a failure if any action results in a +//! channel being force-closed. + +//Uncomment this for libfuzzer builds: +//#![no_main] + +extern crate bitcoin; +extern crate bitcoin_hashes; +extern crate lightning; +extern crate secp256k1; + +use bitcoin::BitcoinHash; +use bitcoin::blockdata::block::BlockHeader; +use bitcoin::blockdata::transaction::{Transaction, TxOut}; +use bitcoin::blockdata::script::{Builder, Script}; +use bitcoin::blockdata::opcodes; +use bitcoin::network::constants::Network; + +use bitcoin_hashes::Hash as TraitImport; +use bitcoin_hashes::hash160::Hash as Hash160; +use bitcoin_hashes::sha256::Hash as Sha256; +use bitcoin_hashes::sha256d::Hash as Sha256d; + +use lightning::chain::chaininterface; +use lightning::chain::transaction::OutPoint; +use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; +use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; +use lightning::ln::channelmonitor; +use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate}; +use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs}; +use lightning::ln::router::{Route, RouteHop}; +use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, HandleError, UpdateAddHTLC, LocalFeatures}; +use lightning::util::events; +use lightning::util::logger::Logger; +use lightning::util::config::UserConfig; +use lightning::util::events::{EventsProvider, MessageSendEventsProvider}; +use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer}; + +mod utils; +use utils::test_logger; + +use secp256k1::key::{PublicKey,SecretKey}; +use secp256k1::Secp256k1; + +use std::mem; +use std::cmp::Ordering; +use std::collections::{HashSet, hash_map, HashMap}; +use std::sync::{Arc,Mutex}; +use std::sync::atomic; +use std::io::Cursor; + +struct FuzzEstimator {} +impl FeeEstimator for FuzzEstimator { + fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u64 { + 253 + } +} + +pub struct TestBroadcaster {} +impl BroadcasterInterface for TestBroadcaster { + fn broadcast_transaction(&self, _tx: &Transaction) { } +} + +pub struct VecWriter(pub Vec); +impl Writer for VecWriter { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + self.0.extend_from_slice(buf); + Ok(()) + } + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); + } +} + +static mut IN_RESTORE: bool = false; +pub struct TestChannelMonitor { + pub simple_monitor: Arc>, + pub update_ret: Mutex>, + pub latest_good_update: Mutex>>, + pub latest_update_good: Mutex>, + pub latest_updates_good_at_last_ser: Mutex>, + pub should_update_manager: atomic::AtomicBool, +} +impl TestChannelMonitor { + pub fn new(chain_monitor: Arc, broadcaster: Arc, logger: Arc, feeest: Arc) -> Self { + Self { + simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest), + update_ret: Mutex::new(Ok(())), + latest_good_update: Mutex::new(HashMap::new()), + latest_update_good: Mutex::new(HashMap::new()), + latest_updates_good_at_last_ser: Mutex::new(HashMap::new()), + should_update_manager: atomic::AtomicBool::new(false), + } + } +} +impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { + fn add_update_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { + let ret = self.update_ret.lock().unwrap().clone(); + if let Ok(()) = ret { + let mut ser = VecWriter(Vec::new()); + monitor.write_for_disk(&mut ser).unwrap(); + self.latest_good_update.lock().unwrap().insert(funding_txo, ser.0); + match self.latest_update_good.lock().unwrap().entry(funding_txo) { + hash_map::Entry::Vacant(mut e) => { e.insert(true); }, + hash_map::Entry::Occupied(mut e) => { + if !e.get() && unsafe { IN_RESTORE } { + // Technically we can't consider an update to be "good" unless we're doing + // it in response to a test_restore_channel_monitor as the channel may + // still be waiting on such a call, so only set us to good if we're in the + // middle of a restore call. + e.insert(true); + } + }, + } + self.should_update_manager.store(true, atomic::Ordering::Relaxed); + } else { + self.latest_update_good.lock().unwrap().insert(funding_txo, false); + } + assert!(self.simple_monitor.add_update_monitor(funding_txo, monitor).is_ok()); + ret + } + + fn fetch_pending_htlc_updated(&self) -> Vec { + return self.simple_monitor.fetch_pending_htlc_updated(); + } +} + +struct KeyProvider { + node_id: u8, + session_id: atomic::AtomicU8, + channel_id: atomic::AtomicU8, +} +impl KeysInterface for KeyProvider { + fn get_node_secret(&self) -> SecretKey { + SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id]).unwrap() + } + + fn get_destination_script(&self) -> Script { + let secp_ctx = Secp256k1::signing_only(); + let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_id]).unwrap(); + let our_channel_monitor_claim_key_hash = Hash160::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); + Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() + } + + fn get_shutdown_pubkey(&self) -> PublicKey { + let secp_ctx = Secp256k1::signing_only(); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap()) + } + + fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { + ChannelKeys { + funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, self.node_id]).unwrap(), + revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, self.node_id]).unwrap(), + payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, self.node_id]).unwrap(), + delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(), + htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(), + commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id], + } + } + + fn get_session_key(&self) -> SecretKey { + let id = self.session_id.fetch_add(1, atomic::Ordering::Relaxed); + SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 10, self.node_id]).unwrap() + } + + fn get_channel_id(&self) -> [u8; 32] { + let id = self.channel_id.fetch_add(1, atomic::Ordering::Relaxed); + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, id, 11, self.node_id] + } +} + +#[inline] +pub fn do_test(data: &[u8]) { + let fee_est = Arc::new(FuzzEstimator{}); + let broadcast = Arc::new(TestBroadcaster{}); + + macro_rules! make_node { + ($node_id: expr) => { { + let logger: Arc = Arc::new(test_logger::TestLogger::new($node_id.to_string())); + let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); + let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone())); + + let keys_manager = Arc::new(KeyProvider { node_id: $node_id, session_id: atomic::AtomicU8::new(0), channel_id: atomic::AtomicU8::new(0) }); + let mut config = UserConfig::new(); + config.channel_options.fee_proportional_millionths = 0; + config.channel_options.announced_channel = true; + config.peer_channel_config_limits.min_dust_limit_satoshis = 0; + (ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap(), + monitor) + } } + } + + macro_rules! reload_node { + ($ser: expr, $node_id: expr, $old_monitors: expr) => { { + let logger: Arc = Arc::new(test_logger::TestLogger::new($node_id.to_string())); + let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); + let monitor = Arc::new(TestChannelMonitor::new(watch.clone(), broadcast.clone(), logger.clone(), fee_est.clone())); + + let keys_manager = Arc::new(KeyProvider { node_id: $node_id, session_id: atomic::AtomicU8::new(0), channel_id: atomic::AtomicU8::new(0) }); + let mut config = UserConfig::new(); + config.channel_options.fee_proportional_millionths = 0; + config.channel_options.announced_channel = true; + config.peer_channel_config_limits.min_dust_limit_satoshis = 0; + + let mut monitors = HashMap::new(); + let mut old_monitors = $old_monitors.latest_good_update.lock().unwrap(); + for (outpoint, monitor_ser) in old_monitors.drain() { + monitors.insert(outpoint, <(Sha256d, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), Arc::clone(&logger)).expect("Failed to read monitor").1); + monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser); + } + let mut monitor_refs = HashMap::new(); + for (outpoint, monitor) in monitors.iter() { + monitor_refs.insert(*outpoint, monitor); + } + + let read_args = ChannelManagerReadArgs { + keys_manager, + fee_estimator: fee_est.clone(), + monitor: monitor.clone(), + chain_monitor: watch, + tx_broadcaster: broadcast.clone(), + logger, + default_config: config, + channel_monitors: &monitor_refs, + }; + + let res = (<(Sha256d, ChannelManager)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor); + for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() { + if !was_good { + // If the last time we updated a monitor we didn't successfully update (and we + // have sense updated our serialized copy of the ChannelManager) we may + // force-close the channel on our counterparty cause we know we're missing + // something. Thus, we just return here since we can't continue to test. + return; + } + } + res + } } + } + + + let mut channel_txn = Vec::new(); + macro_rules! make_channel { + ($source: expr, $dest: expr, $chan_id: expr) => { { + $source.create_channel($dest.get_our_node_id(), 10000000, 42, 0).unwrap(); + let open_channel = { + let events = $source.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + if let events::MessageSendEvent::SendOpenChannel { ref msg, .. } = events[0] { + msg.clone() + } else { panic!("Wrong event type"); } + }; + + $dest.handle_open_channel(&$source.get_our_node_id(), LocalFeatures::new(), &open_channel).unwrap(); + let accept_channel = { + let events = $dest.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + if let events::MessageSendEvent::SendAcceptChannel { ref msg, .. } = events[0] { + msg.clone() + } else { panic!("Wrong event type"); } + }; + + $source.handle_accept_channel(&$dest.get_our_node_id(), LocalFeatures::new(), &accept_channel).unwrap(); + { + let events = $source.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + if let events::Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, .. } = events[0] { + let tx = Transaction { version: $chan_id, lock_time: 0, input: Vec::new(), output: vec![TxOut { + value: *channel_value_satoshis, script_pubkey: output_script.clone(), + }]}; + let funding_output = OutPoint::new(tx.txid(), 0); + $source.funding_transaction_generated(&temporary_channel_id, funding_output); + channel_txn.push(tx); + } else { panic!("Wrong event type"); } + } + + let funding_created = { + let events = $source.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + if let events::MessageSendEvent::SendFundingCreated { ref msg, .. } = events[0] { + msg.clone() + } else { panic!("Wrong event type"); } + }; + $dest.handle_funding_created(&$source.get_our_node_id(), &funding_created).unwrap(); + + let funding_signed = { + let events = $dest.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + if let events::MessageSendEvent::SendFundingSigned { ref msg, .. } = events[0] { + msg.clone() + } else { panic!("Wrong event type"); } + }; + $source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed).unwrap(); + + { + let events = $source.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + if let events::Event::FundingBroadcastSafe { .. } = events[0] { + } else { panic!("Wrong event type"); } + } + } } + } + + macro_rules! confirm_txn { + ($node: expr) => { { + let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + let mut txn = Vec::with_capacity(channel_txn.len()); + let mut posn = Vec::with_capacity(channel_txn.len()); + for i in 0..channel_txn.len() { + txn.push(&channel_txn[i]); + posn.push(i as u32 + 1); + } + $node.block_connected(&header, 1, &txn, &posn); + for i in 2..100 { + header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + $node.block_connected(&header, i, &Vec::new(), &[0; 0]); + } + } } + } + + macro_rules! lock_fundings { + ($nodes: expr) => { { + let mut node_events = Vec::new(); + for node in $nodes.iter() { + node_events.push(node.get_and_clear_pending_msg_events()); + } + for (idx, node_event) in node_events.iter().enumerate() { + for event in node_event { + if let events::MessageSendEvent::SendFundingLocked { ref node_id, ref msg } = event { + for node in $nodes.iter() { + if node.get_our_node_id() == *node_id { + node.handle_funding_locked(&$nodes[idx].get_our_node_id(), msg).unwrap(); + } + } + } else { panic!("Wrong event type"); } + } + } + + for node in $nodes.iter() { + let events = node.get_and_clear_pending_msg_events(); + for event in events { + if let events::MessageSendEvent::SendAnnouncementSignatures { .. } = event { + } else { panic!("Wrong event type"); } + } + } + } } + } + + // 3 nodes is enough to hit all the possible cases, notably unknown-source-unknown-dest + // forwarding. + let (mut node_a, mut monitor_a) = make_node!(0); + let (mut node_b, mut monitor_b) = make_node!(1); + let (mut node_c, mut monitor_c) = make_node!(2); + + let mut nodes = [node_a, node_b, node_c]; + + make_channel!(nodes[0], nodes[1], 0); + make_channel!(nodes[1], nodes[2], 1); + + for node in nodes.iter() { + confirm_txn!(node); + } + + lock_fundings!(nodes); + + let chan_a = nodes[0].list_usable_channels()[0].short_channel_id.unwrap(); + let chan_b = nodes[2].list_usable_channels()[0].short_channel_id.unwrap(); + + let mut payment_id = 0; + + let mut chan_a_disconnected = false; + let mut chan_b_disconnected = false; + let mut ba_events = Vec::new(); + let mut bc_events = Vec::new(); + + let mut node_a_ser = VecWriter(Vec::new()); + nodes[0].write(&mut node_a_ser).unwrap(); + let mut node_b_ser = VecWriter(Vec::new()); + nodes[1].write(&mut node_b_ser).unwrap(); + let mut node_c_ser = VecWriter(Vec::new()); + nodes[2].write(&mut node_c_ser).unwrap(); + + macro_rules! test_err { + ($res: expr) => { + match $res { + Ok(()) => {}, + Err(HandleError { action: Some(ErrorAction::IgnoreError), .. }) => { }, + _ => { $res.unwrap() }, + } + } + } + + macro_rules! test_return { + () => { { + assert_eq!(nodes[0].list_channels().len(), 1); + assert_eq!(nodes[1].list_channels().len(), 2); + assert_eq!(nodes[2].list_channels().len(), 1); + return; + } } + } + + let mut read_pos = 0; + macro_rules! get_slice { + ($len: expr) => { + { + let slice_len = $len as usize; + if data.len() < read_pos + slice_len { + test_return!(); + } + read_pos += slice_len; + &data[read_pos - slice_len..read_pos] + } + } + } + + loop { + macro_rules! send_payment { + ($source: expr, $dest: expr) => { { + let payment_hash = Sha256::hash(&[payment_id; 1]); + payment_id = payment_id.wrapping_add(1); + if let Err(_) = $source.send_payment(Route { + hops: vec![RouteHop { + pubkey: $dest.0.get_our_node_id(), + short_channel_id: $dest.1, + fee_msat: 5000000, + cltv_expiry_delta: 200, + }], + }, PaymentHash(payment_hash.into_inner())) { + // Probably ran out of funds + test_return!(); + } + } }; + ($source: expr, $middle: expr, $dest: expr) => { { + let payment_hash = Sha256::hash(&[payment_id; 1]); + payment_id = payment_id.wrapping_add(1); + if let Err(_) = $source.send_payment(Route { + hops: vec![RouteHop { + pubkey: $middle.0.get_our_node_id(), + short_channel_id: $middle.1, + fee_msat: 50000, + cltv_expiry_delta: 100, + },RouteHop { + pubkey: $dest.0.get_our_node_id(), + short_channel_id: $dest.1, + fee_msat: 5000000, + cltv_expiry_delta: 200, + }], + }, PaymentHash(payment_hash.into_inner())) { + // Probably ran out of funds + test_return!(); + } + } } + } + + macro_rules! process_msg_events { + ($node: expr, $corrupt_forward: expr) => { { + let events = if $node == 1 { + let mut new_events = Vec::new(); + mem::swap(&mut new_events, &mut ba_events); + new_events.extend_from_slice(&bc_events[..]); + bc_events.clear(); + new_events + } else { Vec::new() }; + for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) { + match event { + events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + for dest in nodes.iter() { + if dest.get_our_node_id() == *node_id { + assert!(update_fee.is_none()); + for update_add in update_add_htlcs { + if !$corrupt_forward { + test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &update_add)); + } else { + // Corrupt the update_add_htlc message so that its HMAC + // check will fail and we generate a + // update_fail_malformed_htlc instead of an + // update_fail_htlc as we do when we reject a payment. + let mut msg_ser = update_add.encode(); + msg_ser[1000] ^= 0xff; + let new_msg = UpdateAddHTLC::read(&mut Cursor::new(&msg_ser)).unwrap(); + test_err!(dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &new_msg)); + } + } + for update_fulfill in update_fulfill_htlcs { + test_err!(dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), &update_fulfill)); + } + for update_fail in update_fail_htlcs { + test_err!(dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), &update_fail)); + } + for update_fail_malformed in update_fail_malformed_htlcs { + test_err!(dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), &update_fail_malformed)); + } + test_err!(dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed)); + } + } + }, + events::MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + for dest in nodes.iter() { + if dest.get_our_node_id() == *node_id { + test_err!(dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg)); + } + } + }, + events::MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => { + for dest in nodes.iter() { + if dest.get_our_node_id() == *node_id { + test_err!(dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg)); + } + } + }, + events::MessageSendEvent::SendFundingLocked { .. } => { + // Can be generated as a reestablish response + }, + events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => { + // Can be generated due to a payment forward being rejected due to a + // channel having previously failed a monitor update + }, + _ => panic!("Unhandled message event"), + } + } + } } + } + + macro_rules! drain_msg_events_on_disconnect { + ($counterparty_id: expr) => { { + if $counterparty_id == 0 { + for event in nodes[0].get_and_clear_pending_msg_events() { + match event { + events::MessageSendEvent::UpdateHTLCs { .. } => {}, + events::MessageSendEvent::SendRevokeAndACK { .. } => {}, + events::MessageSendEvent::SendChannelReestablish { .. } => {}, + events::MessageSendEvent::SendFundingLocked { .. } => {}, + events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, + _ => panic!("Unhandled message event"), + } + } + ba_events.clear(); + } else { + for event in nodes[2].get_and_clear_pending_msg_events() { + match event { + events::MessageSendEvent::UpdateHTLCs { .. } => {}, + events::MessageSendEvent::SendRevokeAndACK { .. } => {}, + events::MessageSendEvent::SendChannelReestablish { .. } => {}, + events::MessageSendEvent::SendFundingLocked { .. } => {}, + events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {}, + _ => panic!("Unhandled message event"), + } + } + bc_events.clear(); + } + let mut events = nodes[1].get_and_clear_pending_msg_events(); + let drop_node_id = if $counterparty_id == 0 { nodes[0].get_our_node_id() } else { nodes[2].get_our_node_id() }; + let msg_sink = if $counterparty_id == 0 { &mut bc_events } else { &mut ba_events }; + for event in events.drain(..) { + let push = match event { + events::MessageSendEvent::UpdateHTLCs { ref node_id, .. } => { + if *node_id != drop_node_id { true } else { false } + }, + events::MessageSendEvent::SendRevokeAndACK { ref node_id, .. } => { + if *node_id != drop_node_id { true } else { false } + }, + events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => { + if *node_id != drop_node_id { true } else { false } + }, + events::MessageSendEvent::SendFundingLocked { .. } => false, + events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => false, + _ => panic!("Unhandled message event"), + }; + if push { msg_sink.push(event); } + } + } } + } + + macro_rules! process_events { + ($node: expr, $fail: expr) => { { + // In case we get 256 payments we may have a hash collision, resulting in the + // second claim/fail call not finding the duplicate-hash HTLC, so we have to + // deduplicate the calls here. + let mut claim_set = HashSet::new(); + let mut events = nodes[$node].get_and_clear_pending_events(); + // Sort events so that PendingHTLCsForwardable get processed last. This avoids a + // case where we first process a PendingHTLCsForwardable, then claim/fail on a + // PaymentReceived, claiming/failing two HTLCs, but leaving a just-generated + // PaymentReceived event for the second HTLC in our pending_events (and breaking + // our claim_set deduplication). + events.sort_by(|a, b| { + if let events::Event::PaymentReceived { .. } = a { + if let events::Event::PendingHTLCsForwardable { .. } = b { + Ordering::Less + } else { Ordering::Equal } + } else if let events::Event::PendingHTLCsForwardable { .. } = a { + if let events::Event::PaymentReceived { .. } = b { + Ordering::Greater + } else { Ordering::Equal } + } else { Ordering::Equal } + }); + for event in events.drain(..) { + match event { + events::Event::PaymentReceived { payment_hash, .. } => { + if claim_set.insert(payment_hash.0) { + if $fail { + assert!(nodes[$node].fail_htlc_backwards(&payment_hash)); + } else { + assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0))); + } + } + }, + events::Event::PaymentSent { .. } => {}, + events::Event::PaymentFailed { .. } => {}, + events::Event::PendingHTLCsForwardable { .. } => { + nodes[$node].process_pending_htlc_forwards(); + }, + _ => panic!("Unhandled event"), + } + } + } } + } + + match get_slice!(1)[0] { + 0x00 => *monitor_a.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), + 0x01 => *monitor_b.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), + 0x02 => *monitor_c.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), + 0x03 => *monitor_a.update_ret.lock().unwrap() = Ok(()), + 0x04 => *monitor_b.update_ret.lock().unwrap() = Ok(()), + 0x05 => *monitor_c.update_ret.lock().unwrap() = Ok(()), + 0x06 => { unsafe { IN_RESTORE = true }; nodes[0].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, + 0x07 => { unsafe { IN_RESTORE = true }; nodes[1].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, + 0x08 => { unsafe { IN_RESTORE = true }; nodes[2].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, + 0x09 => send_payment!(nodes[0], (&nodes[1], chan_a)), + 0x0a => send_payment!(nodes[1], (&nodes[0], chan_a)), + 0x0b => send_payment!(nodes[1], (&nodes[2], chan_b)), + 0x0c => send_payment!(nodes[2], (&nodes[1], chan_b)), + 0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)), + 0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)), + 0x0f => { + if !chan_a_disconnected { + nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); + nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); + chan_a_disconnected = true; + drain_msg_events_on_disconnect!(0); + } + }, + 0x10 => { + if !chan_b_disconnected { + nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); + nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false); + chan_b_disconnected = true; + drain_msg_events_on_disconnect!(2); + } + }, + 0x11 => { + if chan_a_disconnected { + nodes[0].peer_connected(&nodes[1].get_our_node_id()); + nodes[1].peer_connected(&nodes[0].get_our_node_id()); + chan_a_disconnected = false; + } + }, + 0x12 => { + if chan_b_disconnected { + nodes[1].peer_connected(&nodes[2].get_our_node_id()); + nodes[2].peer_connected(&nodes[1].get_our_node_id()); + chan_b_disconnected = false; + } + }, + 0x13 => process_msg_events!(0, true), + 0x14 => process_msg_events!(0, false), + 0x15 => process_events!(0, true), + 0x16 => process_events!(0, false), + 0x17 => process_msg_events!(1, true), + 0x18 => process_msg_events!(1, false), + 0x19 => process_events!(1, true), + 0x1a => process_events!(1, false), + 0x1b => process_msg_events!(2, true), + 0x1c => process_msg_events!(2, false), + 0x1d => process_events!(2, true), + 0x1e => process_events!(2, false), + 0x1f => { + if !chan_a_disconnected { + nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); + chan_a_disconnected = true; + drain_msg_events_on_disconnect!(0); + } + let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a); + node_a = Arc::new(new_node_a); + nodes[0] = node_a.clone(); + monitor_a = new_monitor_a; + }, + 0x20 => { + if !chan_a_disconnected { + nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); + chan_a_disconnected = true; + nodes[0].get_and_clear_pending_msg_events(); + ba_events.clear(); + } + if !chan_b_disconnected { + nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false); + chan_b_disconnected = true; + nodes[2].get_and_clear_pending_msg_events(); + bc_events.clear(); + } + let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b); + node_b = Arc::new(new_node_b); + nodes[1] = node_b.clone(); + monitor_b = new_monitor_b; + }, + 0x21 => { + if !chan_b_disconnected { + nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); + chan_b_disconnected = true; + drain_msg_events_on_disconnect!(2); + } + let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c); + node_c = Arc::new(new_node_c); + nodes[2] = node_c.clone(); + monitor_c = new_monitor_c; + }, + _ => test_return!(), + } + + if monitor_a.should_update_manager.load(atomic::Ordering::Relaxed) { + node_a_ser.0.clear(); + nodes[0].write(&mut node_a_ser).unwrap(); + monitor_a.should_update_manager.store(false, atomic::Ordering::Relaxed); + *monitor_a.latest_updates_good_at_last_ser.lock().unwrap() = monitor_a.latest_update_good.lock().unwrap().clone(); + } + if monitor_b.should_update_manager.load(atomic::Ordering::Relaxed) { + node_b_ser.0.clear(); + nodes[1].write(&mut node_b_ser).unwrap(); + monitor_b.should_update_manager.store(false, atomic::Ordering::Relaxed); + *monitor_b.latest_updates_good_at_last_ser.lock().unwrap() = monitor_b.latest_update_good.lock().unwrap().clone(); + } + if monitor_c.should_update_manager.load(atomic::Ordering::Relaxed) { + node_c_ser.0.clear(); + nodes[2].write(&mut node_c_ser).unwrap(); + monitor_c.should_update_manager.store(false, atomic::Ordering::Relaxed); + *monitor_c.latest_updates_good_at_last_ser.lock().unwrap() = monitor_c.latest_update_good.lock().unwrap().clone(); + } + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(feature = "libfuzzer_fuzz")] +#[macro_use] extern crate libfuzzer_sys; +#[cfg(feature = "libfuzzer_fuzz")] +fuzz_target!(|data: &[u8]| { + do_test(data); +}); + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/full_stack_target.rs b/lightning/fuzz/fuzz_targets/full_stack_target.rs new file mode 100644 index 000000000..6145d003b --- /dev/null +++ b/lightning/fuzz/fuzz_targets/full_stack_target.rs @@ -0,0 +1,890 @@ +//! Test that no series of bytes received over the wire/connections created/payments sent can +//! result in a crash. We do this by standing up a node and then reading bytes from input to denote +//! actions such as creating new inbound/outbound connections, bytes to be read from a connection, +//! or payments to send/ways to handle events generated. +//! This test has been very useful, though due to its complexity good starting inputs are critical. + +//Uncomment this for libfuzzer builds: +//#![no_main] + +extern crate bitcoin; +extern crate bitcoin_hashes; +extern crate lightning; +extern crate secp256k1; + +use bitcoin::blockdata::block::BlockHeader; +use bitcoin::blockdata::transaction::{Transaction, TxOut}; +use bitcoin::blockdata::script::{Builder, Script}; +use bitcoin::blockdata::opcodes; +use bitcoin::consensus::encode::deserialize; +use bitcoin::network::constants::Network; +use bitcoin::util::hash::BitcoinHash; + +use bitcoin_hashes::Hash as TraitImport; +use bitcoin_hashes::HashEngine as TraitImportEngine; +use bitcoin_hashes::sha256::Hash as Sha256; +use bitcoin_hashes::hash160::Hash as Hash160; +use bitcoin_hashes::sha256d::Hash as Sha256dHash; + +use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; +use lightning::chain::transaction::OutPoint; +use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; +use lightning::ln::channelmonitor; +use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage}; +use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; +use lightning::ln::router::Router; +use lightning::util::events::{EventsProvider,Event}; +use lightning::util::logger::Logger; +use lightning::util::config::UserConfig; + +mod utils; + +use utils::test_logger; + +use secp256k1::key::{PublicKey,SecretKey}; +use secp256k1::Secp256k1; + +use std::cell::RefCell; +use std::collections::{HashMap, hash_map}; +use std::cmp; +use std::hash::Hash; +use std::sync::Arc; +use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering}; + +#[inline] +pub fn slice_to_be16(v: &[u8]) -> u16 { + ((v[0] as u16) << 8*1) | + ((v[1] as u16) << 8*0) +} + +#[inline] +pub fn slice_to_be24(v: &[u8]) -> u32 { + ((v[0] as u32) << 8*2) | + ((v[1] as u32) << 8*1) | + ((v[2] as u32) << 8*0) +} + +#[inline] +pub fn slice_to_be32(v: &[u8]) -> u32 { + ((v[0] as u32) << 8*3) | + ((v[1] as u32) << 8*2) | + ((v[2] as u32) << 8*1) | + ((v[3] as u32) << 8*0) +} + +#[inline] +pub fn be64_to_array(u: u64) -> [u8; 8] { + let mut v = [0; 8]; + v[0] = ((u >> 8*7) & 0xff) as u8; + v[1] = ((u >> 8*6) & 0xff) as u8; + v[2] = ((u >> 8*5) & 0xff) as u8; + v[3] = ((u >> 8*4) & 0xff) as u8; + v[4] = ((u >> 8*3) & 0xff) as u8; + v[5] = ((u >> 8*2) & 0xff) as u8; + v[6] = ((u >> 8*1) & 0xff) as u8; + v[7] = ((u >> 8*0) & 0xff) as u8; + v +} + +struct InputData { + data: Vec, + read_pos: AtomicUsize, +} +impl InputData { + fn get_slice(&self, len: usize) -> Option<&[u8]> { + let old_pos = self.read_pos.fetch_add(len, Ordering::AcqRel); + if self.data.len() < old_pos + len { + return None; + } + Some(&self.data[old_pos..old_pos + len]) + } +} + +struct FuzzEstimator { + input: Arc, +} +impl FeeEstimator for FuzzEstimator { + fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u64 { + //TODO: We should actually be testing at least much more than 64k... + match self.input.get_slice(2) { + Some(slice) => cmp::max(slice_to_be16(slice) as u64, 253), + None => 0 + } + } +} + +struct TestBroadcaster {} +impl BroadcasterInterface for TestBroadcaster { + fn broadcast_transaction(&self, _tx: &Transaction) {} +} + +#[derive(Clone)] +struct Peer<'a> { + id: u8, + peers_connected: &'a RefCell<[bool; 256]>, +} +impl<'a> SocketDescriptor for Peer<'a> { + fn send_data(&mut self, data: &[u8], _resume_read: bool) -> usize { + data.len() + } + fn disconnect_socket(&mut self) { + assert!(self.peers_connected.borrow()[self.id as usize]); + self.peers_connected.borrow_mut()[self.id as usize] = false; + } +} +impl<'a> PartialEq for Peer<'a> { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} +impl<'a> Eq for Peer<'a> {} +impl<'a> Hash for Peer<'a> { + fn hash(&self, h: &mut H) { + self.id.hash(h) + } +} + +struct MoneyLossDetector<'a> { + manager: Arc, + monitor: Arc>, + handler: PeerManager>, + + peers: &'a RefCell<[bool; 256]>, + funding_txn: Vec, + txids_confirmed: HashMap, + header_hashes: Vec, + height: usize, + max_height: usize, + blocks_connected: u32, +} +impl<'a> MoneyLossDetector<'a> { + pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc, monitor: Arc>, handler: PeerManager>) -> Self { + MoneyLossDetector { + manager, + monitor, + handler, + + peers, + funding_txn: Vec::new(), + txids_confirmed: HashMap::new(), + header_hashes: vec![Default::default()], + height: 0, + max_height: 0, + blocks_connected: 0, + } + } + + fn connect_block(&mut self, all_txn: &[Transaction]) { + let mut txn = Vec::with_capacity(all_txn.len()); + let mut txn_idxs = Vec::with_capacity(all_txn.len()); + for (idx, tx) in all_txn.iter().enumerate() { + let txid = tx.txid(); + match self.txids_confirmed.entry(txid) { + hash_map::Entry::Vacant(e) => { + e.insert(self.height); + txn.push(tx); + txn_idxs.push(idx as u32 + 1); + }, + _ => {}, + } + } + + let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 }; + self.height += 1; + self.blocks_connected += 1; + self.manager.block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]); + (*self.monitor).block_connected(&header, self.height as u32, &txn[..], &txn_idxs[..]); + if self.header_hashes.len() > self.height { + self.header_hashes[self.height] = header.bitcoin_hash(); + } else { + assert_eq!(self.header_hashes.len(), self.height); + self.header_hashes.push(header.bitcoin_hash()); + } + self.max_height = cmp::max(self.height, self.max_height); + } + + fn disconnect_block(&mut self) { + if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) { + self.height -= 1; + let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + self.manager.block_disconnected(&header, self.height as u32); + self.monitor.block_disconnected(&header, self.height as u32); + let removal_height = self.height; + self.txids_confirmed.retain(|_, height| { + removal_height != *height + }); + } + } +} + +impl<'a> Drop for MoneyLossDetector<'a> { + fn drop(&mut self) { + if !::std::thread::panicking() { + // Disconnect all peers + for (idx, peer) in self.peers.borrow().iter().enumerate() { + if *peer { + self.handler.disconnect_event(&Peer{id: idx as u8, peers_connected: &self.peers}); + } + } + + // Force all channels onto the chain (and time out claim txn) + self.manager.force_close_all_channels(); + } + } +} + +struct KeyProvider { + node_secret: SecretKey, + counter: AtomicU64, +} +impl KeysInterface for KeyProvider { + fn get_node_secret(&self) -> SecretKey { + self.node_secret.clone() + } + + fn get_destination_script(&self) -> Script { + let secp_ctx = Secp256k1::signing_only(); + let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(); + let our_channel_monitor_claim_key_hash = ::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize()); + Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() + } + + fn get_shutdown_pubkey(&self) -> PublicKey { + let secp_ctx = Secp256k1::signing_only(); + PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap()) + } + + fn get_channel_keys(&self, inbound: bool) -> ChannelKeys { + let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; + if inbound { + ChannelKeys { + funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ctr]).unwrap(), + revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ctr]).unwrap(), + payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ctr]).unwrap(), + delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ctr]).unwrap(), + htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, ctr]).unwrap(), + commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr], + } + } else { + ChannelKeys { + funding_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, ctr]).unwrap(), + revocation_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, ctr]).unwrap(), + payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, ctr]).unwrap(), + delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, ctr]).unwrap(), + htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, ctr]).unwrap(), + commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr], + } + } + } + + fn get_session_key(&self) -> SecretKey { + let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8; + SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, ctr]).unwrap() + } + + fn get_channel_id(&self) -> [u8; 32] { + let ctr = self.counter.fetch_add(1, Ordering::Relaxed); + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8] + } +} + +#[inline] +pub fn do_test(data: &[u8], logger: &Arc) { + let input = Arc::new(InputData { + data: data.to_vec(), + read_pos: AtomicUsize::new(0), + }); + let fee_est = Arc::new(FuzzEstimator { + input: input.clone(), + }); + + macro_rules! get_slice { + ($len: expr) => { + match input.get_slice($len as usize) { + Some(slice) => slice, + None => return, + } + } + } + + macro_rules! get_pubkey { + () => { + match PublicKey::from_slice(get_slice!(33)) { + Ok(key) => key, + Err(_) => return, + } + } + } + + let our_network_key = match SecretKey::from_slice(get_slice!(32)) { + Ok(key) => key, + Err(_) => return, + }; + + let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); + let broadcast = Arc::new(TestBroadcaster{}); + let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger), fee_est.clone()); + + let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), counter: AtomicU64::new(0) }); + let mut config = UserConfig::new(); + config.channel_options.fee_proportional_millionths = slice_to_be32(get_slice!(4)); + config.channel_options.announced_channel = get_slice!(1)[0] != 0; + config.peer_channel_config_limits.min_dust_limit_satoshis = 0; + let channelmanager = ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap(); + let router = Arc::new(Router::new(PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret()), watch.clone(), Arc::clone(&logger))); + + let peers = RefCell::new([false; 256]); + let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler { + chan_handler: channelmanager.clone(), + route_handler: router.clone(), + }, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger))); + + let mut should_forward = false; + let mut payments_received: Vec = Vec::new(); + let mut payments_sent = 0; + let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new(); + let mut pending_funding_signatures = HashMap::new(); + let mut pending_funding_relay = Vec::new(); + + loop { + match get_slice!(1)[0] { + 0 => { + let mut new_id = 0; + for i in 1..256 { + if !peers.borrow()[i-1] { + new_id = i; + break; + } + } + if new_id == 0 { return; } + loss_detector.handler.new_outbound_connection(get_pubkey!(), Peer{id: (new_id - 1) as u8, peers_connected: &peers}).unwrap(); + peers.borrow_mut()[new_id - 1] = true; + }, + 1 => { + let mut new_id = 0; + for i in 1..256 { + if !peers.borrow()[i-1] { + new_id = i; + break; + } + } + if new_id == 0 { return; } + loss_detector.handler.new_inbound_connection(Peer{id: (new_id - 1) as u8, peers_connected: &peers}).unwrap(); + peers.borrow_mut()[new_id - 1] = true; + }, + 2 => { + let peer_id = get_slice!(1)[0]; + if !peers.borrow()[peer_id as usize] { return; } + loss_detector.handler.disconnect_event(&Peer{id: peer_id, peers_connected: &peers}); + peers.borrow_mut()[peer_id as usize] = false; + }, + 3 => { + let peer_id = get_slice!(1)[0]; + if !peers.borrow()[peer_id as usize] { return; } + match loss_detector.handler.read_event(&mut Peer{id: peer_id, peers_connected: &peers}, get_slice!(get_slice!(1)[0]).to_vec()) { + Ok(res) => assert!(!res), + Err(_) => { peers.borrow_mut()[peer_id as usize] = false; } + } + }, + 4 => { + let value = slice_to_be24(get_slice!(3)) as u64; + let route = match router.get_route(&get_pubkey!(), None, &Vec::new(), value, 42) { + Ok(route) => route, + Err(_) => return, + }; + let mut payment_hash = PaymentHash([0; 32]); + payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent)); + let mut sha = Sha256::engine(); + sha.input(&payment_hash.0[..]); + payment_hash.0 = Sha256::from_engine(sha).into_inner(); + payments_sent += 1; + match channelmanager.send_payment(route, payment_hash) { + Ok(_) => {}, + Err(_) => return, + } + }, + 5 => { + let peer_id = get_slice!(1)[0]; + if !peers.borrow()[peer_id as usize] { return; } + let their_key = get_pubkey!(); + let chan_value = slice_to_be24(get_slice!(3)) as u64; + let push_msat_value = slice_to_be24(get_slice!(3)) as u64; + if channelmanager.create_channel(their_key, chan_value, push_msat_value, 0).is_err() { return; } + }, + 6 => { + let mut channels = channelmanager.list_channels(); + let channel_id = get_slice!(1)[0] as usize; + if channel_id >= channels.len() { return; } + channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) }); + if channelmanager.close_channel(&channels[channel_id].channel_id).is_err() { return; } + }, + 7 => { + if should_forward { + channelmanager.process_pending_htlc_forwards(); + should_forward = false; + } + }, + 8 => { + for payment in payments_received.drain(..) { + // SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s + // for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot + // fulfill this HTLC, but if they are, we can just take the first byte and + // place that anywhere in our preimage. + if &payment.0[1..] != &[0; 31] { + channelmanager.fail_htlc_backwards(&payment); + } else { + let mut payment_preimage = PaymentPreimage([0; 32]); + payment_preimage.0[0] = payment.0[0]; + channelmanager.claim_funds(payment_preimage); + } + } + }, + 9 => { + for payment in payments_received.drain(..) { + channelmanager.fail_htlc_backwards(&payment); + } + }, + 10 => { + 'outer_loop: for funding_generation in pending_funding_generation.drain(..) { + let mut tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: vec![TxOut { + value: funding_generation.1, script_pubkey: funding_generation.2, + }] }; + let funding_output = 'search_loop: loop { + let funding_txid = tx.txid(); + if let None = loss_detector.txids_confirmed.get(&funding_txid) { + let outpoint = OutPoint::new(funding_txid, 0); + for chan in channelmanager.list_channels() { + if chan.channel_id == outpoint.to_channel_id() { + tx.version += 1; + continue 'search_loop; + } + } + break outpoint; + } + tx.version += 1; + if tx.version > 0xff { + continue 'outer_loop; + } + }; + channelmanager.funding_transaction_generated(&funding_generation.0, funding_output.clone()); + pending_funding_signatures.insert(funding_output, tx); + } + }, + 11 => { + if !pending_funding_relay.is_empty() { + loss_detector.connect_block(&pending_funding_relay[..]); + for _ in 2..100 { + loss_detector.connect_block(&[]); + } + } + for tx in pending_funding_relay.drain(..) { + loss_detector.funding_txn.push(tx); + } + }, + 12 => { + let txlen = slice_to_be16(get_slice!(2)); + if txlen == 0 { + loss_detector.connect_block(&[]); + } else { + let txres: Result = deserialize(get_slice!(txlen)); + if let Ok(tx) = txres { + loss_detector.connect_block(&[tx]); + } else { + return; + } + } + }, + 13 => { + loss_detector.disconnect_block(); + }, + 14 => { + let mut channels = channelmanager.list_channels(); + let channel_id = get_slice!(1)[0] as usize; + if channel_id >= channels.len() { return; } + channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) }); + channelmanager.force_close_channel(&channels[channel_id].channel_id); + }, + _ => return, + } + loss_detector.handler.process_events(); + for event in loss_detector.manager.get_and_clear_pending_events() { + match event { + Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => { + pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script)); + }, + Event::FundingBroadcastSafe { funding_txo, .. } => { + pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap()); + }, + Event::PaymentReceived { payment_hash, .. } => { + payments_received.push(payment_hash); + }, + Event::PaymentSent {..} => {}, + Event::PaymentFailed {..} => {}, + Event::PendingHTLCsForwardable {..} => { + should_forward = true; + }, + Event::SpendableOutputs {..} => {}, + } + } + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); + do_test(data, &logger); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); + do_test(data, &logger); + }); + } +} + +#[cfg(feature = "libfuzzer_fuzz")] +#[macro_use] extern crate libfuzzer_sys; +#[cfg(feature = "libfuzzer_fuzz")] +fuzz_target!(|data: &[u8]| { + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); + do_test(data, &logger); +}); + +extern crate hex; +#[cfg(test)] +mod tests { + use utils::test_logger; + use lightning::util::logger::{Logger, Record}; + use std::collections::HashMap; + use std::sync::{Arc, Mutex}; + + #[test] + fn duplicate_crash() { + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); + super::do_test(&::hex::decode("00").unwrap(), &logger); + } + + struct TrackingLogger { + /// (module, message) -> count + pub lines: Mutex>, + } + impl Logger for TrackingLogger { + fn log(&self, record: &Record) { + *self.lines.lock().unwrap().entry((record.module_path.to_string(), format!("{}", record.args))).or_insert(0) += 1; + println!("{:<5} [{} : {}, {}] {}", record.level.to_string(), record.module_path, record.file, record.line, record.args); + } + } + + #[test] + fn test_no_existing_test_breakage() { + // To avoid accidentally causing all existing fuzz test cases to be useless by making minor + // changes (such as requesting feerate info in a new place), we run a pretty full + // step-through with two peers and HTLC forwarding here. Obviously this is pretty finicky, + // so this should be updated pretty liberally, but at least we'll know when changes occur. + // If nothing else, this test serves as a pretty great initial full_stack_target seed. + + // What each byte represents is broken down below, and then everything is concatenated into + // one large test at the end (you want %s/ -.*//g %s/\n\| \|\t\|\///g). + + // Following BOLT 8, lightning message on the wire are: 2-byte encrypted message length + + // 16-byte MAC of the encrypted message length + encrypted Lightning message + 16-byte MAC + // of the Lightning message + // I.e 2nd inbound read, len 18 : 0006 (encrypted message length) + 03000000000000000000000000000000 (MAC of the encrypted message length) + // Len 22 : 0010 00000000 (encrypted lightning message) + 03000000000000000000000000000000 (MAC of the Lightning message) + + // 0000000000000000000000000000000000000000000000000000000000000000 - our network key + // 00000000 - fee_proportional_millionths + // 01 - announce_channels_publicly + // + // 00 - new outbound connection with id 0 + // 030000000000000000000000000000000000000000000000000000000000000000 - peer's pubkey + // 030032 - inbound read from peer id 0 of len 50 + // 00 030000000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - noise act two (0||pubkey||mac) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0006 03000000000000000000000000000000 - message header indicating message length 6 + // 030016 - inbound read from peer id 0 of len 22 + // 0010 00000000 03000000000000000000000000000000 - init message with no features (type 16) and mac + // + // 030012 - inbound read from peer id 0 of len 18 + // 0141 03000000000000000000000000000000 - message header indicating message length 321 + // 0300fe - inbound read from peer id 0 of len 254 + // 0020 7500000000000000000000000000000000000000000000000000000000000000 ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679 000000000000c350 0000000000000000 0000000000000222 ffffffffffffffff 0000000000000222 0000000000000000 000000fd 0006 01e3 030000000000000000000000000000000000000000000000000000000000000001 030000000000000000000000000000000000000000000000000000000000000002 030000000000000000000000000000000000000000000000000000000000000003 030000000000000000000000000000000000000000000000000000000000000004 - beginning of open_channel message + // 030053 - inbound read from peer id 0 of len 83 + // 030000000000000000000000000000000000000000000000000000000000000005 030000000000000000000000000000000000000000000000000000000000000000 01 03000000000000000000000000000000 - rest of open_channel and mac + // + // 00fd00fd00fd - Three feerate requests (all returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // - client should now respond with accept_channel (CHECK 1: type 33 to peer 03000000) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0084 03000000000000000000000000000000 - message header indicating message length 132 + // 030094 - inbound read from peer id 0 of len 148 + // 0022 ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679 3d00000000000000000000000000000000000000000000000000000000000000 0000 5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 03000000000000000000000000000000 - funding_created and mac + // - client should now respond with funding_signed (CHECK 2: type 35 to peer 03000000) + // + // 0c005e - connect a block with one transaction of len 94 + // 020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000 - the funding transaction + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // - by now client should have sent a funding_locked (CHECK 3: SendFundingLocked to 03000000 for chan 3d000000) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0043 03000000000000000000000000000000 - message header indicating message length 67 + // 030053 - inbound read from peer id 0 of len 83 + // 0024 3d00000000000000000000000000000000000000000000000000000000000000 030100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - funding_locked and mac + // + // 01 - new inbound connection with id 1 + // 030132 - inbound read from peer id 1 of len 50 + // 0003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000 - inbound noise act 1 + // 030142 - inbound read from peer id 1 of len 66 + // 000302000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003000000000000000000000000000000 - inbound noise act 3 + // + // 030112 - inbound read from peer id 1 of len 18 + // 0006 01000000000000000000000000000000 - message header indicating message length 6 + // 030116 - inbound read from peer id 1 of len 22 + // 0010 00000000 01000000000000000000000000000000 - init message with no features (type 16) + // + // 05 01 030200000000000000000000000000000000000000000000000000000000000000 00c350 0003e8 - create outbound channel to peer 1 for 50k sat + // 00fd00fd00fd - Three feerate requests (all returning min feerate) (gonna be ingested by FuzzEstimator) + // + // 030112 - inbound read from peer id 1 of len 18 + // 0110 01000000000000000000000000000000 - message header indicating message length 272 + // 0301ff - inbound read from peer id 1 of len 255 + // 0021 0000000000000000000000000000000000000000000000000000000000000e02 000000000000001a 00000000004c4b40 00000000000003e8 00000000000003e8 00000002 03f0 0005 030000000000000000000000000000000000000000000000000000000000000100 030000000000000000000000000000000000000000000000000000000000000200 030000000000000000000000000000000000000000000000000000000000000300 030000000000000000000000000000000000000000000000000000000000000400 030000000000000000000000000000000000000000000000000000000000000500 03000000000000000000000000000000 - beginning of accept_channel + // 030121 - inbound read from peer id 1 of len 33 + // 0000000000000000000000000000000000 01000000000000000000000000000000 - rest of accept_channel and mac + // + // 0a - create the funding transaction (client should send funding_created now) + // + // 030112 - inbound read from peer id 1 of len 18 + // 0062 01000000000000000000000000000000 - message header indicating message length 98 + // 030172 - inbound read from peer id 1 of len 114 + // 0023 3900000000000000000000000000000000000000000000000000000000000000 f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 01000000000000000000000000000000 - funding_signed message and mac + // + // 0b - broadcast funding transaction + // - by now client should have sent a funding_locked (CHECK 4: SendFundingLocked to 03020000 for chan 3f000000) + // + // 030112 - inbound read from peer id 1 of len 18 + // 0043 01000000000000000000000000000000 - message header indicating message length 67 + // 030153 - inbound read from peer id 1 of len 83 + // 0024 3900000000000000000000000000000000000000000000000000000000000000 030100000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - funding_locked and mac + // + // 030012 - inbound read from peer id 0 of len 18 + // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 + // 0300ff - inbound read from peer id 0 of len 255 + // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000000 0000000000003e80 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300c1 - inbound read from peer id 0 of len 193 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac + // + // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0064 03000000000000000000000000000000 - message header indicating message length 100 + // 030074 - inbound read from peer id 0 of len 116 + // 0084 3d00000000000000000000000000000000000000000000000000000000000000 4d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac + // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6: types 133 and 132 to peer 03000000) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0063 03000000000000000000000000000000 - message header indicating message length 99 + // 030073 - inbound read from peer id 0 of len 115 + // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 030200000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac + // + // 07 - process the now-pending HTLC forward + // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: SendHTLCs event for node 03020000 with 1 HTLCs for channel 3f000000) + // + // - we respond with commitment_signed then revoke_and_ack (a weird, but valid, order) + // 030112 - inbound read from peer id 1 of len 18 + // 0064 01000000000000000000000000000000 - message header indicating message length 100 + // 030174 - inbound read from peer id 1 of len 116 + // 0084 3900000000000000000000000000000000000000000000000000000000000000 f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 0063 01000000000000000000000000000000 - message header indicating message length 99 + // 030173 - inbound read from peer id 1 of len 115 + // 0085 3900000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 030200000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 004a 01000000000000000000000000000000 - message header indicating message length 74 + // 03015a - inbound read from peer id 1 of len 90 + // 0082 3900000000000000000000000000000000000000000000000000000000000000 0000000000000000 ff00888888888888888888888888888888888888888888888888888888888888 01000000000000000000000000000000 - update_fulfill_htlc and mac + // - client should immediately claim the pending HTLC from peer 0 (CHECK 8: SendFulfillHTLCs for node 03000000 with preimage ff00888888 for channel 3d000000) + // + // 030112 - inbound read from peer id 1 of len 18 + // 0064 01000000000000000000000000000000 - message header indicating message length 100 + // 030174 - inbound read from peer id 1 of len 116 + // 0084 3900000000000000000000000000000000000000000000000000000000000000 fd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 0063 01000000000000000000000000000000 - message header indicating message length 99 + // 030173 - inbound read from peer id 1 of len 115 + // 0085 3900000000000000000000000000000000000000000000000000000000000000 0100000000000000000000000000000000000000000000000000000000000000 030300000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac + // + // - before responding to the commitment_signed generated above, send a new HTLC + // 030012 - inbound read from peer id 0 of len 18 + // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 + // 0300ff - inbound read from peer id 0 of len 255 + // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000000000003e80 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300c1 - inbound read from peer id 0 of len 193 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac + // + // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // + // - now respond to the update_fulfill_htlc+commitment_signed messages the client sent to peer 0 + // 030012 - inbound read from peer id 0 of len 18 + // 0063 03000000000000000000000000000000 - message header indicating message length 99 + // 030073 - inbound read from peer id 0 of len 115 + // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0100000000000000000000000000000000000000000000000000000000000000 030300000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac + // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6 duplicates) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0064 03000000000000000000000000000000 - message header indicating message length 100 + // 030074 - inbound read from peer id 0 of len 116 + // 0084 3d00000000000000000000000000000000000000000000000000000000000000 be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac + // + // 030012 - inbound read from peer id 0 of len 18 + // 0063 03000000000000000000000000000000 - message header indicating message length 99 + // 030073 - inbound read from peer id 0 of len 115 + // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0200000000000000000000000000000000000000000000000000000000000000 030400000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac + // + // 07 - process the now-pending HTLC forward + // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) + // - we respond with revoke_and_ack, then commitment_signed, then update_fail_htlc + // + // 030112 - inbound read from peer id 1 of len 18 + // 0064 01000000000000000000000000000000 - message header indicating message length 100 + // 030174 - inbound read from peer id 1 of len 116 + // 0084 3900000000000000000000000000000000000000000000000000000000000000 fc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 0063 01000000000000000000000000000000 - message header indicating message length 99 + // 030173 - inbound read from peer id 1 of len 115 + // 0085 3900000000000000000000000000000000000000000000000000000000000000 0200000000000000000000000000000000000000000000000000000000000000 030400000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 002c 01000000000000000000000000000000 - message header indicating message length 44 + // 03013c - inbound read from peer id 1 of len 60 + // 0083 3900000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000 01000000000000000000000000000000 - update_fail_htlc and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 0064 01000000000000000000000000000000 - message header indicating message length 100 + // 030174 - inbound read from peer id 1 of len 116 + // 0084 3900000000000000000000000000000000000000000000000000000000000000 fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 0000 01000000000000000000000000000000 - commitment_signed and mac + // + // 030112 - inbound read from peer id 1 of len 18 + // 0063 01000000000000000000000000000000 - message header indicating message length 99 + // 030173 - inbound read from peer id 1 of len 115 + // 0085 3900000000000000000000000000000000000000000000000000000000000000 0300000000000000000000000000000000000000000000000000000000000000 030500000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000 - revoke_and_ack and mac + // + // 07 - process the now-pending HTLC forward + // - client now sends id 0 update_fail_htlc and commitment_signed (CHECK 9) + // - now respond to the update_fail_htlc+commitment_signed messages the client sent to peer 0 + // + // 030012 - inbound read from peer id 0 of len 18 + // 0063 03000000000000000000000000000000 - message header indicating message length 99 + // 030073 - inbound read from peer id 0 of len 115 + // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0300000000000000000000000000000000000000000000000000000000000000 030500000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac + // + // 030012 - inbound read from peer id 0 of len 18 + // 0064 03000000000000000000000000000000 - message header indicating message length 100 + // 030074 - inbound read from peer id 0 of len 116 + // 0084 3d00000000000000000000000000000000000000000000000000000000000000 4f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0000 03000000000000000000000000000000 - commitment_signed and mac + // - client should now respond with revoke_and_ack (CHECK 5 duplicate) + // + // 030012 - inbound read from peer id 0 of len 18 + // 05ac 03000000000000000000000000000000 - message header indicating message length 1452 + // 0300ff - inbound read from peer id 0 of len 255 + // 0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000002 00000000000b0838 ff00000000000000000000000000000000000000000000000000000000000000 00000121 00 030000000000000000000000000000000000000000000000000000000000000555 0000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - beginning of update_add_htlc from 0 to 1 via client + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300ff - inbound read from peer id 0 of len 255 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // 0300c1 - inbound read from peer id 0 of len 193 + // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ef00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - end of update_add_htlc from 0 to 1 via client and mac + // + // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // + // 030012 - inbound read from peer id 0 of len 18 + // 00a4 03000000000000000000000000000000 - message header indicating message length 164 + // 0300b4 - inbound read from peer id 0 of len 180 + // 0084 3d00000000000000000000000000000000000000000000000000000000000000 07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 0001 c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f00000000000000 03000000000000000000000000000000 - commitment_signed and mac + // - client should now respond with revoke_and_ack and commitment_signed (CHECK 5/6 duplicates) + // + // 030012 - inbound read from peer id 0 of len 18 + // 0063 03000000000000000000000000000000 - message header indicating message length 99 + // 030073 - inbound read from peer id 0 of len 115 + // 0085 3d00000000000000000000000000000000000000000000000000000000000000 0400000000000000000000000000000000000000000000000000000000000000 030600000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000 - revoke_and_ack and mac + // + // 07 - process the now-pending HTLC forward + // - client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate) + // + // 0c007d - connect a block with one transaction of len 125 + // 0200000001390000000000000000000000000000000000000000000000000000000000000000000000000000008002000100000000000022002090000000000000000000000000000000000000000000000000000000000000006cc10000000000001600145c0000000000000000000000000000000000000005000020 - the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000 + // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // 00fd - A feerate request (returning min feerate, which our open_channel also uses) (gonna be ingested by FuzzEstimator) + // 0c005e - connect a block with one transaction of len 94 + // 0200000001fd00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f60000000000000000000000000000000000000000000000000000000000000000000000 - the funding transaction + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // 0c0000 - connect a block with no transactions + // + // 07 - process the now-pending HTLC forward + // - client now fails the HTLC backwards as it was unable to extract the payment preimage (CHECK 9 duplicate and CHECK 10) + + let logger = Arc::new(TrackingLogger { lines: Mutex::new(HashMap::new()) }); + super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000603000000000000000000000000000000030016001000000000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d0000000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001030132000300000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003014200030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000300000000000000000000000000000003011200060100000000000000000000000000000003011600100000000001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd00fd0301120110010000000000000000000000000000000301ff00210000000000000000000000000000000000000000000000000000000000000e02000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233900000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b030112004301000000000000000000000000000000030153002439000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a008239000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000301120063010000000000000000000000000000000301730085390000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e8000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833900000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000030112006301000000000000000000000000000000030173008539000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e800000000010000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d0200000001390000000000000000000000000000000000000000000000000000000000000000000000000000008002000100000000000022002090000000000000000000000000000000000000000000000000000000000000006cc10000000000001600145c000000000000000000000000000000000000000500002000fd00fd0c005e0200000001fd00000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f600000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c000007").unwrap(), &(Arc::clone(&logger) as Arc)); + + let log_entries = logger.lines.lock().unwrap(); + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 + assert_eq!(log_entries.get(&("lightning::ln::channelmonitor".to_string(), "Input spending remote commitment tx (00000000000000000000000000000000000000000000000000000000000000fd:0) in 0000000000000000000000000000000000000000000000000000000000000044 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10 + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/gen_target.sh b/lightning/fuzz/fuzz_targets/msg_targets/gen_target.sh new file mode 100755 index 000000000..cfd100f3d --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/gen_target.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +GEN_TEST() { + tn=$(echo $1 | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\2/g') + fn=msg_$(echo $tn | tr '[:upper:]' '[:lower:]')_target.rs + cat msg_target_template.txt | sed s/MSG_TARGET/$1/ | sed "s/TEST_MSG/$2/" | sed "s/EXTRA_ARGS/$3/" > $fn +} + +GEN_TEST AcceptChannel test_msg "" +GEN_TEST AnnouncementSignatures test_msg "" +GEN_TEST ChannelReestablish test_msg "" +GEN_TEST ClosingSigned test_msg "" +GEN_TEST CommitmentSigned test_msg "" +GEN_TEST DecodedOnionErrorPacket test_msg "" +GEN_TEST FundingCreated test_msg "" +GEN_TEST FundingLocked test_msg "" +GEN_TEST FundingSigned test_msg "" +GEN_TEST Init test_msg "" +GEN_TEST OpenChannel test_msg "" +GEN_TEST RevokeAndACK test_msg "" +GEN_TEST Shutdown test_msg "" +GEN_TEST UpdateFailHTLC test_msg "" +GEN_TEST UpdateFailMalformedHTLC test_msg "" +GEN_TEST UpdateFee test_msg "" +GEN_TEST UpdateFulfillHTLC test_msg "" + +GEN_TEST ChannelAnnouncement test_msg_exact "" +GEN_TEST ChannelUpdate test_msg_exact "" +GEN_TEST NodeAnnouncement test_msg_exact "" + +GEN_TEST UpdateAddHTLC test_msg_hole ", 85, 33" +GEN_TEST ErrorMessage test_msg_hole ", 32, 2" +GEN_TEST OnionHopData test_msg_hole ", 1+8+8+4, 12" + +GEN_TEST Ping test_msg_simple "" +GEN_TEST Pong test_msg_simple "" diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs new file mode 100644 index 000000000..0f18d0232 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::AcceptChannel, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs new file mode 100644 index 000000000..226028ea0 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::AnnouncementSignatures, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs new file mode 100644 index 000000000..0bdc10e85 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_exact!(msgs::ChannelAnnouncement, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs new file mode 100644 index 000000000..4af593759 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::ChannelReestablish, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs new file mode 100644 index 000000000..724dca412 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_exact!(msgs::ChannelUpdate, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs new file mode 100644 index 000000000..faeeae3eb --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::ClosingSigned, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs new file mode 100644 index 000000000..97c4b3088 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::CommitmentSigned, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs new file mode 100644 index 000000000..9b190b086 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::DecodedOnionErrorPacket, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs new file mode 100644 index 000000000..d749dc91f --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_hole!(msgs::ErrorMessage, data, 32, 2); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs new file mode 100644 index 000000000..45b257bb0 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::FundingCreated, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs new file mode 100644 index 000000000..cd1e89741 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::FundingLocked, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs new file mode 100644 index 000000000..5992d6902 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::FundingSigned, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs new file mode 100644 index 000000000..cdca84821 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::Init, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs new file mode 100644 index 000000000..f0a7a4c0d --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_exact!(msgs::NodeAnnouncement, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs new file mode 100644 index 000000000..058c050c5 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_hole!(msgs::OnionHopData, data, 1+8+8+4, 12); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs new file mode 100644 index 000000000..aa13e96dd --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::OpenChannel, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs new file mode 100644 index 000000000..d2ea91335 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_simple!(msgs::Ping, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs new file mode 100644 index 000000000..18120e2d1 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_simple!(msgs::Pong, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs new file mode 100644 index 000000000..d82268d93 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::RevokeAndACK, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs new file mode 100644 index 000000000..34d4d2003 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::Shutdown, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt b/lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt new file mode 100644 index 000000000..2704bcdff --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + TEST_MSG!(msgs::MSG_TARGET, dataEXTRA_ARGS); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs new file mode 100644 index 000000000..e64a5c29f --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg_hole!(msgs::UpdateAddHTLC, data, 85, 33); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs new file mode 100644 index 000000000..fedce568e --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::UpdateFailHTLC, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs new file mode 100644 index 000000000..377378fcc --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::UpdateFailMalformedHTLC, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs new file mode 100644 index 000000000..56b9ac424 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::UpdateFee, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs new file mode 100644 index 000000000..f0c936d1e --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs @@ -0,0 +1,43 @@ +// This file is auto-generated by gen_target.sh based on msg_target_template.txt +// To modify it, modify msg_target_template.txt and run gen_target.sh instead. + +extern crate lightning; + +use lightning::ln::msgs; + +mod utils; +use utils::VecWriter; + +#[inline] +pub fn do_test(data: &[u8]) { + test_msg!(msgs::UpdateFulfillHTLC, data); +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/msg_targets/utils.rs b/lightning/fuzz/fuzz_targets/msg_targets/utils.rs new file mode 100644 index 000000000..a5257ba0f --- /dev/null +++ b/lightning/fuzz/fuzz_targets/msg_targets/utils.rs @@ -0,0 +1,81 @@ +#![macro_use] + +use lightning::util::ser::Writer; +pub struct VecWriter(pub Vec); +impl Writer for VecWriter { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + assert!(self.0.capacity() >= self.0.len() + buf.len()); + self.0.extend_from_slice(buf); + Ok(()) + } + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); + } +} + +#[macro_export] +macro_rules! test_msg { + ($MsgType: path, $data: ident) => { + { + use lightning::util::ser::{Writeable, Readable}; + let mut r = ::std::io::Cursor::new($data); + if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { + let p = r.position() as usize; + let mut w = VecWriter(Vec::new()); + msg.write(&mut w).unwrap(); + + assert_eq!(w.0.len(), p); + assert_eq!(&r.into_inner()[..p], &w.0[..p]); + } + } + } +} + +#[macro_export] +macro_rules! test_msg_simple { + ($MsgType: path, $data: ident) => { + { + use lightning::util::ser::{Writeable, Readable}; + let mut r = ::std::io::Cursor::new($data); + if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { + let mut w = VecWriter(Vec::new()); + msg.write(&mut w).unwrap(); + } + } + } +} + +#[macro_export] +macro_rules! test_msg_exact { + ($MsgType: path, $data: ident) => { + { + use lightning::util::ser::{Writeable, Readable}; + let mut r = ::std::io::Cursor::new($data); + if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { + let mut w = VecWriter(Vec::new()); + msg.write(&mut w).unwrap(); + + assert_eq!(&r.into_inner()[..], &w.0[..]); + } + } + } +} + +#[macro_export] +macro_rules! test_msg_hole { + ($MsgType: path, $data: ident, $hole: expr, $hole_len: expr) => { + { + use lightning::util::ser::{Writeable, Readable}; + let mut r = ::std::io::Cursor::new($data); + if let Ok(msg) = <$MsgType as Readable<::std::io::Cursor<&[u8]>>>::read(&mut r) { + let mut w = VecWriter(Vec::new()); + msg.write(&mut w).unwrap(); + let p = w.0.len() as usize; + + assert_eq!(w.0.len(), p); + assert_eq!(&r.get_ref()[..$hole], &w.0[..$hole]); + assert_eq!(&r.get_ref()[$hole+$hole_len..p], &w.0[$hole+$hole_len..]); + } + } + } +} diff --git a/lightning/fuzz/fuzz_targets/peer_crypt_target.rs b/lightning/fuzz/fuzz_targets/peer_crypt_target.rs new file mode 100644 index 000000000..0b82303f8 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/peer_crypt_target.rs @@ -0,0 +1,109 @@ +extern crate lightning; +extern crate secp256k1; + +use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor; + +use secp256k1::key::{PublicKey,SecretKey}; + +#[inline] +fn slice_to_be16(v: &[u8]) -> u16 { + ((v[0] as u16) << 8*1) | + ((v[1] as u16) << 8*0) +} + +#[inline] +pub fn do_test(data: &[u8]) { + let mut read_pos = 0; + macro_rules! get_slice { + ($len: expr) => { + { + let slice_len = $len as usize; + if data.len() < read_pos + slice_len { + return; + } + read_pos += slice_len; + &data[read_pos - slice_len..read_pos] + } + } + } + + let our_network_key = match SecretKey::from_slice(get_slice!(32)) { + Ok(key) => key, + Err(_) => return, + }; + let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) { + Ok(key) => key, + Err(_) => return, + }; + + let mut crypter = if get_slice!(1)[0] != 0 { + let their_pubkey = match PublicKey::from_slice(get_slice!(33)) { + Ok(key) => key, + Err(_) => return, + }; + let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key); + crypter.get_act_one(); + match crypter.process_act_two(get_slice!(50), &our_network_key) { + Ok(_) => {}, + Err(_) => return, + } + assert!(crypter.is_ready_for_encryption()); + crypter + } else { + let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key); + match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key) { + Ok(_) => {}, + Err(_) => return, + } + match crypter.process_act_three(get_slice!(66)) { + Ok(_) => {}, + Err(_) => return, + } + assert!(crypter.is_ready_for_encryption()); + crypter + }; + loop { + if get_slice!(1)[0] == 0 { + crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2)))); + } else { + let len = match crypter.decrypt_length_header(get_slice!(16+2)) { + Ok(len) => len, + Err(_) => return, + }; + match crypter.decrypt_message(get_slice!(len as usize + 16)) { + Ok(_) => {}, + Err(_) => return, + } + } + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("01").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/router_target.rs b/lightning/fuzz/fuzz_targets/router_target.rs new file mode 100644 index 000000000..25bf38274 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/router_target.rs @@ -0,0 +1,264 @@ +extern crate bitcoin; +extern crate bitcoin_hashes; +extern crate lightning; +extern crate secp256k1; + +use bitcoin_hashes::sha256d::Hash as Sha256dHash; +use bitcoin::blockdata::script::{Script, Builder}; + +use lightning::chain::chaininterface::{ChainError,ChainWatchInterface, ChainListener}; +use lightning::ln::channelmanager::ChannelDetails; +use lightning::ln::msgs; +use lightning::ln::msgs::{RoutingMessageHandler}; +use lightning::ln::router::{Router, RouteHint}; +use lightning::util::logger::Logger; +use lightning::util::ser::Readable; + +use secp256k1::key::PublicKey; + +mod utils; + +use utils::test_logger; + +use std::sync::{Weak, Arc}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[inline] +pub fn slice_to_be16(v: &[u8]) -> u16 { + ((v[0] as u16) << 8*1) | + ((v[1] as u16) << 8*0) +} + +#[inline] +pub fn slice_to_be32(v: &[u8]) -> u32 { + ((v[0] as u32) << 8*3) | + ((v[1] as u32) << 8*2) | + ((v[2] as u32) << 8*1) | + ((v[3] as u32) << 8*0) +} + +#[inline] +pub fn slice_to_be64(v: &[u8]) -> u64 { + ((v[0] as u64) << 8*7) | + ((v[1] as u64) << 8*6) | + ((v[2] as u64) << 8*5) | + ((v[3] as u64) << 8*4) | + ((v[4] as u64) << 8*3) | + ((v[5] as u64) << 8*2) | + ((v[6] as u64) << 8*1) | + ((v[7] as u64) << 8*0) +} + + +struct InputData { + data: Vec, + read_pos: AtomicUsize, +} +impl InputData { + fn get_slice(&self, len: usize) -> Option<&[u8]> { + let old_pos = self.read_pos.fetch_add(len, Ordering::AcqRel); + if self.data.len() < old_pos + len { + return None; + } + Some(&self.data[old_pos..old_pos + len]) + } + fn get_slice_nonadvancing(&self, len: usize) -> Option<&[u8]> { + let old_pos = self.read_pos.load(Ordering::Acquire); + if self.data.len() < old_pos + len { + return None; + } + Some(&self.data[old_pos..old_pos + len]) + } +} + +struct DummyChainWatcher { + 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 register_listener(&self, _listener: Weak) { } + + fn get_chain_utxo(&self, _genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> { + 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), + _ => unreachable!(), + } + } +} + +#[inline] +pub fn do_test(data: &[u8]) { + let input = Arc::new(InputData { + data: data.to_vec(), + read_pos: AtomicUsize::new(0), + }); + macro_rules! get_slice_nonadvancing { + ($len: expr) => { + match input.get_slice_nonadvancing($len as usize) { + Some(slice) => slice, + None => return, + } + } + } + macro_rules! get_slice { + ($len: expr) => { + match input.get_slice($len as usize) { + Some(slice) => slice, + None => return, + } + } + } + + macro_rules! decode_msg { + ($MsgType: path, $len: expr) => {{ + let mut reader = ::std::io::Cursor::new(get_slice!($len)); + 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)), + } + } + }} + } + + macro_rules! decode_msg_with_len16 { + ($MsgType: path, $begin_len: expr, $excess: expr) => { + { + let extra_len = slice_to_be16(&get_slice_nonadvancing!($begin_len as usize + 2)[$begin_len..$begin_len + 2]); + decode_msg!($MsgType, $begin_len as usize + 2 + (extra_len as usize) + $excess) + } + } + } + + macro_rules! get_pubkey { + () => { + match PublicKey::from_slice(get_slice!(33)) { + Ok(key) => key, + Err(_) => return, + } + } + } + + let logger: Arc = Arc::new(test_logger::TestLogger::new("".to_owned())); + let chain_monitor = Arc::new(DummyChainWatcher { + input: Arc::clone(&input), + }); + + let our_pubkey = get_pubkey!(); + let router = Router::new(our_pubkey.clone(), chain_monitor, Arc::clone(&logger)); + + loop { + match get_slice!(1)[0] { + 0 => { + let start_len = slice_to_be16(&get_slice_nonadvancing!(64 + 2)[64..64 + 2]) as usize; + let addr_len = slice_to_be16(&get_slice_nonadvancing!(64+start_len+2 + 74)[64+start_len+2 + 72..64+start_len+2 + 74]); + if addr_len > (37+1)*4 { + return; + } + let _ = router.handle_node_announcement(&decode_msg_with_len16!(msgs::NodeAnnouncement, 64, 288)); + }, + 1 => { + let _ = router.handle_channel_announcement(&decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4)); + }, + 2 => { + let _ = router.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 128)); + }, + 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, + } + }, + 4 => { + let target = get_pubkey!(); + 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)); + for _ in 0..count { + first_hops_vec.push(ChannelDetails { + channel_id: [0; 32], + short_channel_id: Some(slice_to_be64(get_slice!(8))), + remote_network_id: get_pubkey!(), + channel_value_satoshis: slice_to_be64(get_slice!(8)), + user_id: 0, + inbound_capacity_msat: 0, + is_live: true, + outbound_capacity_msat: 0, + }); + } + Some(&first_hops_vec[..]) + }, + _ => return, + }; + let mut last_hops_vec = Vec::new(); + let last_hops = { + let count = slice_to_be16(get_slice!(2)); + for _ in 0..count { + 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)), + 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))); + }, + _ => return, + } + } +} + +#[cfg(feature = "afl")] +#[macro_use] extern crate afl; +#[cfg(feature = "afl")] +fn main() { + fuzz!(|data| { + do_test(data); + }); +} + +#[cfg(feature = "honggfuzz")] +#[macro_use] extern crate honggfuzz; +#[cfg(feature = "honggfuzz")] +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +extern crate hex; +#[cfg(test)] +mod tests { + + #[test] + fn duplicate_crash() { + super::do_test(&::hex::decode("00").unwrap()); + } +} diff --git a/lightning/fuzz/fuzz_targets/utils/mod.rs b/lightning/fuzz/fuzz_targets/utils/mod.rs new file mode 100644 index 000000000..a7d7c32d5 --- /dev/null +++ b/lightning/fuzz/fuzz_targets/utils/mod.rs @@ -0,0 +1 @@ +pub(crate) mod test_logger; diff --git a/lightning/fuzz/fuzz_targets/utils/test_logger.rs b/lightning/fuzz/fuzz_targets/utils/test_logger.rs new file mode 100644 index 000000000..097d001db --- /dev/null +++ b/lightning/fuzz/fuzz_targets/utils/test_logger.rs @@ -0,0 +1,23 @@ +use lightning::util::logger::{Logger, Record}; +pub struct TestLogger { + #[cfg(test)] + id: String, +} + +impl TestLogger { + pub fn new(_id: String) -> TestLogger { + TestLogger { + #[cfg(test)] + id: _id + } + } +} + +impl Logger for TestLogger { + fn log(&self, record: &Record) { + #[cfg(test)] + println!("{:<5} {} [{} : {}, {}] {}", record.level.to_string(), self.id, record.module_path, record.file, record.line, record.args); + #[cfg(not(test))] + let _ = format!("{}", record.args); + } +} diff --git a/lightning/fuzz/travis-fuzz.sh b/lightning/fuzz/travis-fuzz.sh new file mode 100755 index 000000000..e602e9518 --- /dev/null +++ b/lightning/fuzz/travis-fuzz.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +pushd fuzz_targets/msg_targets +rm *_target.rs +./gen_target.sh +[ "$(git diff)" != "" ] && exit 1 +popd + +cargo install --force honggfuzz +for TARGET in fuzz_targets/*.rs fuzz_targets/msg_targets/*_target.rs; do + FILENAME=$(basename $TARGET) + FILE="${FILENAME%.*}" + HFUZZ_RUN_ARGS="--exit_upon_crash -v -n2" + if [ "$FILE" = "chanmon_fail_consistency" ]; then + HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -F 64 -N100000" + else + HFUZZ_RUN_ARGS="$HFUZZ_RUN_ARGS -N1000000" + fi + export HFUZZ_RUN_ARGS + HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" cargo hfuzz run $FILE + if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then + cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT + for CASE in hfuzz_workspace/$FILE/SIG*; do + cat $CASE | xxd -p + done + exit 1 + fi +done diff --git a/lightning/src/chain/chaininterface.rs b/lightning/src/chain/chaininterface.rs new file mode 100644 index 000000000..c0330fb29 --- /dev/null +++ b/lightning/src/chain/chaininterface.rs @@ -0,0 +1,321 @@ +//! Traits and utility impls which allow other parts of rust-lightning to interact with the +//! blockchain. +//! +//! Includes traits for monitoring and receiving notifications of new blocks and block +//! disconnections, transaction broadcasting, and feerate information requests. + +use bitcoin::blockdata::block::{Block, BlockHeader}; +use bitcoin::blockdata::transaction::Transaction; +use bitcoin::blockdata::script::Script; +use bitcoin::blockdata::constants::genesis_block; +use bitcoin::util::hash::BitcoinHash; +use bitcoin_hashes::sha256d::Hash as Sha256dHash; +use bitcoin::network::constants::Network; + +use util::logger::Logger; + +use std::sync::{Mutex,Weak,MutexGuard,Arc}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::collections::HashSet; + +/// Used to give chain error details upstream +pub enum ChainError { + /// Client doesn't support UTXO lookup (but the chain hash matches our genesis block hash) + NotSupported, + /// Chain isn't the one watched + NotWatched, + /// Tx doesn't exist or is unconfirmed + UnknownTx, +} + +/// An interface to request notification of certain scripts as they appear the +/// chain. +/// +/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're +/// called from inside the library in response to ChainListener events, P2P events, or timer +/// events). +pub trait ChainWatchInterface: Sync + Send { + /// Provides a txid/random-scriptPubKey-in-the-tx which much be watched for. + fn install_watch_tx(&self, txid: &Sha256dHash, script_pub_key: &Script); + + /// Provides an outpoint which must be watched for, providing any transactions which spend the + /// given outpoint. + fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32), out_script: &Script); + + /// Indicates that a listener needs to see all transactions. + fn watch_all_txn(&self); + + /// Register the given listener to receive events. Only a weak pointer is provided and the + /// registration should be freed once that pointer expires. + fn register_listener(&self, listener: Weak); + //TODO: unregister + + /// Gets the script and value in satoshis for a given unspent transaction output given a + /// short_channel_id (aka unspent_tx_output_identier). For BTC/tBTC channels the top three + /// bytes are the block height, the next 3 the transaction index within the block, and the + /// final two the output within the transaction. + fn get_chain_utxo(&self, genesis_hash: Sha256dHash, unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError>; +} + +/// An interface to send a transaction to the Bitcoin network. +pub trait BroadcasterInterface: Sync + Send { + /// Sends a transaction out to (hopefully) be mined. + fn broadcast_transaction(&self, tx: &Transaction); +} + +/// A trait indicating a desire to listen for events from the chain +pub trait ChainListener: Sync + Send { + /// Notifies a listener that a block was connected. + /// Note that if a new transaction/outpoint is watched during a block_connected call, the block + /// *must* be re-scanned with the new transaction/outpoints and block_connected should be + /// called again with the same header and (at least) the new transactions. + /// + /// Note that if non-new transaction/outpoints may be registered during a call, a second call + /// *must not* happen. + /// + /// This also means those counting confirmations using block_connected callbacks should watch + /// for duplicate headers and not count them towards confirmations! + fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]); + /// Notifies a listener that a block was disconnected. + /// Unlike block_connected, this *must* never be called twice for the same disconnect event. + /// Height must be the one of the block which was disconnected (not new height of the best chain) + fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32); +} + +/// An enum that represents the speed at which we want a transaction to confirm used for feerate +/// estimation. +pub enum ConfirmationTarget { + /// We are happy with this transaction confirming slowly when feerate drops some. + Background, + /// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine. + Normal, + /// We'd like this transaction to confirm in the next few blocks. + HighPriority, +} + +/// A trait which should be implemented to provide feerate information on a number of time +/// horizons. +/// +/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're +/// called from inside the library in response to ChainListener events, P2P events, or timer +/// events). +pub trait FeeEstimator: Sync + Send { + /// Gets estimated satoshis of fee required per 1000 Weight-Units. + /// + /// Must be no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later round-downs + /// don't put us below 1 satoshi-per-byte). + /// + /// This translates to: + /// * satoshis-per-byte * 250 + /// * ceil(satoshis-per-kbyte / 4) + fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u64; +} + +/// Utility for tracking registered txn/outpoints and checking for matches +pub struct ChainWatchedUtil { + watch_all: bool, + + // We are more conservative in matching during testing to ensure everything matches *exactly*, + // even though during normal runtime we take more optimized match approaches... + #[cfg(test)] + watched_txn: HashSet<(Sha256dHash, Script)>, + #[cfg(not(test))] + watched_txn: HashSet