X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=fuzz%2Fsrc%2Fchanmon_consistency.rs;h=5466414b2cd16560e08949c4ec579b2f32a5b602;hb=25c9a37e18b6e3e30a9ad0c8645fb8da34413199;hp=8a17719f9bbafab5a85c2b0f274cb5a46783d61e;hpb=943153530dbd5d002f7193d601b4ba7ad7f6ab60;p=rust-lightning diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 8a17719f..5466414b 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -37,7 +37,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, use lightning::chain::keysinterface::{KeysInterface, InMemoryChannelKeys}; use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs}; use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; -use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init}; +use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, ErrorAction, UpdateAddHTLC, Init}; use lightning::util::enforcing_trait_impls::EnforcingChannelKeys; use lightning::util::errors::APIError; use lightning::util::events; @@ -45,6 +45,7 @@ use lightning::util::logger::Logger; use lightning::util::config::UserConfig; use lightning::util::events::{EventsProvider, MessageSendEventsProvider}; use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer}; +use lightning::util::test_utils::OnlyReadsKeysInterface; use lightning::routing::router::{Route, RouteHop}; @@ -112,7 +113,7 @@ impl chain::Watch for TestChainMonitor { fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { let mut ser = VecWriter(Vec::new()); - monitor.serialize_for_disk(&mut ser).unwrap(); + monitor.write(&mut ser).unwrap(); if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) { panic!("Already had monitor pre-watch_channel"); } @@ -128,10 +129,10 @@ impl chain::Watch for TestChainMonitor { hash_map::Entry::Vacant(_) => panic!("Didn't have monitor on update call"), }; let mut deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: - read(&mut Cursor::new(&map_entry.get().1)).unwrap().1; + read(&mut Cursor::new(&map_entry.get().1), &OnlyReadsKeysInterface {}).unwrap().1; deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator{}, &self.logger).unwrap(); let mut ser = VecWriter(Vec::new()); - deserialized_monitor.serialize_for_disk(&mut ser).unwrap(); + deserialized_monitor.write(&mut ser).unwrap(); map_entry.insert((update.update_id, ser.0)); self.should_update_manager.store(true, atomic::Ordering::Relaxed); self.update_ret.lock().unwrap().clone() @@ -184,6 +185,10 @@ impl KeysInterface for KeyProvider { let id = self.rand_bytes_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] } + + fn read_chan_signer(&self, data: &[u8]) -> Result { + EnforcingChannelKeys::read(&mut std::io::Cursor::new(data)) + } } #[inline] @@ -307,7 +312,7 @@ pub fn do_test(data: &[u8], out: Out) { let mut monitors = HashMap::new(); let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap(); for (outpoint, (update_id, monitor_ser)) in old_monitors.drain() { - monitors.insert(outpoint, <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser)).expect("Failed to read monitor").1); + monitors.insert(outpoint, <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), &OnlyReadsKeysInterface {}).expect("Failed to read monitor").1); chain_monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser)); } let mut monitor_refs = HashMap::new(); @@ -542,7 +547,9 @@ pub fn do_test(data: &[u8], out: Out) { bc_events.clear(); new_events } else { Vec::new() }; + let mut had_events = false; for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) { + had_events = true; 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() { @@ -596,13 +603,10 @@ pub fn do_test(data: &[u8], out: Out) { // Can be generated due to a payment forward being rejected due to a // channel having previously failed a monitor update }, - events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => { - // Can be generated at any processing step to send back an error, disconnect - // peer or just ignore - }, _ => panic!("Unhandled message event"), } } + had_events } } } @@ -682,6 +686,7 @@ pub fn do_test(data: &[u8], out: Out) { } else { Ordering::Equal } } else { Ordering::Equal } }); + let had_events = !events.is_empty(); for event in events.drain(..) { match event { events::Event::PaymentReceived { payment_hash, payment_secret, amt } => { @@ -701,6 +706,7 @@ pub fn do_test(data: &[u8], out: Out) { _ => panic!("Unhandled event"), } } + had_events } } } @@ -768,18 +774,18 @@ pub fn do_test(data: &[u8], out: Out) { } }, - 0x10 => process_msg_events!(0, true), - 0x11 => process_msg_events!(0, false), - 0x12 => process_events!(0, true), - 0x13 => process_events!(0, false), - 0x14 => process_msg_events!(1, true), - 0x15 => process_msg_events!(1, false), - 0x16 => process_events!(1, true), - 0x17 => process_events!(1, false), - 0x18 => process_msg_events!(2, true), - 0x19 => process_msg_events!(2, false), - 0x1a => process_events!(2, true), - 0x1b => process_events!(2, false), + 0x10 => { process_msg_events!(0, true); }, + 0x11 => { process_msg_events!(0, false); }, + 0x12 => { process_events!(0, true); }, + 0x13 => { process_events!(0, false); }, + 0x14 => { process_msg_events!(1, true); }, + 0x15 => { process_msg_events!(1, false); }, + 0x16 => { process_events!(1, true); }, + 0x17 => { process_events!(1, false); }, + 0x18 => { process_msg_events!(2, true); }, + 0x19 => { process_msg_events!(2, false); }, + 0x1a => { process_events!(2, true); }, + 0x1b => { process_events!(2, false); }, 0x1c => { if !chan_a_disconnected { @@ -879,6 +885,62 @@ pub fn do_test(data: &[u8], out: Out) { 0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); }, 0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); }, + 0xff => { + // Test that no channel is in a stuck state where neither party can send funds even + // after we resolve all pending events. + // First make sure there are no pending monitor updates, resetting the error state + // and calling channel_monitor_updated for each monitor. + *monitor_a.update_ret.lock().unwrap() = Ok(()); + *monitor_b.update_ret.lock().unwrap() = Ok(()); + *monitor_c.update_ret.lock().unwrap() = Ok(()); + + if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[0].channel_monitor_updated(&chan_1_funding, *id); + } + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[1].channel_monitor_updated(&chan_1_funding, *id); + } + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[1].channel_monitor_updated(&chan_2_funding, *id); + } + if let Some((id, _)) = monitor_c.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[2].channel_monitor_updated(&chan_2_funding, *id); + } + + // Next, make sure peers are all connected to each other + if chan_a_disconnected { + nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); + nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() }); + chan_a_disconnected = false; + } + if chan_b_disconnected { + nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() }); + nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); + chan_b_disconnected = false; + } + + for i in 0..std::usize::MAX { + if i == 100 { panic!("It may take may iterations to settle the state, but it should not take forever"); } + // Then, make sure any current forwards make their way to their destination + if process_msg_events!(0, false) { continue; } + if process_msg_events!(1, false) { continue; } + if process_msg_events!(2, false) { continue; } + // ...making sure any pending PendingHTLCsForwardable events are handled and + // payments claimed. + if process_events!(0, false) { continue; } + if process_events!(1, false) { continue; } + if process_events!(2, false) { continue; } + break; + } + + // Finally, make sure that at least one end of each channel can make a substantial payment. + assert!( + send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id) || + send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id)); + assert!( + send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) || + send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id)); + }, _ => test_return!(), }