From: Matt Corallo Date: Fri, 26 Oct 2018 18:39:14 +0000 (-0400) Subject: Add very basic test of ChannelManager serialization round-trip X-Git-Tag: v0.0.12~283^2 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=refs%2Fheads%2F2018-10-chanmanager-serialize;p=rust-lightning Add very basic test of ChannelManager serialization round-trip --- diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index c8122ca83..6230225ba 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -3178,8 +3178,8 @@ mod tests { use chain::chaininterface::ChainListener; use chain::keysinterface::KeysInterface; use chain::keysinterface; - use ln::channelmanager::{ChannelManager,OnionKeys,PaymentFailReason,RAACommitmentOrder}; - use ln::channelmonitor::{ChannelMonitorUpdateErr, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS}; + use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,OnionKeys,PaymentFailReason,RAACommitmentOrder}; + use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, CLTV_CLAIM_BUFFER, HTLC_FAIL_TIMEOUT_BLOCKS, ManyChannelMonitor}; use ln::router::{Route, RouteHop, Router}; use ln::msgs; use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; @@ -3187,7 +3187,7 @@ mod tests { use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; use util::errors::APIError; use util::logger::Logger; - use util::ser::Writeable; + use util::ser::{Writeable, Writer, ReadableArgs}; use bitcoin::util::hash::Sha256dHash; use bitcoin::blockdata::block::{Block, BlockHeader}; @@ -3382,6 +3382,7 @@ mod tests { chan_monitor: Arc, node: Arc, router: Router, + node_seed: [u8; 32], network_payment_count: Rc>, network_chan_count: Rc>, } @@ -4053,7 +4054,7 @@ mod tests { let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone())); let node = ChannelManager::new(0, true, Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone()).unwrap(); 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, + nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router, node_seed: seed, network_payment_count: payment_count.clone(), network_chan_count: chan_count.clone(), }); @@ -6856,4 +6857,137 @@ mod tests { sign_msg!(unsigned_msg); assert!(nodes[0].router.handle_channel_announcement(&chan_announcement).is_err()); } + + struct VecWriter(Vec); + impl Writer for VecWriter { + fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { + self.0.extend_from_slice(buf); + Ok(()) + } + fn size_hint(&mut self, size: usize) { + self.0.reserve_exact(size); + } + } + + #[test] + fn test_simple_manager_serialize_deserialize() { + let mut nodes = create_network(2); + create_announced_chan_between_nodes(&nodes, 0, 1); + + let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + let (_, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + + let nodes_0_serialized = nodes[0].node.encode(); + let mut chan_0_monitor_serialized = VecWriter(Vec::new()); + nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap(); + + nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone())); + let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; + let (_, chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap(); + assert!(chan_0_monitor_read.is_empty()); + + let mut nodes_0_read = &nodes_0_serialized[..]; + let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()))); + let (_, nodes_0_deserialized) = { + let mut channel_monitors = HashMap::new(); + channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor); + <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + 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, + }).unwrap() + }; + assert!(nodes_0_read.is_empty()); + + 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); + check_added_monitors!(nodes[0], 1); + + reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + + fail_payment(&nodes[0], &[&nodes[1]], our_payment_hash); + claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage); + } + + #[test] + fn test_manager_serialize_deserialize_inconsistent_monitor() { + // Test deserializing a ChannelManager with a out-of-date ChannelMonitor + let mut nodes = create_network(4); + create_announced_chan_between_nodes(&nodes, 0, 1); + create_announced_chan_between_nodes(&nodes, 2, 0); + let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 3); + + let (our_payment_preimage, _) = route_payment(&nodes[2], &[&nodes[0], &nodes[1]], 1000000); + + // Serialize the ChannelManager here, but the monitor we keep up-to-date + let nodes_0_serialized = nodes[0].node.encode(); + + route_payment(&nodes[0], &[&nodes[3]], 1000000); + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + nodes[2].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + nodes[3].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + + // Now the ChannelMonitor (which is now out-of-sync with ChannelManager for channel w/ + // nodes[3]) + let mut node_0_monitors_serialized = Vec::new(); + for monitor in nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter() { + let mut writer = VecWriter(Vec::new()); + monitor.1.write_for_disk(&mut writer).unwrap(); + node_0_monitors_serialized.push(writer.0); + } + + nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone())); + let mut node_0_monitors = Vec::new(); + for serialized in node_0_monitors_serialized.iter() { + let mut read = &serialized[..]; + let (_, monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut read, Arc::new(test_utils::TestLogger::new())).unwrap(); + assert!(read.is_empty()); + node_0_monitors.push(monitor); + } + + let mut nodes_0_read = &nodes_0_serialized[..]; + let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()))); + let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + 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(), + }).unwrap(); + assert!(nodes_0_read.is_empty()); + + { // Channel close should result in a commitment tx and an HTLC tx + let txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(txn.len(), 2); + assert_eq!(txn[0].input[0].previous_output.txid, funding_tx.txid()); + assert_eq!(txn[1].input[0].previous_output.txid, txn[0].txid()); + } + + for monitor in node_0_monitors.drain(..) { + assert!(nodes[0].chan_monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok()); + check_added_monitors!(nodes[0], 1); + } + nodes[0].node = Arc::new(nodes_0_deserialized); + + // nodes[1] and nodes[2] have no lost state with nodes[0]... + reconnect_nodes(&nodes[0], &nodes[1], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + reconnect_nodes(&nodes[0], &nodes[2], false, (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); + //... and we can even still claim the payment! + claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage); + + nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id()); + let reestablish = get_event_msg!(nodes[3], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()); + nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id()); + if let Err(msgs::HandleError { action: Some(msgs::ErrorAction::SendErrorMessage { msg }), .. }) = nodes[0].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish) { + assert_eq!(msg.channel_id, channel_id); + } else { panic!("Unexpected result"); } + } }