# 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 &&
--- /dev/null
+hfuzz_target
+target
+hfuzz_workspace
--- /dev/null
+[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"
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+//! 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());
+ }
+}
--- /dev/null
+//! 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
+ }
+}
--- /dev/null
+#!/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 ""
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+#![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..]);
+ }
+ }
+ }
+}
--- /dev/null
+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());
+ }
+}
--- /dev/null
+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());
+ }
+}
--- /dev/null
+pub(crate) mod test_logger;
--- /dev/null
+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);
+ }
+}
--- /dev/null
+#!/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
+++ /dev/null
-hfuzz_target
-target
-hfuzz_workspace
+++ /dev/null
-[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"
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-//! 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());
- }
-}
+++ /dev/null
-//! 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
- }
-}
+++ /dev/null
-#!/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 ""
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-// 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());
- }
-}
+++ /dev/null
-#![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..]);
- }
- }
- }
-}
+++ /dev/null
-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());
- }
-}
+++ /dev/null
-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());
- }
-}
+++ /dev/null
-pub(crate) mod test_logger;
+++ /dev/null
-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);
- }
-}
+++ /dev/null
-#!/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
/// 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.
}
}
+/// 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>,
}
}
}
- 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 {
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 {
};
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());
}
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());
}
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))
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};
/// 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)]
}
}
-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
///
/// 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 {
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),
logger,
});
- let weak_res = Arc::downgrade(&res);
- res.chain_monitor.register_listener(weak_res);
+
Ok(res)
}
}
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,
}
}
-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
}
}
-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
}
}
-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());
}
}
-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();
}
}
-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();
/// 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>,
/// 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.
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 {
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),
/// 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`.
///
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);
logger,
fee_estimator: feeest,
});
- let weak_res = Arc::downgrade(&res);
- res.chain_monitor.register_listener(weak_res);
+
res
}
};
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() {
}
}
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);
}
// 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);
}
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
}
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();
}
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)
}
}}
}
-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);
}
}
-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);
}
}
-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)
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()) {
};
}
-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);
}
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,
});
}
//! 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};
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());
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();
{
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);
{
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);
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);
}
{ // 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);
{
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);
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);
}
#[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;
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());
{
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);
}
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);
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);
}
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);
// 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
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);
}
{
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);
{
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);
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);
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();
// 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);
// 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);
},
_ => 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);
// 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();
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]);
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);
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]);
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 });
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]
};
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]);
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);
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] {
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);
}
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,
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);
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,
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(),
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());
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());
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);
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();
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 { .. } => {},
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();
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();
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();
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();
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();
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)
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);
};
// 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
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;
}
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] {
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());
}
// 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());
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 { .. } => {},
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);
// 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();
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);
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 });
// 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);
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 {
// 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 {
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, |_| {}, || {
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, |_| {}, || {
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();
}
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);
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);
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] {
}
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] {
// 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] {
}
} 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);
_ => 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();
}
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] {
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();
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));
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(),
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());
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());