Merge pull request #401 from ariard/2019-11-log-tx-broadcast
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Mon, 25 Nov 2019 22:39:48 +0000 (22:39 +0000)
committerGitHub <noreply@github.com>
Mon, 25 Nov 2019 22:39:48 +0000 (22:39 +0000)
Add log for every tx broadcast

83 files changed:
.travis.yml
fuzz/.gitignore [new file with mode: 0644]
fuzz/Cargo.toml [new file with mode: 0644]
fuzz/fuzz_targets/chanmon_deser_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/chanmon_fail_consistency.rs [new file with mode: 0644]
fuzz/fuzz_targets/full_stack_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/gen_target.sh [new file with mode: 0755]
fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_init_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_ping_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_pong_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_target_template.txt [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/msg_targets/utils.rs [new file with mode: 0644]
fuzz/fuzz_targets/peer_crypt_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/router_target.rs [new file with mode: 0644]
fuzz/fuzz_targets/utils/mod.rs [new file with mode: 0644]
fuzz/fuzz_targets/utils/test_logger.rs [new file with mode: 0644]
fuzz/travis-fuzz.sh [new file with mode: 0755]
lightning/fuzz/.gitignore [deleted file]
lightning/fuzz/Cargo.toml [deleted file]
lightning/fuzz/fuzz_targets/chanmon_deser_target.rs [deleted file]
lightning/fuzz/fuzz_targets/chanmon_fail_consistency.rs [deleted file]
lightning/fuzz/fuzz_targets/full_stack_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/gen_target.sh [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_decoded_onion_error_packet_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs [deleted file]
lightning/fuzz/fuzz_targets/msg_targets/utils.rs [deleted file]
lightning/fuzz/fuzz_targets/peer_crypt_target.rs [deleted file]
lightning/fuzz/fuzz_targets/router_target.rs [deleted file]
lightning/fuzz/fuzz_targets/utils/mod.rs [deleted file]
lightning/fuzz/fuzz_targets/utils/test_logger.rs [deleted file]
lightning/fuzz/travis-fuzz.sh [deleted file]
lightning/src/chain/chaininterface.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/channelmonitor.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs

index 9c9257855cd33c6fefd13385a885a0eec0c4eee4..308c8d634d72debda99c692e549f8446a9c5a48f 100644 (file)
@@ -21,7 +21,7 @@ script:
      # Test lightning workspace for 1.22.0
      - if [ "$(rustup show | grep default | grep 1.22.0)" != "" ]; then RUSTFLAGS="-C link-dead-code" cargo test --verbose -p lightning; fi
      # Run lightning workspace fuzz tests for Rust 1.34.2
-     - 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 1.34.2)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; 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/fuzz/.gitignore b/fuzz/.gitignore
new file mode 100644 (file)
index 0000000..8bf27ec
--- /dev/null
@@ -0,0 +1,3 @@
+hfuzz_target
+target
+hfuzz_workspace
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
new file mode 100644 (file)
index 0000000..96699a7
--- /dev/null
@@ -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 = "../lightning", 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
new file mode 100644 (file)
index 0000000..f741832
--- /dev/null
@@ -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<u8>);
+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
new file mode 100644 (file)
index 0000000..459fca4
--- /dev/null
@@ -0,0 +1,781 @@
+//! 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, LightningError, 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<u8>);
+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<channelmonitor::SimpleManyChannelMonitor<OutPoint>>,
+       pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
+       pub latest_good_update: Mutex<HashMap<OutPoint, Vec<u8>>>,
+       pub latest_update_good: Mutex<HashMap<OutPoint, bool>>,
+       pub latest_updates_good_at_last_ser: Mutex<HashMap<OutPoint, bool>>,
+       pub should_update_manager: atomic::AtomicBool,
+}
+impl TestChannelMonitor {
+       pub fn new(chain_monitor: Arc<chaininterface::ChainWatchInterface>, broadcaster: Arc<chaininterface::BroadcasterInterface>, logger: Arc<Logger>, feeest: Arc<chaininterface::FeeEstimator>) -> 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<HTLCUpdate> {
+               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<Logger> = 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(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).unwrap(),
+                       monitor)
+               } }
+       }
+
+       macro_rules! reload_node {
+               ($ser: expr, $node_id: expr, $old_monitors: expr) => { {
+                       let logger: Arc<Logger> = 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(),
+                               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(LightningError { action: 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), 5_000_000));
+                                                               }
+                                                       }
+                                               },
+                                               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
new file mode 100644 (file)
index 0000000..cd65a2f
--- /dev/null
@@ -0,0 +1,891 @@
+//! 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<u8>,
+       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<InputData>,
+}
+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<H : std::hash::Hasher>(&self, h: &mut H) {
+               self.id.hash(h)
+       }
+}
+
+struct MoneyLossDetector<'a, 'b> {
+       manager: Arc<ChannelManager<'b>>,
+       monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>,
+       handler: PeerManager<Peer<'a>>,
+
+       peers: &'a RefCell<[bool; 256]>,
+       funding_txn: Vec<Transaction>,
+       txids_confirmed: HashMap<Sha256dHash, usize>,
+       header_hashes: Vec<Sha256dHash>,
+       height: usize,
+       max_height: usize,
+       blocks_connected: u32,
+}
+impl<'a, 'b> MoneyLossDetector<'a, 'b> {
+       pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc<ChannelManager<'b>>, monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>, handler: PeerManager<Peer<'a>>) -> 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, 'b> Drop for MoneyLossDetector<'a, 'b> {
+       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 = <Hash160 as bitcoin_hashes::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<Logger>) {
+       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(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0).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<(PaymentHash, u64)> = 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, amt) 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, amt);
+                                       }
+                               }
+                       },
+                       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<Transaction, _> = 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, amt } => {
+                                       //TODO: enhance by fetching random amounts from fuzz input?
+                                       payments_received.push((payment_hash, amt));
+                               },
+                               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<Logger> = 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<Logger> = 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<Logger> = 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<Logger> = Arc::new(test_logger::TestLogger::new("".to_owned()));
+               super::do_test(&::hex::decode("00").unwrap(), &logger);
+       }
+
+       struct TrackingLogger {
+               /// (module, message) -> count
+               pub lines: Mutex<HashMap<(String, String), usize>>,
+       }
+       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<Logger>));
+
+               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
new file mode 100755 (executable)
index 0000000..cfd100f
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs
new file mode 100644 (file)
index 0000000..0f18d02
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs b/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs
new file mode 100644 (file)
index 0000000..226028e
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs
new file mode 100644 (file)
index 0000000..0bdc10e
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs
new file mode 100644 (file)
index 0000000..4af5937
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs b/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs
new file mode 100644 (file)
index 0000000..724dca4
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs
new file mode 100644 (file)
index 0000000..faeeae3
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs
new file mode 100644 (file)
index 0000000..97c4b30
--- /dev/null
@@ -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/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
new file mode 100644 (file)
index 0000000..9b190b0
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs b/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs
new file mode 100644 (file)
index 0000000..d749dc9
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs
new file mode 100644 (file)
index 0000000..45b257b
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs
new file mode 100644 (file)
index 0000000..cd1e897
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs
new file mode 100644 (file)
index 0000000..5992d69
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_init_target.rs b/fuzz/fuzz_targets/msg_targets/msg_init_target.rs
new file mode 100644 (file)
index 0000000..cdca848
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs b/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs
new file mode 100644 (file)
index 0000000..f0a7a4c
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs b/fuzz/fuzz_targets/msg_targets/msg_onion_hop_data_target.rs
new file mode 100644 (file)
index 0000000..058c050
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs
new file mode 100644 (file)
index 0000000..aa13e96
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs b/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs
new file mode 100644 (file)
index 0000000..d2ea913
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs b/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs
new file mode 100644 (file)
index 0000000..18120e2
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs b/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs
new file mode 100644 (file)
index 0000000..d82268d
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs b/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs
new file mode 100644 (file)
index 0000000..34d4d20
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_target_template.txt b/fuzz/fuzz_targets/msg_targets/msg_target_template.txt
new file mode 100644 (file)
index 0000000..2704bcd
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs
new file mode 100644 (file)
index 0000000..e64a5c2
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs
new file mode 100644 (file)
index 0000000..fedce56
--- /dev/null
@@ -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/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
new file mode 100644 (file)
index 0000000..377378f
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs
new file mode 100644 (file)
index 0000000..56b9ac4
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs
new file mode 100644 (file)
index 0000000..f0c936d
--- /dev/null
@@ -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/fuzz/fuzz_targets/msg_targets/utils.rs b/fuzz/fuzz_targets/msg_targets/utils.rs
new file mode 100644 (file)
index 0000000..a5257ba
--- /dev/null
@@ -0,0 +1,81 @@
+#![macro_use]
+
+use lightning::util::ser::Writer;
+pub struct VecWriter(pub Vec<u8>);
+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
new file mode 100644 (file)
index 0000000..0b82303
--- /dev/null
@@ -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/fuzz/fuzz_targets/router_target.rs b/fuzz/fuzz_targets/router_target.rs
new file mode 100644 (file)
index 0000000..d9a8f78
--- /dev/null
@@ -0,0 +1,269 @@
+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 bitcoin::blockdata::block::Block;
+use bitcoin::blockdata::transaction::Transaction;
+
+use lightning::chain::chaininterface::{ChainError,ChainWatchInterface};
+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::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<u8>,
+       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<InputData>,
+}
+
+impl ChainWatchInterface for DummyChainWatcher {
+       fn install_watch_tx(&self, _txid: &Sha256dHash, _script_pub_key: &Script) { }
+       fn install_watch_outpoint(&self, _outpoint: (Sha256dHash, u32), _out_script: &Script) { }
+       fn watch_all_txn(&self) { }
+       fn filter_block<'a>(&self, _block: &'a Block) -> (Vec<&'a Transaction>, Vec<u32>) {
+               (Vec::new(), Vec::new())
+       }
+       fn reentered(&self) -> usize { 0 }
+
+       fn get_chain_utxo(&self, _genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
+               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<Logger> = 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
new file mode 100644 (file)
index 0000000..a7d7c32
--- /dev/null
@@ -0,0 +1 @@
+pub(crate) mod test_logger;
diff --git a/fuzz/fuzz_targets/utils/test_logger.rs b/fuzz/fuzz_targets/utils/test_logger.rs
new file mode 100644 (file)
index 0000000..097d001
--- /dev/null
@@ -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/fuzz/travis-fuzz.sh b/fuzz/travis-fuzz.sh
new file mode 100755 (executable)
index 0000000..e602e95
--- /dev/null
@@ -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/fuzz/.gitignore b/lightning/fuzz/.gitignore
deleted file mode 100644 (file)
index 8bf27ec..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-hfuzz_target
-target
-hfuzz_workspace
diff --git a/lightning/fuzz/Cargo.toml b/lightning/fuzz/Cargo.toml
deleted file mode 100644 (file)
index 19d832e..0000000
+++ /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/lightning/fuzz/fuzz_targets/chanmon_deser_target.rs b/lightning/fuzz/fuzz_targets/chanmon_deser_target.rs
deleted file mode 100644 (file)
index f741832..0000000
+++ /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<u8>);
-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
deleted file mode 100644 (file)
index 74b1e5d..0000000
+++ /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, LightningError, 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<u8>);
-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<channelmonitor::SimpleManyChannelMonitor<OutPoint>>,
-       pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
-       pub latest_good_update: Mutex<HashMap<OutPoint, Vec<u8>>>,
-       pub latest_update_good: Mutex<HashMap<OutPoint, bool>>,
-       pub latest_updates_good_at_last_ser: Mutex<HashMap<OutPoint, bool>>,
-       pub should_update_manager: atomic::AtomicBool,
-}
-impl TestChannelMonitor {
-       pub fn new(chain_monitor: Arc<chaininterface::ChainWatchInterface>, broadcaster: Arc<chaininterface::BroadcasterInterface>, logger: Arc<Logger>, feeest: Arc<chaininterface::FeeEstimator>) -> 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<HTLCUpdate> {
-               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<Logger> = 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, 0).unwrap(),
-                       monitor)
-               } }
-       }
-
-       macro_rules! reload_node {
-               ($ser: expr, $node_id: expr, $old_monitors: expr) => { {
-                       let logger: Arc<Logger> = 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(LightningError { action: 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), 5_000_000));
-                                                               }
-                                                       }
-                                               },
-                                               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
deleted file mode 100644 (file)
index 41ab473..0000000
+++ /dev/null
@@ -1,891 +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<u8>,
-       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<InputData>,
-}
-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<H : std::hash::Hasher>(&self, h: &mut H) {
-               self.id.hash(h)
-       }
-}
-
-struct MoneyLossDetector<'a> {
-       manager: Arc<ChannelManager>,
-       monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>,
-       handler: PeerManager<Peer<'a>>,
-
-       peers: &'a RefCell<[bool; 256]>,
-       funding_txn: Vec<Transaction>,
-       txids_confirmed: HashMap<Sha256dHash, usize>,
-       header_hashes: Vec<Sha256dHash>,
-       height: usize,
-       max_height: usize,
-       blocks_connected: u32,
-}
-impl<'a> MoneyLossDetector<'a> {
-       pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc<ChannelManager>, monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>, handler: PeerManager<Peer<'a>>) -> 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 = <Hash160 as bitcoin_hashes::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<Logger>) {
-       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, 0).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<(PaymentHash, u64)> = 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, amt) 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, amt);
-                                       }
-                               }
-                       },
-                       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<Transaction, _> = 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, amt } => {
-                                       //TODO: enhance by fetching random amounts from fuzz input?
-                                       payments_received.push((payment_hash, amt));
-                               },
-                               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<Logger> = 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<Logger> = 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<Logger> = 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<Logger> = Arc::new(test_logger::TestLogger::new("".to_owned()));
-               super::do_test(&::hex::decode("00").unwrap(), &logger);
-       }
-
-       struct TrackingLogger {
-               /// (module, message) -> count
-               pub lines: Mutex<HashMap<(String, String), usize>>,
-       }
-       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<Logger>));
-
-               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
deleted file mode 100755 (executable)
index cfd100f..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs
deleted file mode 100644 (file)
index 0f18d02..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_announcement_signatures_target.rs
deleted file mode 100644 (file)
index 226028e..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_announcement_target.rs
deleted file mode 100644 (file)
index 0bdc10e..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_reestablish_target.rs
deleted file mode 100644 (file)
index 4af5937..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_channel_update_target.rs
deleted file mode 100644 (file)
index 724dca4..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs
deleted file mode 100644 (file)
index faeeae3..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs
deleted file mode 100644 (file)
index 97c4b30..0000000
+++ /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/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
deleted file mode 100644 (file)
index 9b190b0..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_error_message_target.rs
deleted file mode 100644 (file)
index d749dc9..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs
deleted file mode 100644 (file)
index 45b257b..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs
deleted file mode 100644 (file)
index cd1e897..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs
deleted file mode 100644 (file)
index 5992d69..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_init_target.rs
deleted file mode 100644 (file)
index cdca848..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_node_announcement_target.rs
deleted file mode 100644 (file)
index f0a7a4c..0000000
+++ /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/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
deleted file mode 100644 (file)
index 058c050..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs
deleted file mode 100644 (file)
index aa13e96..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_ping_target.rs
deleted file mode 100644 (file)
index d2ea913..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_pong_target.rs
deleted file mode 100644 (file)
index 18120e2..0000000
+++ /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/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
deleted file mode 100644 (file)
index d82268d..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs
deleted file mode 100644 (file)
index 34d4d20..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt b/lightning/fuzz/fuzz_targets/msg_targets/msg_target_template.txt
deleted file mode 100644 (file)
index 2704bcd..0000000
+++ /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/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
deleted file mode 100644 (file)
index e64a5c2..0000000
+++ /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/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
deleted file mode 100644 (file)
index fedce56..0000000
+++ /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/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
deleted file mode 100644 (file)
index 377378f..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs b/lightning/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs
deleted file mode 100644 (file)
index 56b9ac4..0000000
+++ /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/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
deleted file mode 100644 (file)
index f0c936d..0000000
+++ /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/lightning/fuzz/fuzz_targets/msg_targets/utils.rs b/lightning/fuzz/fuzz_targets/msg_targets/utils.rs
deleted file mode 100644 (file)
index a5257ba..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#![macro_use]
-
-use lightning::util::ser::Writer;
-pub struct VecWriter(pub Vec<u8>);
-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
deleted file mode 100644 (file)
index 0b82303..0000000
+++ /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/lightning/fuzz/fuzz_targets/router_target.rs b/lightning/fuzz/fuzz_targets/router_target.rs
deleted file mode 100644 (file)
index 25bf382..0000000
+++ /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<u8>,
-       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<InputData>,
-}
-
-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<ChainListener>) { }
-
-       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<Logger> = 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
deleted file mode 100644 (file)
index a7d7c32..0000000
+++ /dev/null
@@ -1 +0,0 @@
-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
deleted file mode 100644 (file)
index 097d001..0000000
+++ /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/lightning/fuzz/travis-fuzz.sh b/lightning/fuzz/travis-fuzz.sh
deleted file mode 100755 (executable)
index e602e95..0000000
+++ /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
index c0330fb2963ea868d753c16dd633d5cbbd8890c9..92c9c102597b8546e6ca42f3272d5f0cb9e2289f 100644 (file)
@@ -45,16 +45,20 @@ pub trait ChainWatchInterface: Sync + Send {
        /// 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<ChainListener>);
-       //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>;
+
+       /// Gets the list of transactions and transaction indices that the ChainWatchInterface is
+       /// watching for.
+       fn filter_block<'a>(&self, block: &'a Block) -> (Vec<&'a Transaction>, Vec<u32>);
+
+       /// Returns a usize that changes when the ChainWatchInterface's watched data is modified.
+       /// Users of `filter_block` should pre-save a copy of `reentered`'s return value and use it to
+       /// determine whether they need to re-filter a given block.
+       fn reentered(&self) -> usize;
 }
 
 /// An interface to send a transaction to the Bitcoin network.
@@ -198,13 +202,81 @@ impl ChainWatchedUtil {
        }
 }
 
+/// Utility for notifying listeners about new blocks, and handling block rescans if new watch
+/// data is registered.
+pub struct BlockNotifier<'a> {
+       listeners: Mutex<Vec<Weak<ChainListener + 'a>>>, //TODO(vmw): try removing Weak
+       chain_monitor: Arc<ChainWatchInterface>,
+}
+
+impl<'a> BlockNotifier<'a> {
+       /// Constructs a new BlockNotifier without any listeners.
+       pub fn new(chain_monitor: Arc<ChainWatchInterface>) -> BlockNotifier<'a> {
+               BlockNotifier {
+                       listeners: Mutex::new(Vec::new()),
+                       chain_monitor,
+               }
+       }
+
+       /// Register the given listener to receive events. Only a weak pointer is provided and
+       /// the registration should be freed once that pointer expires.
+       // TODO: unregister
+       pub fn register_listener(&self, listener: Weak<ChainListener + 'a>) {
+               let mut vec = self.listeners.lock().unwrap();
+               vec.push(listener);
+       }
+
+       /// Notify listeners that a block was connected given a full, unfiltered block.
+       ///
+       /// Handles re-scanning the block and calling block_connected again if listeners register new
+       /// watch data during the callbacks for you (see ChainListener::block_connected for more info).
+       pub fn block_connected<'b>(&self, block: &'b Block, height: u32) {
+               let mut reentered = true;
+               while reentered {
+                       let (matched, matched_index) = self.chain_monitor.filter_block(block);
+                       reentered = self.block_connected_checked(&block.header, height, matched.as_slice(), matched_index.as_slice());
+               }
+       }
+
+       /// Notify listeners that a block was connected, given pre-filtered list of transactions in the
+       /// block which matched the filter (probably using does_match_tx).
+       ///
+       /// Returns true if notified listeners registered additional watch data (implying that the
+       /// block must be re-scanned and this function called again prior to further block_connected
+       /// calls, see ChainListener::block_connected for more info).
+       pub fn block_connected_checked(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> bool {
+               let last_seen = self.chain_monitor.reentered();
+
+               let listeners = self.listeners.lock().unwrap().clone();
+               for listener in listeners.iter() {
+                       match listener.upgrade() {
+                               Some(arc) => arc.block_connected(header, height, txn_matched, indexes_of_txn_matched),
+                               None => ()
+                       }
+               }
+               return last_seen != self.chain_monitor.reentered();
+       }
+
+
+       /// Notify listeners that a block was disconnected.
+       pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
+               let listeners = self.listeners.lock().unwrap().clone();
+               for listener in listeners.iter() {
+                       match listener.upgrade() {
+                               Some(arc) => arc.block_disconnected(&header, disconnected_height),
+                               None => ()
+                       }
+               }
+       }
+
+}
+
 /// Utility to capture some common parts of ChainWatchInterface implementors.
 ///
 /// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
 pub struct ChainWatchInterfaceUtil {
        network: Network,
        watched: Mutex<ChainWatchedUtil>,
-       listeners: Mutex<Vec<Weak<ChainListener>>>,
        reentered: AtomicUsize,
        logger: Arc<Logger>,
 }
@@ -232,17 +304,31 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
                }
        }
 
-       fn register_listener(&self, listener: Weak<ChainListener>) {
-               let mut vec = self.listeners.lock().unwrap();
-               vec.push(listener);
-       }
-
        fn get_chain_utxo(&self, genesis_hash: Sha256dHash, _unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError> {
                if genesis_hash != genesis_block(self.network).header.bitcoin_hash() {
                        return Err(ChainError::NotWatched);
                }
                Err(ChainError::NotSupported)
        }
+
+       fn filter_block<'a>(&self, block: &'a Block) -> (Vec<&'a Transaction>, Vec<u32>) {
+               let mut matched = Vec::new();
+               let mut matched_index = Vec::new();
+               {
+                       let watched = self.watched.lock().unwrap();
+                       for (index, transaction) in block.txdata.iter().enumerate() {
+                               if self.does_match_tx_unguarded(transaction, &watched) {
+                                       matched.push(transaction);
+                                       matched_index.push(index as u32);
+                               }
+                       }
+               }
+               (matched, matched_index)
+       }
+
+       fn reentered(&self) -> usize {
+               self.reentered.load(Ordering::Relaxed)
+       }
 }
 
 impl ChainWatchInterfaceUtil {
@@ -251,63 +337,11 @@ impl ChainWatchInterfaceUtil {
                ChainWatchInterfaceUtil {
                        network: network,
                        watched: Mutex::new(ChainWatchedUtil::new()),
-                       listeners: Mutex::new(Vec::new()),
                        reentered: AtomicUsize::new(1),
                        logger: logger,
                }
        }
 
-       /// Notify listeners that a block was connected given a full, unfiltered block.
-       ///
-       /// Handles re-scanning the block and calling block_connected again if listeners register new
-       /// watch data during the callbacks for you (see ChainListener::block_connected for more info).
-       pub fn block_connected_with_filtering(&self, block: &Block, height: u32) {
-               let mut reentered = true;
-               while reentered {
-                       let mut matched = Vec::new();
-                       let mut matched_index = Vec::new();
-                       {
-                               let watched = self.watched.lock().unwrap();
-                               for (index, transaction) in block.txdata.iter().enumerate() {
-                                       if self.does_match_tx_unguarded(transaction, &watched) {
-                                               matched.push(transaction);
-                                               matched_index.push(index as u32);
-                                       }
-                               }
-                       }
-                       reentered = self.block_connected_checked(&block.header, height, matched.as_slice(), matched_index.as_slice());
-               }
-       }
-
-       /// Notify listeners that a block was disconnected.
-       pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
-               let listeners = self.listeners.lock().unwrap().clone();
-               for listener in listeners.iter() {
-                       match listener.upgrade() {
-                               Some(arc) => arc.block_disconnected(&header, disconnected_height),
-                               None => ()
-                       }
-               }
-       }
-
-       /// Notify listeners that a block was connected, given pre-filtered list of transactions in the
-       /// block which matched the filter (probably using does_match_tx).
-       ///
-       /// Returns true if notified listeners registered additional watch data (implying that the
-       /// block must be re-scanned and this function called again prior to further block_connected
-       /// calls, see ChainListener::block_connected for more info).
-       pub fn block_connected_checked(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> bool {
-               let last_seen = self.reentered.load(Ordering::Relaxed);
-
-               let listeners = self.listeners.lock().unwrap().clone();
-               for listener in listeners.iter() {
-                       match listener.upgrade() {
-                               Some(arc) => arc.block_connected(header, height, txn_matched, indexes_of_txn_matched),
-                               None => ()
-                       }
-               }
-               return last_seen != self.reentered.load(Ordering::Relaxed);
-       }
 
        /// Checks if a given transaction matches the current filter.
        pub fn does_match_tx(&self, tx: &Transaction) -> bool {
index c1fe6fbdd6d7c54002d31f277481a200f5cb5b7b..205f1a4bd34fe23bd94ffe36a58b4dd609bceb39 100644 (file)
@@ -1627,11 +1627,11 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails:
        };
 
        if confirm_a_first {
-               confirm_transaction(&nodes[0].chain_monitor, &funding_tx, funding_tx.version);
+               confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &funding_tx, funding_tx.version);
                nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id())).unwrap();
        } else {
                assert!(!restore_b_before_conf);
-               confirm_transaction(&nodes[1].chain_monitor, &funding_tx, funding_tx.version);
+               confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
                assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        }
 
@@ -1643,7 +1643,7 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails:
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 
        if !restore_b_before_conf {
-               confirm_transaction(&nodes[1].chain_monitor, &funding_tx, funding_tx.version);
+               confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
                assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
                assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
        }
@@ -1655,12 +1655,12 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails:
        let (channel_id, (announcement, as_update, bs_update)) = if !confirm_a_first {
                nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[0].node.get_our_node_id())).unwrap();
 
-               confirm_transaction(&nodes[0].chain_monitor, &funding_tx, funding_tx.version);
+               confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &funding_tx, funding_tx.version);
                let (funding_locked, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[1], &nodes[0]);
                (channel_id, create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked))
        } else {
                if restore_b_before_conf {
-                       confirm_transaction(&nodes[1].chain_monitor, &funding_tx, funding_tx.version);
+                       confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &funding_tx, funding_tx.version);
                }
                let (funding_locked, channel_id) = create_chan_between_nodes_with_value_confirm_second(&nodes[0], &nodes[1]);
                (channel_id, create_chan_between_nodes_with_value_b(&nodes[1], &nodes[0], &funding_locked))
index 0522ce0a719820f2448aa3803df4efb2457e607f..33f9441cf6c17e80edadbc12060ef3b851618ede 100644 (file)
@@ -25,7 +25,7 @@ use secp256k1::Secp256k1;
 use secp256k1::ecdh::SharedSecret;
 use secp256k1;
 
-use chain::chaininterface::{BroadcasterInterface,ChainListener,ChainWatchInterface,FeeEstimator};
+use chain::chaininterface::{BroadcasterInterface,ChainListener,FeeEstimator};
 use chain::transaction::OutPoint;
 use ln::channel::{Channel, ChannelError};
 use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, ManyChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
@@ -318,12 +318,11 @@ const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assum
 /// the "reorg path" (ie call block_disconnected() until you get to a common block and then call
 /// block_connected() to step towards your best block) upon deserialization before using the
 /// object!
-pub struct ChannelManager {
+pub struct ChannelManager<'a> {
        default_configuration: UserConfig,
        genesis_hash: Sha256dHash,
        fee_estimator: Arc<FeeEstimator>,
-       monitor: Arc<ManyChannelMonitor>,
-       chain_monitor: Arc<ChainWatchInterface>,
+       monitor: Arc<ManyChannelMonitor + 'a>,
        tx_broadcaster: Arc<BroadcasterInterface>,
 
        #[cfg(test)]
@@ -576,7 +575,7 @@ macro_rules! maybe_break_monitor_err {
        }
 }
 
-impl ChannelManager {
+impl<'a> ChannelManager<'a> {
        /// Constructs a new ChannelManager to hold several channels and route between them.
        ///
        /// This is the main "logic hub" for all channel-related actions, and implements
@@ -586,9 +585,16 @@ impl ChannelManager {
        ///
        /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
        ///
-       /// User must provide the current blockchain height from which to track onchain channel
+       /// Users must provide the current blockchain height from which to track onchain channel
        /// funding outpoints and send payments with reliable timelocks.
-       pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface>, config: UserConfig, current_blockchain_height: usize) -> Result<Arc<ChannelManager>, secp256k1::Error> {
+       ///
+       /// Users need to notify the new ChannelManager when a new block is connected or
+       /// disconnected using its `block_connected` and `block_disconnected` methods.
+       /// However, rather than calling these methods directly, the user should register
+       /// the ChannelManager as a listener to the BlockNotifier and call the BlockNotifier's
+       /// `block_(dis)connected` methods, which will notify all registered listeners in one
+       /// go.
+       pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor + 'a>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface>, config: UserConfig, current_blockchain_height: usize) -> Result<Arc<ChannelManager<'a>>, secp256k1::Error> {
                let secp_ctx = Secp256k1::new();
 
                let res = Arc::new(ChannelManager {
@@ -596,7 +602,6 @@ impl ChannelManager {
                        genesis_hash: genesis_block(network).header.bitcoin_hash(),
                        fee_estimator: feeest.clone(),
                        monitor: monitor.clone(),
-                       chain_monitor,
                        tx_broadcaster,
 
                        latest_block_height: AtomicUsize::new(current_blockchain_height),
@@ -619,8 +624,7 @@ impl ChannelManager {
 
                        logger,
                });
-               let weak_res = Arc::downgrade(&res);
-               res.chain_monitor.register_listener(weak_res);
+
                Ok(res)
        }
 
@@ -1973,6 +1977,15 @@ impl ChannelManager {
                                }
                                try_chan_entry!(self, chan.get_mut().funding_locked(&msg), channel_state, chan);
                                if let Some(announcement_sigs) = self.get_announcement_sigs(chan.get()) {
+                                       // If we see locking block before receiving remote funding_locked, we broadcast our
+                                       // announcement_sigs at remote funding_locked reception. If we receive remote
+                                       // funding_locked before seeing locking block, we broadcast our announcement_sigs at locking
+                                       // block connection. We should guanrantee to broadcast announcement_sigs to our peer whatever
+                                       // the order of the events but our peer may not receive it due to disconnection. The specs
+                                       // lacking an acknowledgement for announcement_sigs we may have to re-send them at peer
+                                       // connection in the future if simultaneous misses by both peers due to network/hardware
+                                       // failures is an issue. Note, to achieve its goal, only one of the announcement_sigs needs
+                                       // to be received, from then sigs are going to be flood to the whole network.
                                        channel_state.pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
                                                node_id: their_node_id.clone(),
                                                msg: announcement_sigs,
@@ -2507,7 +2520,7 @@ impl ChannelManager {
        }
 }
 
-impl events::MessageSendEventsProvider for ChannelManager {
+impl<'a> events::MessageSendEventsProvider for ChannelManager<'a> {
        fn get_and_clear_pending_msg_events(&self) -> Vec<events::MessageSendEvent> {
                // TODO: Event release to users and serialization is currently race-y: it's very easy for a
                // user to serialize a ChannelManager with pending events in it and lose those events on
@@ -2532,7 +2545,7 @@ impl events::MessageSendEventsProvider for ChannelManager {
        }
 }
 
-impl events::EventsProvider for ChannelManager {
+impl<'a> events::EventsProvider for ChannelManager<'a> {
        fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
                // TODO: Event release to users and serialization is currently race-y: it's very easy for a
                // user to serialize a ChannelManager with pending events in it and lose those events on
@@ -2557,7 +2570,7 @@ impl events::EventsProvider for ChannelManager {
        }
 }
 
-impl ChainListener for ChannelManager {
+impl<'a> ChainListener for ChannelManager<'a> {
        fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
                let header_hash = header.bitcoin_hash();
                log_trace!(self, "Block {} at height {} connected with {} txn matched", header_hash, height, txn_matched.len());
@@ -2671,7 +2684,7 @@ impl ChainListener for ChannelManager {
        }
 }
 
-impl ChannelMessageHandler for ChannelManager {
+impl<'a> ChannelMessageHandler for ChannelManager<'a> {
        //TODO: Handle errors and close channel (or so)
        fn handle_open_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &msgs::OpenChannel) -> Result<(), LightningError> {
                let _ = self.total_consistency_lock.read().unwrap();
@@ -3056,7 +3069,7 @@ impl<R: ::std::io::Read> Readable<R> for HTLCForwardInfo {
        }
 }
 
-impl Writeable for ChannelManager {
+impl<'a> Writeable for ChannelManager<'a> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
                let _ = self.total_consistency_lock.write().unwrap();
 
@@ -3118,9 +3131,8 @@ impl Writeable for ChannelManager {
 /// 4) Reconnect blocks on your ChannelMonitors.
 /// 5) Move the ChannelMonitors into your local ManyChannelMonitor.
 /// 6) Disconnect/connect blocks on the ChannelManager.
-/// 7) Register the new ChannelManager with your ChainWatchInterface (this does not happen
-///    automatically as it does in ChannelManager::new()).
-pub struct ChannelManagerReadArgs<'a> {
+/// 7) Register the new ChannelManager with your ChainWatchInterface.
+pub struct ChannelManagerReadArgs<'a, 'b> {
        /// The keys provider which will give us relevant keys. Some keys will be loaded during
        /// deserialization.
        pub keys_manager: Arc<KeysInterface>,
@@ -3134,11 +3146,8 @@ pub struct ChannelManagerReadArgs<'a> {
        /// No calls to the ManyChannelMonitor will be made during deserialization. It is assumed that
        /// you have deserialized ChannelMonitors separately and will add them to your
        /// ManyChannelMonitor after deserializing this ChannelManager.
-       pub monitor: Arc<ManyChannelMonitor>,
-       /// The ChainWatchInterface for use in the ChannelManager in the future.
-       ///
-       /// No calls to the ChainWatchInterface will be made during deserialization.
-       pub chain_monitor: Arc<ChainWatchInterface>,
+       pub monitor: Arc<ManyChannelMonitor + 'b>,
+
        /// The BroadcasterInterface which will be used in the ChannelManager in the future and may be
        /// used to broadcast the latest local commitment transactions of channels which must be
        /// force-closed during deserialization.
@@ -3163,8 +3172,8 @@ pub struct ChannelManagerReadArgs<'a> {
        pub channel_monitors: &'a HashMap<OutPoint, &'a ChannelMonitor>,
 }
 
-impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (Sha256dHash, ChannelManager) {
-       fn read(reader: &mut R, args: ChannelManagerReadArgs<'a>) -> Result<Self, DecodeError> {
+impl<'a, 'b, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a, 'b>> for (Sha256dHash, ChannelManager<'b>) {
+       fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, 'b>) -> Result<Self, DecodeError> {
                let _ver: u8 = Readable::read(reader)?;
                let min_ver: u8 = Readable::read(reader)?;
                if min_ver > SERIALIZATION_VERSION {
@@ -3241,7 +3250,6 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
                        genesis_hash,
                        fee_estimator: args.fee_estimator,
                        monitor: args.monitor,
-                       chain_monitor: args.chain_monitor,
                        tx_broadcaster: args.tx_broadcaster,
 
                        latest_block_height: AtomicUsize::new(latest_block_height as usize),
index d3121c131cbce91616719f98e7d296b460209420..d619edcbcd98f7fd8a6c6c1c1e6c7f51a2f37194 100644 (file)
@@ -109,6 +109,12 @@ pub struct HTLCUpdate {
 /// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
 /// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
 /// which we have revoked, allowing our counterparty to claim all funds in the channel!
+///
+/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or
+/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather
+/// than calling these methods directly, the user should register implementors as listeners to the
+/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
+/// all registered listeners in one go.
 pub trait ManyChannelMonitor: Send + Sync {
        /// Adds or updates a monitor for the given `funding_txo`.
        ///
@@ -146,7 +152,8 @@ pub struct SimpleManyChannelMonitor<Key> {
        fee_estimator: Arc<FeeEstimator>
 }
 
-impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonitor<Key> {
+impl<'a, Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonitor<Key> {
+
        fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
                let block_hash = header.bitcoin_hash();
                let mut new_events: Vec<events::Event> = Vec::with_capacity(0);
@@ -223,8 +230,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key>
                        logger,
                        fee_estimator: feeest,
                });
-               let weak_res = Arc::downgrade(&res);
-               res.chain_monitor.register_listener(weak_res);
+
                res
        }
 
@@ -2138,14 +2144,14 @@ impl ChannelMonitor {
                                };
                                if funding_txo.is_none() || (prevout.txid == funding_txo.as_ref().unwrap().0.txid && prevout.vout == funding_txo.as_ref().unwrap().0.index as u32) {
                                        if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
-                                               let (remote_txn, new_outputs, mut spendable_output) = self.check_spend_remote_transaction(tx, height, fee_estimator);
+                                               let (remote_txn, new_outputs, mut spendable_output) = self.check_spend_remote_transaction(&tx, height, fee_estimator);
                                                txn = remote_txn;
                                                spendable_outputs.append(&mut spendable_output);
                                                if !new_outputs.1.is_empty() {
                                                        watch_outputs.push(new_outputs);
                                                }
                                                if txn.is_empty() {
-                                                       let (local_txn, mut spendable_output, new_outputs) = self.check_spend_local_transaction(tx, height);
+                                                       let (local_txn, mut spendable_output, new_outputs) = self.check_spend_local_transaction(&tx, height);
                                                        spendable_outputs.append(&mut spendable_output);
                                                        txn = local_txn;
                                                        if !new_outputs.1.is_empty() {
@@ -2154,13 +2160,13 @@ impl ChannelMonitor {
                                                }
                                        }
                                        if !funding_txo.is_none() && txn.is_empty() {
-                                               if let Some(spendable_output) = self.check_spend_closing_transaction(tx) {
+                                               if let Some(spendable_output) = self.check_spend_closing_transaction(&tx) {
                                                        spendable_outputs.push(spendable_output);
                                                }
                                        }
                                } else {
                                        if let Some(&(commitment_number, _)) = self.remote_commitment_txn_on_chain.get(&prevout.txid) {
-                                               let (tx, spendable_output) = self.check_spend_remote_htlc(tx, commitment_number, height, fee_estimator);
+                                               let (tx, spendable_output) = self.check_spend_remote_htlc(&tx, commitment_number, height, fee_estimator);
                                                if let Some(tx) = tx {
                                                        txn.push(tx);
                                                }
@@ -2177,7 +2183,7 @@ impl ChannelMonitor {
                        // While all commitment/HTLC-Success/HTLC-Timeout transactions have one input, HTLCs
                        // can also be resolved in a few other ways which can have more than one output. Thus,
                        // we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check.
-                       let mut updated = self.is_resolving_htlc_output(tx, height);
+                       let mut updated = self.is_resolving_htlc_output(&tx, height);
                        if updated.len() > 0 {
                                htlc_updated.append(&mut updated);
                        }
index 7e776227aeef3871294d3726b8606bf6feacc0f7..4c8f162bcf53dc41c982346ce4335222ce4e451f 100644 (file)
@@ -34,38 +34,39 @@ use std::sync::{Arc, Mutex};
 use std::mem;
 
 pub const CHAN_CONFIRM_DEPTH: u32 = 100;
-pub fn confirm_transaction(chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: u32) {
+pub fn confirm_transaction(notifier: &chaininterface::BlockNotifier, chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: u32) {
        assert!(chain.does_match_tx(tx));
        let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       chain.block_connected_checked(&header, 1, &[tx; 1], &[chan_id; 1]);
+       notifier.block_connected_checked(&header, 1, &[tx; 1], &[chan_id; 1]);
        for i in 2..CHAN_CONFIRM_DEPTH {
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               chain.block_connected_checked(&header, i, &[tx; 0], &[0; 0]);
+               notifier.block_connected_checked(&header, i, &vec![], &[0; 0]);
        }
 }
 
-pub fn connect_blocks(chain: &chaininterface::ChainWatchInterfaceUtil, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256d) -> Sha256d {
+pub fn connect_blocks(notifier: &chaininterface::BlockNotifier, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256d) -> Sha256d {
        let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       chain.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new());
+       notifier.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new());
        for i in 2..depth + 1 {
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               chain.block_connected_checked(&header, height + i, &Vec::new(), &Vec::new());
+               notifier.block_connected_checked(&header, height + i, &Vec::new(), &Vec::new());
        }
        header.bitcoin_hash()
 }
 
-pub struct Node {
+pub struct Node<'a, 'b: 'a> {
+       pub block_notifier: Arc<chaininterface::BlockNotifier<'a>>,
        pub chain_monitor: Arc<chaininterface::ChainWatchInterfaceUtil>,
        pub tx_broadcaster: Arc<test_utils::TestBroadcaster>,
        pub chan_monitor: Arc<test_utils::TestChannelMonitor>,
        pub keys_manager: Arc<test_utils::TestKeysInterface>,
-       pub node: Arc<ChannelManager>,
+       pub node: Arc<ChannelManager<'b>>,
        pub router: Router,
        pub node_seed: [u8; 32],
        pub network_payment_count: Rc<RefCell<u8>>,
        pub network_chan_count: Rc<RefCell<u32>>,
 }
-impl Drop for Node {
+impl<'a, 'b> Drop for Node<'a, 'b> {
        fn drop(&mut self) {
                if !::std::thread::panicking() {
                        // Check that we processed all pending events
@@ -220,7 +221,7 @@ pub fn create_chan_between_nodes_with_value_init(node_a: &Node, node_b: &Node, c
 }
 
 pub fn create_chan_between_nodes_with_value_confirm_first(node_recv: &Node, node_conf: &Node, tx: &Transaction) {
-       confirm_transaction(&node_conf.chain_monitor, &tx, tx.version);
+       confirm_transaction(&node_conf.block_notifier, &node_conf.chain_monitor, &tx, tx.version);
        node_recv.node.handle_funding_locked(&node_conf.node.get_our_node_id(), &get_event_msg!(node_conf, MessageSendEvent::SendFundingLocked, node_recv.node.get_our_node_id())).unwrap();
 }
 
@@ -246,7 +247,7 @@ pub fn create_chan_between_nodes_with_value_confirm_second(node_recv: &Node, nod
 
 pub fn create_chan_between_nodes_with_value_confirm(node_a: &Node, node_b: &Node, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) {
        create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx);
-       confirm_transaction(&node_a.chain_monitor, &tx, tx.version);
+       confirm_transaction(&node_a.block_notifier, &node_a.chain_monitor, &tx, tx.version);
        create_chan_between_nodes_with_value_confirm_second(node_b, node_a)
 }
 
@@ -353,7 +354,7 @@ macro_rules! check_closed_broadcast {
        }}
 }
 
-pub fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) {
+pub fn close_channel<'a, 'b>(outbound_node: &Node<'a, 'b>, inbound_node: &Node<'a, 'b>, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) {
        let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) };
        let (node_b, broadcaster_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster) } else { (&inbound_node.node, &inbound_node.tx_broadcaster) };
        let (tx_a, tx_b);
@@ -588,7 +589,7 @@ macro_rules! expect_payment_sent {
        }
 }
 
-pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64, our_payment_hash: PaymentHash) {
+pub fn send_along_route_with_hash<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64, our_payment_hash: PaymentHash) {
        let mut payment_event = {
                origin_node.node.send_payment(route, our_payment_hash).unwrap();
                check_added_monitors!(origin_node, 1);
@@ -630,7 +631,7 @@ pub fn send_along_route_with_hash(origin_node: &Node, route: Route, expected_rou
        }
 }
 
-pub fn send_along_route(origin_node: &Node, route: Route, expected_route: &[&Node], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
+pub fn send_along_route<'a, 'b>(origin_node: &Node<'a, 'b>, route: Route, expected_route: &[&Node<'a, 'b>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
        let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(origin_node);
        send_along_route_with_hash(origin_node, route, expected_route, recv_value, our_payment_hash);
        (our_payment_preimage, our_payment_hash)
@@ -720,7 +721,7 @@ pub fn claim_payment(origin_node: &Node, expected_route: &[&Node], our_payment_p
 
 pub const TEST_FINAL_CLTV: u32 = 32;
 
-pub fn route_payment(origin_node: &Node, expected_route: &[&Node], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
+pub fn route_payment<'a, 'b>(origin_node: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
        let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap();
        assert_eq!(route.hops.len(), expected_route.len());
        for (node, hop) in expected_route.iter().zip(route.hops.iter()) {
@@ -746,7 +747,7 @@ pub fn route_over_limit(origin_node: &Node, expected_route: &[&Node], recv_value
        };
 }
 
-pub fn send_payment(origin: &Node, expected_route: &[&Node], recv_value: u64, expected_value: u64) {
+pub fn send_payment<'a, 'b>(origin: &Node<'a, 'b>, expected_route: &[&Node<'a, 'b>], recv_value: u64, expected_value: u64) {
        let our_payment_preimage = route_payment(&origin, expected_route, recv_value).0;
        claim_payment(&origin, expected_route, our_payment_preimage, expected_value);
 }
@@ -836,19 +837,25 @@ pub fn create_network(node_count: usize, node_config: &[Option<UserConfig>]) ->
                let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
                let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
                let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
+               let block_notifier = Arc::new(chaininterface::BlockNotifier::new(chain_monitor.clone()));
                let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
                let mut seed = [0; 32];
                rng.fill_bytes(&mut seed);
                let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet, Arc::clone(&logger)));
                let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
+               let weak_res = Arc::downgrade(&chan_monitor.simple_monitor);
+               block_notifier.register_listener(weak_res);
                let mut default_config = UserConfig::new();
                default_config.channel_options.announced_channel = true;
                default_config.peer_channel_config_limits.force_announced_channel_preference = false;
-               let node = ChannelManager::new(Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone(), if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0).unwrap();
+               let node = ChannelManager::new(Network::Testnet, feeest.clone(), chan_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone(), if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, 0).unwrap();
+               let weak_res = Arc::downgrade(&node);
+               block_notifier.register_listener(weak_res);
                let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()), chain_monitor.clone(), Arc::clone(&logger));
                nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router, keys_manager, node_seed: seed,
                        network_payment_count: payment_count.clone(),
                        network_chan_count: chan_count.clone(),
+                       block_notifier,
                });
        }
 
index d44b75cc981a64997e4a060d6df6087e1b7bfa84..83ca1e422ec7104f1433fc28becdb30510d7c698 100644 (file)
@@ -3,7 +3,7 @@
 //! claim outputs on-chain.
 
 use chain::transaction::OutPoint;
-use chain::chaininterface::{ChainListener, ChainWatchInterface, ChainWatchInterfaceUtil};
+use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil};
 use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor, KeysManager};
 use chain::keysinterface;
 use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
@@ -656,8 +656,8 @@ fn pre_funding_lock_shutdown_test() {
        let nodes = create_network(2, &[None, None]);
        let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 8000000, 0, LocalFeatures::new(), LocalFeatures::new());
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&tx; 1], &[1; 1]);
-       nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&tx; 1], &[1; 1]);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![tx.clone()]}, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![tx.clone()]}, 1);
 
        nodes[0].node.close_channel(&OutPoint::new(tx.txid(), 0).to_channel_id()).unwrap();
        let node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[1].node.get_our_node_id());
@@ -1281,8 +1281,7 @@ fn test_duplicate_htlc_different_direction_onchain() {
        assert_eq!(has_both_htlcs, 2);
 
        let header = BlockHeader { version: 0x2000_0000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![remote_txn[0].clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![remote_txn[0].clone()] }, 1);
 
        // Check we only broadcast 1 timeout tx
        let claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
@@ -1739,7 +1738,7 @@ fn channel_monitor_network_test() {
        {
                let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
                test_txn_broadcast(&nodes[0], &chan_1, None, HTLCType::NONE);
        }
        get_announce_close_broadcast_events(&nodes, 0, 1);
@@ -1754,7 +1753,7 @@ fn channel_monitor_network_test() {
        {
                let mut node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
+               nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
                test_txn_broadcast(&nodes[2], &chan_2, None, HTLCType::NONE);
        }
        get_announce_close_broadcast_events(&nodes, 1, 2);
@@ -1791,7 +1790,7 @@ fn channel_monitor_network_test() {
                claim_funds!(nodes[3], nodes[2], payment_preimage_1, 3_000_000);
 
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[3].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 1);
+               nodes[3].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 1);
 
                check_preimage_claim(&nodes[3], &node_txn);
        }
@@ -1801,7 +1800,7 @@ fn channel_monitor_network_test() {
 
        { // Cheat and reset nodes[4]'s height to 1
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[4].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![] }, 1);
+               nodes[4].block_notifier.block_connected(&Block { header, txdata: vec![] }, 1);
        }
 
        assert_eq!(nodes[3].node.latest_block_height.load(Ordering::Acquire), 1);
@@ -1813,10 +1812,10 @@ fn channel_monitor_network_test() {
 
        {
                let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[3].chain_monitor.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]);
+               nodes[3].block_notifier.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]);
                for i in 3..TEST_FINAL_CLTV + 2 + LATENCY_GRACE_PERIOD_BLOCKS + 1 {
                        header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-                       nodes[3].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
+                       nodes[3].block_notifier.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
                }
 
                let node_txn = test_txn_broadcast(&nodes[3], &chan_4, None, HTLCType::TIMEOUT);
@@ -1825,16 +1824,17 @@ fn channel_monitor_network_test() {
                claim_funds!(nodes[4], nodes[3], payment_preimage_2, 3_000_000);
 
                header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[4].chain_monitor.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]);
+
+               nodes[4].block_notifier.block_connected_checked(&header, 2, &Vec::new()[..], &[0; 0]);
                for i in 3..TEST_FINAL_CLTV + 2 - CLTV_CLAIM_BUFFER + 1 {
                        header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-                       nodes[4].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
+                       nodes[4].block_notifier.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
                }
 
                test_txn_broadcast(&nodes[4], &chan_4, None, HTLCType::SUCCESS);
 
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[4].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, TEST_FINAL_CLTV - 5);
+               nodes[4].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, TEST_FINAL_CLTV - 5);
 
                check_preimage_claim(&nodes[4], &node_txn);
        }
@@ -1846,7 +1846,6 @@ fn channel_monitor_network_test() {
 #[test]
 fn test_justice_tx() {
        // Test justice txn built on revoked HTLC-Success tx, against both sides
-
        let mut alice_config = UserConfig::new();
        alice_config.channel_options.announced_channel = true;
        alice_config.peer_channel_config_limits.force_announced_channel_preference = false;
@@ -1855,7 +1854,8 @@ fn test_justice_tx() {
        bob_config.channel_options.announced_channel = true;
        bob_config.peer_channel_config_limits.force_announced_channel_preference = false;
        bob_config.own_channel_config.our_to_self_delay = 6 * 24 * 3;
-       let nodes = create_network(2, &[Some(alice_config), Some(bob_config)]);
+       let cfgs = [Some(alice_config), Some(bob_config)];
+       let nodes = create_network(2, &cfgs);
        // Create some new channels:
        let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
 
@@ -1875,7 +1875,7 @@ fn test_justice_tx() {
 
        {
                let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
                {
                        let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
                        assert_eq!(node_txn.len(), 3);
@@ -1887,10 +1887,10 @@ fn test_justice_tx() {
                }
                test_txn_broadcast(&nodes[1], &chan_5, None, HTLCType::NONE);
 
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
                let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
+               nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
                test_revoked_htlc_claim_txn_broadcast(&nodes[1], node_txn[1].clone());
        }
        get_announce_close_broadcast_events(&nodes, 0, 1);
@@ -1914,7 +1914,7 @@ fn test_justice_tx() {
        claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_4, 3_000_000);
        {
                let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
                {
                        let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
                        assert_eq!(node_txn.len(), 3);
@@ -1926,10 +1926,10 @@ fn test_justice_tx() {
                }
                test_txn_broadcast(&nodes[0], &chan_6, None, HTLCType::NONE);
 
-               nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
                let node_txn = test_txn_broadcast(&nodes[1], &chan_6, Some(revoked_local_txn[0].clone()), HTLCType::SUCCESS);
                header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
                test_revoked_htlc_claim_txn_broadcast(&nodes[0], node_txn[1].clone());
        }
        get_announce_close_broadcast_events(&nodes, 0, 1);
@@ -1953,7 +1953,7 @@ fn revoked_output_claim() {
 
        // Inform nodes[1] that nodes[0] broadcast a stale tx
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
        assert_eq!(node_txn.len(), 3); // nodes[1] will broadcast justice tx twice, and its own local state once
 
@@ -1963,7 +1963,7 @@ fn revoked_output_claim() {
        check_spends!(node_txn[1], chan_1.3.clone());
 
        // Inform nodes[0] that a watchtower cheated on its behalf, so it will force-close the chan
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        get_announce_close_broadcast_events(&nodes, 0, 1);
 }
 
@@ -1996,9 +1996,9 @@ fn claim_htlc_outputs_shared_tx() {
 
        {
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
-               nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
-               connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+               connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
 
                let events = nodes[1].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 1);
@@ -2064,9 +2064,9 @@ fn claim_htlc_outputs_single_tx() {
 
        {
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200);
-               nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200);
-               connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 200, true, header.bitcoin_hash());
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200);
+               nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 200);
+               connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 200, true, header.bitcoin_hash());
 
                let events = nodes[1].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 1);
@@ -2175,7 +2175,7 @@ fn test_htlc_on_chain_success() {
        assert!(updates.update_fail_malformed_htlcs.is_empty());
        assert_eq!(updates.update_fulfill_htlcs.len(), 1);
 
-       nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
+       nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        check_closed_broadcast!(nodes[2]);
        let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 4 (2*2 * HTLC-Success tx)
        assert_eq!(node_txn.len(), 5);
@@ -2192,7 +2192,7 @@ fn test_htlc_on_chain_success() {
        assert_eq!(node_txn[1].lock_time, 0);
 
        // Verify that B's ChannelManager is able to extract preimage from HTLC Success tx and pass it backward
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: node_txn}, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: node_txn}, 1);
        let events = nodes[1].node.get_and_clear_pending_msg_events();
        {
                let mut added_monitors = nodes[1].chan_monitor.added_monitors.lock().unwrap();
@@ -2260,7 +2260,7 @@ fn test_htlc_on_chain_success() {
        // Broadcast preimage tx by B on offered output from A commitment tx  on A's chain
        let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
        check_spends!(commitment_tx[0], chan_1.3.clone());
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        check_closed_broadcast!(nodes[1]);
        let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 1 (HTLC-Success) * 2 (block-rescan)
        assert_eq!(node_txn.len(), 3);
@@ -2277,7 +2277,7 @@ fn test_htlc_on_chain_success() {
        // we already checked the same situation with A.
 
        // Verify that A's ChannelManager is able to extract preimage from preimage tx and generate PaymentSent
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone(), node_txn[0].clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone(), node_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[0]);
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 2);
@@ -2341,7 +2341,7 @@ fn test_htlc_on_chain_timeout() {
                },
                _ => panic!("Unexpected event"),
        };
-       nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
+       nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        check_closed_broadcast!(nodes[2]);
        let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx)
        assert_eq!(node_txn.len(), 1);
@@ -2350,7 +2350,7 @@ fn test_htlc_on_chain_timeout() {
 
        // Broadcast timeout transaction by B on received output from C's commitment tx on B's chain
        // Verify that B's ChannelManager is able to detect that HTLC is timeout by its own tx and react backward in consequence
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
        let timeout_tx;
        {
                let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -2372,8 +2372,8 @@ fn test_htlc_on_chain_timeout() {
                node_txn.clear();
        }
 
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![timeout_tx]}, 1);
-       connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![timeout_tx]}, 1);
+       connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
        check_added_monitors!(nodes[1], 0);
        check_closed_broadcast!(nodes[1]);
 
@@ -2398,7 +2398,7 @@ fn test_htlc_on_chain_timeout() {
        let commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
        check_spends!(commitment_tx[0], chan_1.3.clone());
 
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
        check_closed_broadcast!(nodes[0]);
        let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Timeout tx), ChannelMonitor : 2 (timeout tx) * 2 block-rescan
        assert_eq!(node_txn.len(), 4);
@@ -2431,8 +2431,8 @@ fn test_simple_commitment_revoked_fail_backward() {
        route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
-       connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
        check_added_monitors!(nodes[1], 0);
        check_closed_broadcast!(nodes[1]);
 
@@ -2584,8 +2584,8 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
        assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
-       connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 1, true, header.bitcoin_hash());
 
        let events = nodes[1].node.get_and_clear_pending_events();
        assert_eq!(events.len(), if deliver_bs_raa { 1 } else { 2 });
@@ -2706,12 +2706,12 @@ fn test_htlc_ignore_latest_remote_commitment() {
        assert_eq!(node_txn.len(), 2);
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0], &node_txn[1]], &[1; 2]);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone(), node_txn[1].clone()]}, 1);
        check_closed_broadcast!(nodes[1]);
 
        // Duplicate the block_connected call since this may happen due to other listeners
        // registering new transactions
-       nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0], &node_txn[1]], &[1; 2]);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone(), node_txn[1].clone()]}, 1);
 }
 
 #[test]
@@ -2766,7 +2766,7 @@ fn test_force_close_fail_back() {
        };
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&tx], &[1]);
+       nodes[1].block_notifier.block_connected_checked(&header, 1, &[&tx], &[1]);
 
        // Note no UpdateHTLCs event here from nodes[1] to nodes[0]!
        check_closed_broadcast!(nodes[1]);
@@ -2777,7 +2777,7 @@ fn test_force_close_fail_back() {
                monitors.get_mut(&OutPoint::new(Sha256dHash::from_slice(&payment_event.commitment_msg.channel_id[..]).unwrap(), 0)).unwrap()
                        .provide_payment_preimage(&our_payment_hash, &our_payment_preimage);
        }
-       nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&tx], &[1]);
+       nodes[2].block_notifier.block_connected_checked(&header, 1, &[&tx], &[1]);
        let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap();
        assert_eq!(node_txn.len(), 1);
        assert_eq!(node_txn[0].input.len(), 1);
@@ -3085,7 +3085,7 @@ fn test_funding_peer_disconnect() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       confirm_transaction(&nodes[0].chain_monitor, &tx, tx.version);
+       confirm_transaction(&nodes[0].block_notifier, &nodes[0].chain_monitor, &tx, tx.version);
        let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(events_1.len(), 1);
        match events_1[0] {
@@ -3100,28 +3100,59 @@ fn test_funding_peer_disconnect() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       confirm_transaction(&nodes[1].chain_monitor, &tx, tx.version);
+       confirm_transaction(&nodes[1].block_notifier, &nodes[1].chain_monitor, &tx, tx.version);
        let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
        assert_eq!(events_2.len(), 2);
-       match events_2[0] {
-               MessageSendEvent::SendFundingLocked { ref node_id, msg: _ } => {
+       let funding_locked = match events_2[0] {
+               MessageSendEvent::SendFundingLocked { ref node_id, ref msg } => {
                        assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+                       msg.clone()
                },
                _ => panic!("Unexpected event"),
-       }
-       match events_2[1] {
-               MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ } => {
+       };
+       let bs_announcement_sigs = match events_2[1] {
+               MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => {
                        assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+                       msg.clone()
                },
                _ => panic!("Unexpected event"),
-       }
+       };
 
        reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
 
-       // TODO: We shouldn't need to manually pass list_usable_chanels here once we support
-       // rebroadcasting announcement_signatures upon reconnect.
+       nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &funding_locked).unwrap();
+       nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs).unwrap();
+       let events_3 = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(events_3.len(), 2);
+       let as_announcement_sigs = match events_3[0] {
+               MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } => {
+                       assert_eq!(*node_id, nodes[1].node.get_our_node_id());
+                       msg.clone()
+               },
+               _ => panic!("Unexpected event"),
+       };
+       let (as_announcement, as_update) = match events_3[1] {
+               MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
+                       (msg.clone(), update_msg.clone())
+               },
+               _ => panic!("Unexpected event"),
+       };
+
+       nodes[1].node.handle_announcement_signatures(&nodes[0].node.get_our_node_id(), &as_announcement_sigs).unwrap();
+       let events_4 = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(events_4.len(), 1);
+       let (_, bs_update) = match events_4[0] {
+               MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
+                       (msg.clone(), update_msg.clone())
+               },
+               _ => panic!("Unexpected event"),
+       };
+
+       nodes[0].router.handle_channel_announcement(&as_announcement).unwrap();
+       nodes[0].router.handle_channel_update(&bs_update).unwrap();
+       nodes[0].router.handle_channel_update(&as_update).unwrap();
 
-       let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), Some(&nodes[0].node.list_usable_channels()), &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+       let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
        let (payment_preimage, _) = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000);
        claim_payment(&nodes[0], &[&nodes[1]], payment_preimage, 1_000_000);
 }
@@ -3367,7 +3398,6 @@ fn test_no_txn_manager_serialize_deserialize() {
                        keys_manager,
                        fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                        monitor: nodes[0].chan_monitor.clone(),
-                       chain_monitor: nodes[0].chain_monitor.clone(),
                        tx_broadcaster: nodes[0].tx_broadcaster.clone(),
                        logger: Arc::new(test_utils::TestLogger::new()),
                        channel_monitors: &channel_monitors,
@@ -3378,7 +3408,7 @@ fn test_no_txn_manager_serialize_deserialize() {
        assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
        nodes[0].node = Arc::new(nodes_0_deserialized);
        let nodes_0_as_listener: Arc<ChainListener> = nodes[0].node.clone();
-       nodes[0].chain_monitor.register_listener(Arc::downgrade(&nodes_0_as_listener));
+       nodes[0].block_notifier.register_listener(Arc::downgrade(&nodes_0_as_listener));
        assert_eq!(nodes[0].node.list_channels().len(), 1);
        check_added_monitors!(nodes[0], 1);
 
@@ -3432,7 +3462,6 @@ fn test_simple_manager_serialize_deserialize() {
                        keys_manager,
                        fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                        monitor: nodes[0].chan_monitor.clone(),
-                       chain_monitor: nodes[0].chain_monitor.clone(),
                        tx_broadcaster: nodes[0].tx_broadcaster.clone(),
                        logger: Arc::new(test_utils::TestLogger::new()),
                        channel_monitors: &channel_monitors,
@@ -3493,7 +3522,6 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
                keys_manager,
                fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                monitor: nodes[0].chan_monitor.clone(),
-               chain_monitor: nodes[0].chain_monitor.clone(),
                tx_broadcaster: nodes[0].tx_broadcaster.clone(),
                logger: Arc::new(test_utils::TestLogger::new()),
                channel_monitors: &node_0_monitors.iter().map(|monitor| { (monitor.get_funding_txo().unwrap(), monitor) }).collect(),
@@ -3653,7 +3681,7 @@ fn test_claim_sizeable_push_msat() {
        assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
        let spend_txn = check_spendable_outputs!(nodes[1], 1);
        assert_eq!(spend_txn.len(), 1);
        check_spends!(spend_txn[0], node_txn[0].clone());
@@ -3663,7 +3691,6 @@ fn test_claim_sizeable_push_msat() {
 fn test_claim_on_remote_sizeable_push_msat() {
        // Same test as previous, just test on remote commitment tx, as per_commitment_point registration changes following you're funder/fundee and
        // to_remote output is encumbered by a P2WPKH
-
        let nodes = create_network(2, &[None, None]);
 
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000, LocalFeatures::new(), LocalFeatures::new());
@@ -3676,7 +3703,7 @@ fn test_claim_on_remote_sizeable_push_msat() {
        assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
        check_closed_broadcast!(nodes[1]);
        let spend_txn = check_spendable_outputs!(nodes[1], 1);
        assert_eq!(spend_txn.len(), 2);
@@ -3699,7 +3726,7 @@ fn test_claim_on_remote_revoked_sizeable_push_msat() {
 
        claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
        let  header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[1]);
 
        let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -3728,7 +3755,7 @@ fn test_static_spendable_outputs_preimage_tx() {
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        assert!(nodes[1].node.claim_funds(payment_preimage, 3_000_000));
        check_added_monitors!(nodes[1], 1);
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()] }, 1);
        let events = nodes[1].node.get_and_clear_pending_msg_events();
        match events[0] {
                MessageSendEvent::UpdateHTLCs { .. } => {},
@@ -3767,7 +3794,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
        claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 3_000_000);
 
        let  header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[1]);
 
        let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -3798,7 +3825,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        // A will generate HTLC-Timeout from revoked commitment tx
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[0]);
 
        let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -3810,7 +3837,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
        check_spends!(revoked_htlc_txn[1], chan_1.3.clone());
 
        // B will generate justice tx from A's revoked commitment/HTLC tx
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[1]);
 
        let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -3842,7 +3869,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        // B will generate HTLC-Success from revoked commitment tx
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[1]);
        let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
 
@@ -3853,7 +3880,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
        check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone());
 
        // A will generate justice tx from B's revoked commitment/HTLC tx
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[0]);
 
        let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -3903,7 +3930,7 @@ fn test_onchain_to_onchain_claim() {
        assert_eq!(updates.update_fulfill_htlcs.len(), 1);
        assert!(updates.update_fail_malformed_htlcs.is_empty());
 
-       nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
+       nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        check_closed_broadcast!(nodes[2]);
 
        let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Success tx), ChannelMonitor : 1 (HTLC-Success tx)
@@ -3918,7 +3945,7 @@ fn test_onchain_to_onchain_claim() {
        assert_eq!(c_txn[0].lock_time, 0); // Success tx
 
        // So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![c_txn[1].clone(), c_txn[2].clone()]}, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![c_txn[1].clone(), c_txn[2].clone()]}, 1);
        {
                let mut b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
                assert_eq!(b_txn.len(), 4);
@@ -3952,7 +3979,7 @@ fn test_onchain_to_onchain_claim() {
        };
        // Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx
        let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
        let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
        assert_eq!(b_txn.len(), 3);
        check_spends!(b_txn[1], chan_1.3); // Local commitment tx, issued by ChannelManager
@@ -3983,7 +4010,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        check_spends!(commitment_txn[0], chan_2.3.clone());
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
        check_closed_broadcast!(nodes[1]);
 
        let htlc_timeout_tx;
@@ -4004,7 +4031,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        }
 
        nodes[2].node.claim_funds(our_payment_preimage, 900_000);
-       nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
+       nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
        check_added_monitors!(nodes[2], 2);
        let events = nodes[2].node.get_and_clear_pending_msg_events();
        match events[0] {
@@ -4028,8 +4055,8 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        check_spends!(htlc_success_txn[0], commitment_txn[0].clone());
        check_spends!(htlc_success_txn[1], commitment_txn[0].clone());
 
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![htlc_timeout_tx] }, 200);
-       connect_blocks(&nodes[1].chain_monitor, ANTI_REORG_DELAY - 1, 200, true, header.bitcoin_hash());
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![htlc_timeout_tx] }, 200);
+       connect_blocks(&nodes[1].block_notifier, ANTI_REORG_DELAY - 1, 200, true, header.bitcoin_hash());
        expect_pending_htlcs_forwardable!(nodes[1]);
        let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        assert!(htlc_updates.update_add_htlcs.is_empty());
@@ -4060,7 +4087,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        }
 
        // Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![htlc_success_txn[0].clone()] }, 200);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![htlc_success_txn[0].clone()] }, 200);
        let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        assert!(updates.update_add_htlcs.is_empty());
        assert!(updates.update_fail_htlcs.is_empty());
@@ -4097,7 +4124,7 @@ fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
        nodes[1].node.claim_funds(payment_preimage, 9_000_000);
        check_added_monitors!(nodes[1], 1);
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![local_txn[0].clone()] }, 1);
        let events = nodes[1].node.get_and_clear_pending_msg_events();
        match events[0] {
                MessageSendEvent::UpdateHTLCs { .. } => {},
@@ -4244,11 +4271,11 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        if announce_latest {
-               nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&ds_last_commitment_tx[0]], &[1; 1]);
+               nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![ds_last_commitment_tx[0].clone()]}, 1);
        } else {
-               nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&ds_prev_commitment_tx[0]], &[1; 1]);
+               nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![ds_prev_commitment_tx[0].clone()]}, 1);
        }
-       connect_blocks(&nodes[2].chain_monitor, ANTI_REORG_DELAY - 1, 1, true,  header.bitcoin_hash());
+       connect_blocks(&nodes[2].block_notifier, ANTI_REORG_DELAY - 1, 1, true,  header.bitcoin_hash());
        check_closed_broadcast!(nodes[2]);
        expect_pending_htlcs_forwardable!(nodes[2]);
        check_added_monitors!(nodes[2], 2);
@@ -4383,7 +4410,7 @@ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() {
 
        // Timeout HTLC on A's chain and so it can generate a HTLC-Timeout tx
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 200);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![local_txn[0].clone()] }, 200);
        check_closed_broadcast!(nodes[0]);
 
        let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
@@ -4414,12 +4441,12 @@ fn test_static_output_closing_tx() {
        let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2;
 
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
        let spend_txn = check_spendable_outputs!(nodes[0], 2);
        assert_eq!(spend_txn.len(), 1);
        check_spends!(spend_txn[0], closing_tx.clone());
 
-       nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
+       nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
        let spend_txn = check_spendable_outputs!(nodes[1], 2);
        assert_eq!(spend_txn.len(), 1);
        check_spends!(spend_txn[0], closing_tx);
@@ -4455,7 +4482,7 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) {
 
        let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        for i in 1..TEST_FINAL_CLTV - CLTV_CLAIM_BUFFER + CHAN_CONFIRM_DEPTH + 1 {
-               nodes[1].chain_monitor.block_connected_checked(&header, i, &Vec::new(), &Vec::new());
+               nodes[1].block_notifier.block_connected_checked(&header, i, &Vec::new(), &Vec::new());
                header.prev_blockhash = header.bitcoin_hash();
        }
        test_txn_broadcast(&nodes[1], &chan, None, if use_dust { HTLCType::NONE } else { HTLCType::SUCCESS });
@@ -4478,8 +4505,9 @@ fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) {
        // to "time out" the HTLC.
 
        let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+
        for i in 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + CHAN_CONFIRM_DEPTH + 1 {
-               nodes[0].chain_monitor.block_connected_checked(&header, i, &Vec::new(), &Vec::new());
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: Vec::new()}, i);
                header.prev_blockhash = header.bitcoin_hash();
        }
        test_txn_broadcast(&nodes[0], &chan, None, HTLCType::NONE);
@@ -4518,7 +4546,7 @@ fn do_htlc_claim_previous_remote_commitment_only(use_dust: bool, check_revoke_no
 
        let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        for i in 1..TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS + CHAN_CONFIRM_DEPTH + 1 {
-               nodes[0].chain_monitor.block_connected_checked(&header, i, &Vec::new(), &Vec::new());
+               nodes[0].block_notifier.block_connected_checked(&header, i, &Vec::new(), &Vec::new());
                header.prev_blockhash = header.bitcoin_hash();
        }
        if !check_revoke_no_close {
@@ -4588,7 +4616,7 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
        // reset block height
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
        for ix in 0..nodes.len() {
-               nodes[ix].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]);
+               nodes[ix].block_notifier.block_connected_checked(&header, 1, &[], &[]);
        }
 
        macro_rules! expect_event {
@@ -4921,7 +4949,8 @@ fn test_onion_failure() {
        run_onion_failure_test("expiry_too_soon", 0, &nodes, &route, &payment_hash, |msg| {
                let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[1].chain_monitor.block_connected_checked(&header, height, &Vec::new()[..], &[0; 0]);
+
+               nodes[1].block_notifier.block_connected_checked(&header, height, &[], &[]);
        }, ||{}, true, Some(UPDATE|14), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
 
        run_onion_failure_test("unknown_payment_hash", 2, &nodes, &route, &payment_hash, |_| {}, || {
@@ -4931,7 +4960,8 @@ fn test_onion_failure() {
        run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, |msg| {
                let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
                let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               nodes[2].chain_monitor.block_connected_checked(&header, height, &Vec::new()[..], &[0; 0]);
+
+               nodes[2].block_notifier.block_connected_checked(&header, height, &[], &[]);
        }, || {}, true, Some(17), None);
 
        run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, |_| {}, || {
@@ -5692,10 +5722,11 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
        assert_ne!(as_prev_commitment_tx, as_last_commitment_tx);
        // Fail the 2 dust-HTLCs, move their failure in maturation buffer (htlc_updated_waiting_threshold_conf)
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+
        if announce_latest {
-               nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_last_commitment_tx[0]], &[1; 1]);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![as_last_commitment_tx[0].clone()]}, 1);
        } else {
-               nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_prev_commitment_tx[0]], &[1; 1]);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![as_prev_commitment_tx[0].clone()]}, 1);
        }
 
        let events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -5706,7 +5737,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
        }
 
        assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
-       connect_blocks(&nodes[0].chain_monitor, ANTI_REORG_DELAY - 1, 1, true,  header.bitcoin_hash());
+       connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 1, true,  header.bitcoin_hash());
        let events = nodes[0].node.get_and_clear_pending_events();
        // Only 2 PaymentFailed events should show up, over-dust HTLC has to be failed by timeout tx
        assert_eq!(events.len(), 2);
@@ -5775,7 +5806,7 @@ fn test_no_failure_dust_htlc_local_commitment() {
        assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
        assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0);
        // We broadcast a few more block to check everything is all right
-       connect_blocks(&nodes[0].chain_monitor, 20, 1, true,  header.bitcoin_hash());
+       connect_blocks(&nodes[0].block_notifier, 20, 1, true,  header.bitcoin_hash());
        assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
        assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0);
 
@@ -5812,7 +5843,7 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
        let mut timeout_tx = Vec::new();
        if local {
                // We fail dust-HTLC 1 by broadcast of local commitment tx
-               nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&as_commitment_tx[0]], &[1; 1]);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![as_commitment_tx[0].clone()]}, 1);
                let events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
                match events[0] {
@@ -5821,7 +5852,7 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
                }
                assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
                timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone());
-               let parent_hash  = connect_blocks(&nodes[0].chain_monitor, ANTI_REORG_DELAY - 1, 2, true, header.bitcoin_hash());
+               let parent_hash  = connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 2, true, header.bitcoin_hash());
                let events = nodes[0].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 1);
                match events[0] {
@@ -5834,9 +5865,9 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
                // We fail non-dust-HTLC 2 by broadcast of local HTLC-timeout tx on local commitment tx
                let header_2 = BlockHeader { version: 0x20000000, prev_blockhash: parent_hash, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
                assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
-               nodes[0].chain_monitor.block_connected_checked(&header_2, 7, &[&timeout_tx[0]], &[1; 1]);
+               nodes[0].block_notifier.block_connected(&Block { header: header_2, txdata: vec![timeout_tx[0].clone()]}, 7);
                let header_3 = BlockHeader { version: 0x20000000, prev_blockhash: header_2.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-               connect_blocks(&nodes[0].chain_monitor, ANTI_REORG_DELAY - 1, 8, true, header_3.bitcoin_hash());
+               connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 8, true, header_3.bitcoin_hash());
                let events = nodes[0].node.get_and_clear_pending_events();
                assert_eq!(events.len(), 1);
                match events[0] {
@@ -5847,7 +5878,7 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
                }
        } else {
                // We fail dust-HTLC 1 by broadcast of remote commitment tx. If revoked, fail also non-dust HTLC
-               nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&bs_commitment_tx[0]], &[1; 1]);
+               nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![bs_commitment_tx[0].clone()]}, 1);
                assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
                let events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@ -5856,7 +5887,7 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
                        _ => panic!("Unexpected event"),
                }
                timeout_tx.push(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0].clone());
-               let parent_hash  = connect_blocks(&nodes[0].chain_monitor, ANTI_REORG_DELAY - 1, 2, true, header.bitcoin_hash());
+               let parent_hash  = connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 2, true, header.bitcoin_hash());
                let header_2 = BlockHeader { version: 0x20000000, prev_blockhash: parent_hash, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
                if !revoked {
                        let events = nodes[0].node.get_and_clear_pending_events();
@@ -5869,10 +5900,10 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
                        }
                        assert_eq!(timeout_tx[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
                        // We fail non-dust-HTLC 2 by broadcast of local timeout tx on remote commitment tx
-                       nodes[0].chain_monitor.block_connected_checked(&header_2, 7, &[&timeout_tx[0]], &[1; 1]);
+                       nodes[0].block_notifier.block_connected(&Block { header: header_2, txdata: vec![timeout_tx[0].clone()]}, 7);
                        assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0);
                        let header_3 = BlockHeader { version: 0x20000000, prev_blockhash: header_2.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-                       connect_blocks(&nodes[0].chain_monitor, ANTI_REORG_DELAY - 1, 8, true, header_3.bitcoin_hash());
+                       connect_blocks(&nodes[0].block_notifier, ANTI_REORG_DELAY - 1, 8, true, header_3.bitcoin_hash());
                        let events = nodes[0].node.get_and_clear_pending_events();
                        assert_eq!(events.len(), 1);
                        match events[0] {
@@ -5921,7 +5952,8 @@ fn test_upfront_shutdown_script() {
        config.channel_options.announced_channel = true;
        config.peer_channel_config_limits.force_announced_channel_preference = false;
        config.channel_options.commit_upfront_shutdown_pubkey = false;
-       let nodes = create_network(3, &[None, Some(config), None]);
+       let cfgs = [None, Some(config), None];
+       let nodes = create_network(3, &cfgs);
 
        // We test that in case of peer committing upfront to a script, if it changes at closing, we refuse to sign
        let flags = LocalFeatures::new();
@@ -6018,7 +6050,8 @@ fn test_user_configurable_csv_delay() {
        low_our_to_self_config.own_channel_config.our_to_self_delay = 6;
        let mut high_their_to_self_config = UserConfig::new();
        high_their_to_self_config.peer_channel_config_limits.their_to_self_delay = 100;
-       let nodes = create_network(2, &[Some(high_their_to_self_config.clone()), None]);
+       let cfgs = [Some(high_their_to_self_config.clone()), None];
+       let nodes = create_network(2, &cfgs);
 
        // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
        let keys_manager: Arc<KeysInterface> = Arc::new(KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()), 10, 20));
@@ -6100,7 +6133,6 @@ fn test_data_loss_protect() {
                keys_manager: Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger), 42, 21)),
                fee_estimator: feeest.clone(),
                monitor: monitor.clone(),
-               chain_monitor: chain_monitor.clone(),
                logger: Arc::clone(&logger),
                tx_broadcaster,
                default_config: UserConfig::new(),
@@ -6110,6 +6142,12 @@ fn test_data_loss_protect() {
        monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok();
        nodes[0].chan_monitor = monitor;
        nodes[0].chain_monitor = chain_monitor;
+
+       let weak_res = Arc::downgrade(&nodes[0].chan_monitor.simple_monitor);
+       nodes[0].block_notifier.register_listener(weak_res);
+       let weak_res = Arc::downgrade(&nodes[0].node);
+       nodes[0].block_notifier.register_listener(weak_res);
+
        check_added_monitors!(nodes[0], 1);
 
        nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
@@ -6166,7 +6204,7 @@ fn test_data_loss_protect() {
        check_spends!(node_txn[0], chan.3.clone());
        assert_eq!(node_txn[0].output.len(), 2);
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
-       nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()]}, 1);
+       nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![node_txn[0].clone()]}, 1);
        let spend_txn = check_spendable_outputs!(nodes[0], 1);
        assert_eq!(spend_txn.len(), 1);
        check_spends!(spend_txn[0], node_txn[0].clone());