X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchanmon_update_fail_tests.rs;h=30088f2eba6815256990d634afa9e7ec1f2c5d53;hb=843d25d750c3408d3f8f917764b8a58019a9dd81;hp=187cdeaf5ff9d97024da8d3bbb4748b232d6527b;hpb=bb9df69d0d91cf5ea4cef6b81ab2edd9baddb6be;p=rust-lightning diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 187cdeaf..30088f2e 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -28,7 +28,7 @@ use ln::msgs::{ChannelMessageHandler, ErrorAction, RoutingMessageHandler}; use routing::router::get_route; use util::config::UserConfig; use util::enforcing_trait_impls::EnforcingSigner; -use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; +use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose, ClosureReason}; use util::errors::APIError; use util::ser::{ReadableArgs, Writeable}; use util::test_utils::TestBroadcaster; @@ -78,9 +78,10 @@ fn do_test_simple_monitor_permanent_update_fail(persister_fail: bool) { }; // TODO: Once we hit the chain with the failure transaction we should check that we get a - // PaymentFailed event + // PaymentPathFailed event assert_eq!(nodes[0].node.list_channels().len(), 0); + check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() }); } #[test] @@ -266,9 +267,10 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool, persister_fail check_closed_broadcast!(nodes[0], true); // TODO: Once we hit the chain with the failure transaction we should check that we get a - // PaymentFailed event + // PaymentPathFailed event assert_eq!(nodes[0].node.list_channels().len(), 0); + check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed); } #[test] @@ -308,7 +310,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2; let logger = test_utils::TestLogger::new(); - let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); // Now try to send a second payment which will fail to send let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]); @@ -344,8 +346,9 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let events_3 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { - Event::PaymentSent { ref payment_preimage } => { + Event::PaymentSent { ref payment_preimage, ref payment_hash } => { assert_eq!(*payment_preimage, payment_preimage_1); + assert_eq!(*payment_hash, payment_hash_1); }, _ => panic!("Unexpected event"), } @@ -436,8 +439,9 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let events_3 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_3.len(), 1); match events_3[0] { - Event::PaymentSent { ref payment_preimage } => { + Event::PaymentSent { ref payment_preimage, ref payment_hash } => { assert_eq!(*payment_preimage, payment_preimage_1); + assert_eq!(*payment_hash, payment_hash_1); }, _ => panic!("Unexpected event"), } @@ -1362,7 +1366,7 @@ fn claim_while_disconnected_monitor_update_fail() { let logger = test_utils::TestLogger::new(); // Forward a payment for B to claim - let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); 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); @@ -1463,8 +1467,9 @@ fn claim_while_disconnected_monitor_update_fail() { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentSent { ref payment_preimage } => { + Event::PaymentSent { ref payment_preimage, ref payment_hash } => { assert_eq!(*payment_preimage, payment_preimage_1); + assert_eq!(*payment_hash, payment_hash_1); }, _ => panic!("Unexpected event"), } @@ -1817,7 +1822,7 @@ fn test_monitor_update_on_pending_forwards() { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); - if let Event::PaymentFailed { payment_hash, rejected_by_dest, .. } = events[0] { + if let Event::PaymentPathFailed { payment_hash, rejected_by_dest, .. } = events[0] { assert_eq!(payment_hash, payment_hash_1); assert!(rejected_by_dest); } else { panic!("Unexpected event!"); } @@ -1845,7 +1850,7 @@ fn monitor_update_claim_fail_no_response() { let logger = test_utils::TestLogger::new(); // Forward a payment for B to claim - let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + let (payment_preimage_1, payment_hash_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); // Now start forwarding a second payment, skipping the last RAA so B is in AwaitingRAA let (payment_preimage_2, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]); @@ -1887,8 +1892,9 @@ fn monitor_update_claim_fail_no_response() { let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentSent { ref payment_preimage } => { + Event::PaymentSent { ref payment_preimage, ref payment_hash } => { assert_eq!(*payment_preimage, payment_preimage_1); + assert_eq!(*payment_hash, payment_hash_1); }, _ => panic!("Unexpected event"), } @@ -1985,6 +1991,8 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf: send_payment(&nodes[0], &[&nodes[1]], 8000000); close_channel(&nodes[0], &nodes[1], &channel_id, funding_tx, true); + check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure); + check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure); } #[test] @@ -2610,6 +2618,8 @@ fn test_temporary_error_during_shutdown() { assert_eq!(txn_a, txn_b); assert_eq!(txn_a.len(), 1); check_spends!(txn_a[0], funding_tx); + check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure); + check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure); } #[test] @@ -2630,6 +2640,7 @@ fn test_permanent_error_during_sending_shutdown() { assert!(nodes[0].node.close_channel(&channel_id).is_ok()); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 2); + check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() }); } #[test] @@ -2652,4 +2663,102 @@ fn test_permanent_error_during_handling_shutdown() { nodes[1].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &shutdown); check_closed_broadcast!(nodes[1], true); check_added_monitors!(nodes[1], 2); + check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "ChannelMonitor storage failure".to_string() }); +} + +#[test] +fn double_temp_error() { + // Test that it's OK to have multiple `ChainMonitor::update_channel` calls fail in a row. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + let (_, _, channel_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); + + let (payment_preimage_1, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + let (payment_preimage_2, _, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); + + *nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure)); + // `claim_funds` results in a ChannelMonitorUpdate. + assert!(nodes[1].node.claim_funds(payment_preimage_1)); + check_added_monitors!(nodes[1], 1); + let (funding_tx, latest_update_1) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + + *nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure)); + // Previously, this would've panicked due to a double-call to `Channel::monitor_update_failed`, + // which had some asserts that prevented it from being called twice. + assert!(nodes[1].node.claim_funds(payment_preimage_2)); + check_added_monitors!(nodes[1], 1); + *nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Ok(())); + + let (_, latest_update_2) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&funding_tx, latest_update_1); + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + check_added_monitors!(nodes[1], 0); + nodes[1].node.channel_monitor_updated(&funding_tx, latest_update_2); + + // Complete the first HTLC. + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let (update_fulfill_1, commitment_signed_b1, node_id) = { + 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_eq!(update_fulfill_htlcs.len(), 1); + assert!(update_fail_htlcs.is_empty()); + assert!(update_fail_malformed_htlcs.is_empty()); + assert!(update_fee.is_none()); + (update_fulfill_htlcs[0].clone(), commitment_signed.clone(), node_id.clone()) + }, + _ => panic!("Unexpected event"), + } + }; + assert_eq!(node_id, nodes[0].node.get_our_node_id()); + nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_1); + check_added_monitors!(nodes[0], 0); + expect_payment_sent!(nodes[0], payment_preimage_1); + nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed_b1); + check_added_monitors!(nodes[0], 1); + nodes[0].node.process_pending_htlc_forwards(); + let (raa_a1, commitment_signed_a1) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); + check_added_monitors!(nodes[1], 0); + assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); + nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa_a1); + check_added_monitors!(nodes[1], 1); + nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &commitment_signed_a1); + check_added_monitors!(nodes[1], 1); + + // Complete the second HTLC. + let ((update_fulfill_2, commitment_signed_b2), raa_b2) = { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 2); + (match &events[0] { + MessageSendEvent::UpdateHTLCs { node_id, updates } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + assert!(updates.update_add_htlcs.is_empty()); + assert!(updates.update_fail_htlcs.is_empty()); + assert!(updates.update_fail_malformed_htlcs.is_empty()); + assert!(updates.update_fee.is_none()); + assert_eq!(updates.update_fulfill_htlcs.len(), 1); + (updates.update_fulfill_htlcs[0].clone(), updates.commitment_signed.clone()) + }, + _ => panic!("Unexpected event"), + }, + match events[1] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }) + }; + nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &raa_b2); + check_added_monitors!(nodes[0], 1); + + nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_2); + check_added_monitors!(nodes[0], 0); + assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); + commitment_signed_dance!(nodes[0], nodes[1], commitment_signed_b2, false); + expect_payment_sent!(nodes[0], payment_preimage_2); }