X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=9fbbcfff39c9701306f0c06e0dcc47c0fdd7728b;hb=0273ac52db6df30b798b1815b093d9ef065c8c17;hp=82c5d2901e2c15ddedf1ca35548492207f392858;hpb=b3be420cfbf5eccfeebdd813a4c64a9e2e563711;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 82c5d290..9fbbcfff 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -239,12 +239,12 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { // Check that if we serialize the Router, we can deserialize it again. { let mut w = test_utils::TestVecWriter(Vec::new()); - let network_graph_ser = self.net_graph_msg_handler.network_graph.read().unwrap(); + let network_graph_ser = &self.net_graph_msg_handler.network_graph; network_graph_ser.write(&mut w).unwrap(); let network_graph_deser = ::read(&mut io::Cursor::new(&w.0)).unwrap(); - assert!(network_graph_deser == *self.net_graph_msg_handler.network_graph.read().unwrap()); - let net_graph_msg_handler = NetGraphMsgHandler::from_net_graph( - Some(self.chain_source), self.logger, network_graph_deser + assert!(network_graph_deser == self.net_graph_msg_handler.network_graph); + let net_graph_msg_handler = NetGraphMsgHandler::new( + network_graph_deser, Some(self.chain_source), self.logger ); let mut chan_progress = 0; loop { @@ -743,16 +743,16 @@ macro_rules! get_closing_signed_broadcast { #[macro_export] macro_rules! check_closed_broadcast { ($node: expr, $with_error_msg: expr) => {{ - let events = $node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), if $with_error_msg { 2 } else { 1 }); - match events[0] { + let msg_events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(msg_events.len(), if $with_error_msg { 2 } else { 1 }); + match msg_events[0] { MessageSendEvent::BroadcastChannelUpdate { ref msg } => { assert_eq!(msg.contents.flags & 2, 2); }, _ => panic!("Unexpected event"), } if $with_error_msg { - match events[1] { + match msg_events[1] { MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => { // TODO: Check node_id Some(msg.clone()) @@ -763,6 +763,24 @@ macro_rules! check_closed_broadcast { }} } +/// Check that a channel's closing channel event has been issued +#[macro_export] +macro_rules! check_closed_event { + ($node: expr, $events: expr, $reason: expr) => {{ + let events = $node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), $events); + let expected_reason = $reason; + for event in events { + match event { + Event::ChannelClosed { ref reason, .. } => { + assert_eq!(*reason, expected_reason); + }, + _ => panic!("Unexpected event"), + } + } + }} +} + pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: &Node<'a, 'b, 'c>, 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, struct_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) } else { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) }; @@ -962,7 +980,7 @@ macro_rules! get_route_and_payment_hash { let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!($recv_node); let net_graph_msg_handler = &$send_node.net_graph_msg_handler; let route = get_route(&$send_node.node.get_our_node_id(), - &net_graph_msg_handler.network_graph.read().unwrap(), + &net_graph_msg_handler.network_graph, &$recv_node.node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, $send_node.logger).unwrap(); (route, payment_hash, payment_preimage, payment_secret) }} @@ -986,6 +1004,20 @@ macro_rules! expect_pending_htlcs_forwardable { }} } +#[cfg(test)] +macro_rules! expect_pending_htlcs_forwardable_from_events { + ($node: expr, $events: expr, $ignore: expr) => {{ + assert_eq!($events.len(), 1); + match $events[0] { + Event::PendingHTLCsForwardable { .. } => { }, + _ => panic!("Unexpected event"), + }; + if $ignore { + $node.node.process_pending_htlc_forwards(); + } + }} +} + #[cfg(any(test, feature = "unstable"))] macro_rules! expect_payment_received { ($node: expr, $expected_payment_hash: expr, $expected_payment_secret: expr, $expected_recv_value: expr) => { @@ -1036,22 +1068,27 @@ macro_rules! expect_payment_forwarded { } #[cfg(test)] -macro_rules! expect_payment_failure_chan_update { - ($node: expr, $scid: expr, $chan_closed: expr) => { - let events = $node.node.get_and_clear_pending_msg_events(); +macro_rules! expect_payment_failed_with_update { + ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr, $scid: expr, $chan_closed: expr) => { + let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::PaymentFailureNetworkUpdate { ref update } => { - match update { - &HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } if !$chan_closed => { + Event::PaymentPathFailed { ref payment_hash, rejected_by_dest, ref network_update, ref error_code, ref error_data, .. } => { + assert_eq!(*payment_hash, $expected_payment_hash, "unexpected payment_hash"); + assert_eq!(rejected_by_dest, $rejected_by_dest, "unexpected rejected_by_dest value"); + assert!(error_code.is_some(), "expected error_code.is_some() = true"); + assert!(error_data.is_some(), "expected error_data.is_some() = true"); + match network_update { + &Some(NetworkUpdate::ChannelUpdateMessage { ref msg }) if !$chan_closed => { assert_eq!(msg.contents.short_channel_id, $scid); assert_eq!(msg.contents.flags & 2, 0); }, - &HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } if $chan_closed => { + &Some(NetworkUpdate::ChannelClosed { short_channel_id, is_permanent }) if $chan_closed => { assert_eq!(short_channel_id, $scid); assert!(is_permanent); }, - _ => panic!("Unexpected update type"), + Some(_) => panic!("Unexpected update type"), + None => panic!("Expected update"), } }, _ => panic!("Unexpected event"), @@ -1065,7 +1102,7 @@ macro_rules! expect_payment_failed { let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentFailed { ref payment_hash, rejected_by_dest, ref error_code, ref error_data } => { + Event::PaymentPathFailed { ref payment_hash, rejected_by_dest, network_update: _, ref error_code, ref error_data, .. } => { assert_eq!(*payment_hash, $expected_payment_hash, "unexpected payment_hash"); assert_eq!(rejected_by_dest, $rejected_by_dest, "unexpected rejected_by_dest value"); assert!(error_code.is_some(), "expected error_code.is_some() = true"); @@ -1237,9 +1274,11 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp if !skip_last { last_update_fulfill_dance!(origin_node, expected_route.first().unwrap()); - expect_payment_sent!(origin_node, our_payment_preimage); } } + if !skip_last { + expect_payment_sent!(origin_node, our_payment_preimage); + } } pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) { @@ -1250,7 +1289,7 @@ pub const TEST_FINAL_CLTV: u32 = 70; pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) { let net_graph_msg_handler = &origin_node.net_graph_msg_handler; - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), + let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), Some(&origin_node.node.list_usable_channels().iter().collect::>()), &[], recv_value, TEST_FINAL_CLTV, origin_node.logger).unwrap(); @@ -1265,7 +1304,7 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) { let net_graph_msg_handler = &origin_node.net_graph_msg_handler; - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, origin_node.logger).unwrap(); + let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, origin_node.logger).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { @@ -1282,77 +1321,100 @@ pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&No claim_payment(&origin, expected_route, our_payment_preimage); } -pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_hash: PaymentHash) { - assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash)); - expect_pending_htlcs_forwardable!(expected_route.last().unwrap()); - check_added_monitors!(expected_route.last().unwrap(), 1); +pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) { + let mut expected_paths: Vec<_> = expected_paths_slice.iter().collect(); + for path in expected_paths.iter() { + assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id()); + } + assert!(expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash)); + expect_pending_htlcs_forwardable!(expected_paths[0].last().unwrap()); + check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len()); - let mut next_msgs: Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned)> = None; - macro_rules! update_fail_dance { - ($node: expr, $prev_node: expr, $last_node: expr) => { - { - $node.node.handle_update_fail_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, !$last_node); - if skip_last && $last_node { - expect_pending_htlcs_forwardable!($node); + let mut per_path_msgs: Vec<((msgs::UpdateFailHTLC, msgs::CommitmentSigned), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let events = expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), expected_paths.len()); + for ev in events.iter() { + let (update_fail, commitment_signed, node_id) = match ev { + &MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + assert!(update_add_htlcs.is_empty()); + assert!(update_fulfill_htlcs.is_empty()); + assert_eq!(update_fail_htlcs.len(), 1); + assert!(update_fail_malformed_htlcs.is_empty()); + assert!(update_fee.is_none()); + (update_fail_htlcs[0].clone(), commitment_signed.clone(), node_id.clone()) + }, + _ => panic!("Unexpected event"), + }; + per_path_msgs.push(((update_fail, commitment_signed), node_id)); + } + per_path_msgs.sort_unstable_by(|(_, node_id_a), (_, node_id_b)| node_id_a.cmp(node_id_b)); + expected_paths.sort_unstable_by(|path_a, path_b| path_a[path_a.len() - 2].node.get_our_node_id().cmp(&path_b[path_b.len() - 2].node.get_our_node_id())); + + for (i, (expected_route, (path_msgs, next_hop))) in expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() { + let mut next_msgs = Some(path_msgs); + let mut expected_next_node = next_hop; + let mut prev_node = expected_route.last().unwrap(); + + for (idx, node) in expected_route.iter().rev().enumerate().skip(1) { + assert_eq!(expected_next_node, node.node.get_our_node_id()); + let update_next_node = !skip_last || idx != expected_route.len() - 1; + if next_msgs.is_some() { + node.node.handle_update_fail_htlc(&prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); + commitment_signed_dance!(node, prev_node, next_msgs.as_ref().unwrap().1, update_next_node); + if !update_next_node { + expect_pending_htlcs_forwardable!(node); } } - } - } + let events = node.node.get_and_clear_pending_msg_events(); + if update_next_node { + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + assert!(update_add_htlcs.is_empty()); + assert!(update_fulfill_htlcs.is_empty()); + assert_eq!(update_fail_htlcs.len(), 1); + assert!(update_fail_malformed_htlcs.is_empty()); + assert!(update_fee.is_none()); + expected_next_node = node_id.clone(); + next_msgs = Some((update_fail_htlcs[0].clone(), commitment_signed.clone())); + }, + _ => panic!("Unexpected event"), + } + } else { + assert!(events.is_empty()); + } + if !skip_last && idx == expected_route.len() - 1 { + assert_eq!(expected_next_node, origin_node.node.get_our_node_id()); + } - let mut expected_next_node = expected_route.last().unwrap().node.get_our_node_id(); - let mut prev_node = expected_route.last().unwrap(); - for (idx, node) in expected_route.iter().rev().enumerate() { - assert_eq!(expected_next_node, node.node.get_our_node_id()); - if next_msgs.is_some() { - // We may be the "last node" for the purpose of the commitment dance if we're - // skipping the last node (implying it is disconnected) and we're the - // second-to-last node! - update_fail_dance!(node, prev_node, skip_last && idx == expected_route.len() - 1); + prev_node = node; } - let events = node.node.get_and_clear_pending_msg_events(); - if !skip_last || idx != expected_route.len() - 1 { + if !skip_last { + let prev_node = expected_route.first().unwrap(); + origin_node.node.handle_update_fail_htlc(&prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); + check_added_monitors!(origin_node, 0); + assert!(origin_node.node.get_and_clear_pending_msg_events().is_empty()); + commitment_signed_dance!(origin_node, prev_node, next_msgs.as_ref().unwrap().1, false); + let events = origin_node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { - assert!(update_add_htlcs.is_empty()); - assert!(update_fulfill_htlcs.is_empty()); - assert_eq!(update_fail_htlcs.len(), 1); - assert!(update_fail_malformed_htlcs.is_empty()); - assert!(update_fee.is_none()); - expected_next_node = node_id.clone(); - next_msgs = Some((update_fail_htlcs[0].clone(), commitment_signed.clone())); + Event::PaymentPathFailed { payment_hash, rejected_by_dest, all_paths_failed, ref path, .. } => { + assert_eq!(payment_hash, our_payment_hash); + assert!(rejected_by_dest); + assert_eq!(all_paths_failed, i == expected_paths.len() - 1); + for (idx, hop) in expected_route.iter().enumerate() { + assert_eq!(hop.node.get_our_node_id(), path[idx].pubkey); + } }, _ => panic!("Unexpected event"), } - } else { - assert!(events.is_empty()); - } - if !skip_last && idx == expected_route.len() - 1 { - assert_eq!(expected_next_node, origin_node.node.get_our_node_id()); - } - - prev_node = node; - } - - if !skip_last { - update_fail_dance!(origin_node, expected_route.first().unwrap(), true); - - let events = origin_node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - match events[0] { - Event::PaymentFailed { payment_hash, rejected_by_dest, .. } => { - assert_eq!(payment_hash, our_payment_hash); - assert!(rejected_by_dest); - }, - _ => panic!("Unexpected event"), } } } -pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash) { - fail_payment_along_route(origin_node, expected_route, false, our_payment_hash); +pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash) { + fail_payment_along_route(origin_node, &[&expected_path[..]], false, our_payment_hash); } pub fn create_chanmon_cfgs(node_count: usize) -> Vec { @@ -1435,7 +1497,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec