Merge pull request #2411 from valentinewallace/2023-07-blinded-onion-keys
[rust-lightning] / lightning / src / ln / functional_tests.rs
index b73b857580c7ad8f5ba0d19b5839ac251cc6f627..ebbb9c4728668804cb8485fd06a9eac288d29f23 100644 (file)
@@ -26,7 +26,7 @@ use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, ChannelError};
 use crate::ln::{chan_utils, onion_utils};
 use crate::ln::chan_utils::{OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
 use crate::routing::gossip::{NetworkGraph, NetworkUpdate};
-use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, RouteParameters, find_route, get_route};
+use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route};
 use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
@@ -2124,7 +2124,7 @@ fn channel_reserve_in_flight_removes() {
        nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_removes.commitment_signed);
        check_added_monitors!(nodes[0], 1);
        let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
-       expect_payment_sent_without_paths!(nodes[0], payment_preimage_1);
+       expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false);
 
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_1.msgs[0]);
        nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &send_1.commitment_msg);
@@ -2153,7 +2153,7 @@ fn channel_reserve_in_flight_removes() {
        nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_cs.commitment_signed);
        check_added_monitors!(nodes[0], 1);
        let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
-       expect_payment_sent_without_paths!(nodes[0], payment_preimage_2);
+       expect_payment_sent(&nodes[0], payment_preimage_2, None, false, false);
 
        nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_raa);
        check_added_monitors!(nodes[1], 1);
@@ -3584,7 +3584,7 @@ fn test_dup_events_on_peer_disconnect() {
        check_added_monitors!(nodes[1], 1);
        let claim_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &claim_msgs.update_fulfill_htlcs[0]);
-       expect_payment_sent_without_paths!(nodes[0], payment_preimage);
+       expect_payment_sent(&nodes[0], payment_preimage, None, false, false);
 
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id());
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
@@ -3706,6 +3706,7 @@ fn test_simple_peer_disconnect() {
                        _ => panic!("Unexpected event"),
                }
        }
+       check_added_monitors(&nodes[0], 1);
 
        claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4);
        fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_6);
@@ -4943,7 +4944,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
 
        nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
        commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false);
-       expect_payment_sent(&nodes[0], our_payment_preimage, None, true);
+       expect_payment_sent(&nodes[0], our_payment_preimage, None, true, true);
 }
 
 #[test]
@@ -5486,7 +5487,7 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) {
 
        let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]);
-       expect_payment_sent_without_paths!(nodes[0], payment_preimage);
+       expect_payment_sent(&nodes[0], payment_preimage, None, false, false);
 
        nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_updates.commitment_signed);
        check_added_monitors!(nodes[0], 1);
@@ -7013,7 +7014,7 @@ fn test_user_configurable_csv_delay() {
        open_channel.to_self_delay = 200;
        if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
                &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
-               &low_our_to_self_config, 0, &nodes[0].logger, 42)
+               &low_our_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false)
        {
                match error {
                        ChannelError::Close(err) => { assert!(regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap().is_match(err.as_str()));  },
@@ -7045,7 +7046,7 @@ fn test_user_configurable_csv_delay() {
        open_channel.to_self_delay = 200;
        if let Err(error) = InboundV1Channel::new(&LowerBoundedFeeEstimator::new(&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }),
                &nodes[0].keys_manager, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &nodes[0].node.channel_type_features(), &nodes[1].node.init_features(), &open_channel, 0,
-               &high_their_to_self_config, 0, &nodes[0].logger, 42)
+               &high_their_to_self_config, 0, &nodes[0].logger, /*is_0conf=*/false)
        {
                match error {
                        ChannelError::Close(err) => { assert!(regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap().is_match(err.as_str())); },
@@ -7878,71 +7879,9 @@ fn test_manually_reject_inbound_channel_request() {
                }
                _ => panic!("Unexpected event"),
        }
-       check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
-}
-
-#[test]
-fn test_reject_funding_before_inbound_channel_accepted() {
-       // This tests that when `UserConfig::manually_accept_inbound_channels` is set to true, inbound
-       // channels must to be manually accepted through `ChannelManager::accept_inbound_channel` by
-       // the node operator before the counterparty sends a `FundingCreated` message. If a
-       // `FundingCreated` message is received before the channel is accepted, it should be rejected
-       // and the channel should be closed.
-       let mut manually_accept_conf = UserConfig::default();
-       manually_accept_conf.manually_accept_inbound_channels = true;
-       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, Some(manually_accept_conf.clone())]);
-       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
-
-       nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, Some(manually_accept_conf)).unwrap();
-       let res = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
-       let temp_channel_id = res.temporary_channel_id;
-
-       nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &res);
-
-       // Assert that `nodes[1]` has no `MessageSendEvent::SendAcceptChannel` in the `msg_events`.
-       assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
-
-       // Clear the `Event::OpenChannelRequest` event without responding to the request.
-       nodes[1].node.get_and_clear_pending_events();
-
-       // Get the `AcceptChannel` message of `nodes[1]` without calling
-       // `ChannelManager::accept_inbound_channel`, which generates a
-       // `MessageSendEvent::SendAcceptChannel` event. The message is passed to `nodes[0]`
-       // `handle_accept_channel`, which is required in order for `create_funding_transaction` to
-       // succeed when `nodes[0]` is passed to it.
-       let accept_chan_msg = {
-               let mut node_1_per_peer_lock;
-               let mut node_1_peer_state_lock;
-               let channel =  get_inbound_v1_channel_ref!(&nodes[1], nodes[0], node_1_per_peer_lock, node_1_peer_state_lock, temp_channel_id);
-               channel.get_accept_channel_message()
-       };
-       nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_chan_msg);
-
-       let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
-
-       nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
-       let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
-
-       // The `funding_created_msg` should be rejected by `nodes[1]` as it hasn't accepted the channel
-       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
-
-       let close_msg_ev = nodes[1].node.get_and_clear_pending_msg_events();
-       assert_eq!(close_msg_ev.len(), 1);
-
-       let expected_err = "FundingCreated message received before the channel was accepted";
-       match close_msg_ev[0] {
-               MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, ref node_id, } => {
-                       assert_eq!(msg.channel_id, temp_channel_id);
-                       assert_eq!(*node_id, nodes[0].node.get_our_node_id());
-                       assert_eq!(msg.data, expected_err);
-               }
-               _ => panic!("Unexpected event"),
-       }
 
-       check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: expected_err.to_string() }
-               , [nodes[0].node.get_our_node_id()], 100000);
+       // There should be no more events to process, as the channel was never opened.
+       assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
 }
 
 #[test]
@@ -7970,10 +7909,10 @@ fn test_can_not_accept_inbound_channel_twice() {
                        let api_res = nodes[1].node.accept_inbound_channel(&temporary_channel_id, &nodes[0].node.get_our_node_id(), 0);
                        match api_res {
                                Err(APIError::APIMisuseError { err }) => {
-                                       assert_eq!(err, "The channel isn't currently awaiting to be accepted.");
+                                       assert_eq!(err, "No such channel awaiting to be accepted.");
                                },
                                Ok(_) => panic!("Channel shouldn't be possible to be accepted twice"),
-                               Err(_) => panic!("Unexpected Error"),
+                               Err(e) => panic!("Unexpected Error {:?}", e),
                        }
                }
                _ => panic!("Unexpected event"),
@@ -8001,11 +7940,11 @@ fn test_can_not_accept_unknown_inbound_channel() {
        let unknown_channel_id = [0; 32];
        let api_res = nodes[0].node.accept_inbound_channel(&unknown_channel_id, &nodes[1].node.get_our_node_id(), 0);
        match api_res {
-               Err(APIError::ChannelUnavailable { err }) => {
-                       assert_eq!(err, format!("Channel with id {} not found for the passed counterparty node_id {}", log_bytes!(unknown_channel_id), nodes[1].node.get_our_node_id()));
+               Err(APIError::APIMisuseError { err }) => {
+                       assert_eq!(err, "No such channel awaiting to be accepted.");
                },
                Ok(_) => panic!("It shouldn't be possible to accept an unkown channel"),
-               Err(_) => panic!("Unexpected Error"),
+               Err(e) => panic!("Unexpected Error: {:?}", e),
        }
 }
 
@@ -8076,7 +8015,9 @@ fn test_onion_value_mpp_set_calculation() {
                                RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap();
                        // Edit amt_to_forward to simulate the sender having set
                        // the final amount and the routing node taking less fee
-                       onion_payloads[1].amt_to_forward = 99_000;
+                       if let msgs::OutboundOnionPayload::Receive { ref mut amt_msat, .. } = onion_payloads[1] {
+                               *amt_msat = 99_000;
+                       } else { panic!() }
                        let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap();
                        payment_event.msgs[0].onion_routing_packet = new_onion_packet;
                }
@@ -9419,74 +9360,7 @@ fn test_inconsistent_mpp_params() {
        pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 15_000_000, our_payment_hash, Some(our_payment_secret), events.pop().unwrap(), true, None);
 
        do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, our_payment_preimage);
-       expect_payment_sent(&nodes[0], our_payment_preimage, Some(None), true);
-}
-
-#[test]
-fn test_keysend_payments_to_public_node() {
-       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 nodes = create_network(2, &node_cfgs, &node_chanmgrs);
-
-       let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001);
-       let network_graph = nodes[0].network_graph.clone();
-       let payer_pubkey = nodes[0].node.get_our_node_id();
-       let payee_pubkey = nodes[1].node.get_our_node_id();
-       let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
-               final_value_msat: 10000,
-       };
-       let scorer = test_utils::TestScorer::new();
-       let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
-       let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
-
-       let test_preimage = PaymentPreimage([42; 32]);
-       let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage),
-               RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0)).unwrap();
-       check_added_monitors!(nodes[0], 1);
-       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
-       assert_eq!(events.len(), 1);
-       let event = events.pop().unwrap();
-       let path = vec![&nodes[1]];
-       pass_along_path(&nodes[0], &path, 10000, payment_hash, None, event, true, Some(test_preimage));
-       claim_payment(&nodes[0], &path, test_preimage);
-}
-
-#[test]
-fn test_keysend_payments_to_private_node() {
-       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 nodes = create_network(2, &node_cfgs, &node_chanmgrs);
-
-       let payer_pubkey = nodes[0].node.get_our_node_id();
-       let payee_pubkey = nodes[1].node.get_our_node_id();
-
-       let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
-       let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
-               final_value_msat: 10000,
-       };
-       let network_graph = nodes[0].network_graph.clone();
-       let first_hops = nodes[0].node.list_usable_channels();
-       let scorer = test_utils::TestScorer::new();
-       let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
-       let route = find_route(
-               &payer_pubkey, &route_params, &network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
-               nodes[0].logger, &scorer, &(), &random_seed_bytes
-       ).unwrap();
-
-       let test_preimage = PaymentPreimage([42; 32]);
-       let payment_hash = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage),
-               RecipientOnionFields::spontaneous_empty(), PaymentId(test_preimage.0)).unwrap();
-       check_added_monitors!(nodes[0], 1);
-       let mut events = nodes[0].node.get_and_clear_pending_msg_events();
-       assert_eq!(events.len(), 1);
-       let event = events.pop().unwrap();
-       let path = vec![&nodes[1]];
-       pass_along_path(&nodes[0], &path, 10000, payment_hash, None, event, true, Some(test_preimage));
-       claim_payment(&nodes[0], &path, test_preimage);
+       expect_payment_sent(&nodes[0], our_payment_preimage, Some(None), true, true);
 }
 
 #[test]
@@ -10101,7 +9975,15 @@ fn test_remove_expired_outbound_unfunded_channels() {
        nodes[0].node.timer_tick_occurred();
        check_outbound_channel_existence(false);
 
-       check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
+       let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
+       assert_eq!(msg_events.len(), 1);
+       match msg_events[0] {
+               MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => {
+                       assert_eq!(msg.data, "Force-closing pending channel due to timeout awaiting establishment handshake");
+               },
+               _ => panic!("Unexpected event"),
+       }
+       check_closed_event(&nodes[0], 1, ClosureReason::HolderForceClosed, false, &[nodes[1].node.get_our_node_id()], 100000);
 }
 
 #[test]
@@ -10144,5 +10026,99 @@ fn test_remove_expired_inbound_unfunded_channels() {
        nodes[1].node.timer_tick_occurred();
        check_inbound_channel_existence(false);
 
-       check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed, [nodes[0].node.get_our_node_id()], 100000);
+       let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(msg_events.len(), 1);
+       match msg_events[0] {
+               MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id: _ } => {
+                       assert_eq!(msg.data, "Force-closing pending channel due to timeout awaiting establishment handshake");
+               },
+               _ => panic!("Unexpected event"),
+       }
+       check_closed_event(&nodes[1], 1, ClosureReason::HolderForceClosed, false, &[nodes[0].node.get_our_node_id()], 100000);
+}
+
+fn do_test_multi_post_event_actions(do_reload: bool) {
+       // Tests handling multiple post-Event actions at once.
+       // There is specific code in ChannelManager to handle channels where multiple post-Event
+       // `ChannelMonitorUpdates` are pending at once. This test exercises that code.
+       //
+       // Specifically, we test calling `get_and_clear_pending_events` while there are two
+       // PaymentSents from different channels and one channel has two pending `ChannelMonitorUpdate`s
+       // - one from an RAA and one from an inbound commitment_signed.
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+       let (persister, chain_monitor, nodes_0_deserialized);
+       let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1).2;
+       let chan_id_2 = create_announced_chan_between_nodes(&nodes, 0, 2).2;
+
+       send_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       send_payment(&nodes[0], &[&nodes[2]], 1_000_000);
+
+       let (our_payment_preimage, our_payment_hash, _) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
+       let (payment_preimage_2, payment_hash_2, _) = route_payment(&nodes[0], &[&nodes[2]], 1_000_000);
+
+       nodes[1].node.claim_funds(our_payment_preimage);
+       check_added_monitors!(nodes[1], 1);
+       expect_payment_claimed!(nodes[1], our_payment_hash, 1_000_000);
+
+       nodes[2].node.claim_funds(payment_preimage_2);
+       check_added_monitors!(nodes[2], 1);
+       expect_payment_claimed!(nodes[2], payment_hash_2, 1_000_000);
+
+       for dest in &[1, 2] {
+               let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[*dest], nodes[0].node.get_our_node_id());
+               nodes[0].node.handle_update_fulfill_htlc(&nodes[*dest].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]);
+               commitment_signed_dance!(nodes[0], nodes[*dest], htlc_fulfill_updates.commitment_signed, false);
+               check_added_monitors(&nodes[0], 0);
+       }
+
+       let (route, payment_hash_3, _, payment_secret_3) =
+               get_route_and_payment_hash!(nodes[1], nodes[0], 100_000);
+       let payment_id = PaymentId(payment_hash_3.0);
+       nodes[1].node.send_payment_with_route(&route, payment_hash_3,
+               RecipientOnionFields::secret_only(payment_secret_3), payment_id).unwrap();
+       check_added_monitors(&nodes[1], 1);
+
+       let send_event = SendEvent::from_node(&nodes[1]);
+       nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &send_event.msgs[0]);
+       nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &send_event.commitment_msg);
+       assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+       if do_reload {
+               let nodes_0_serialized = nodes[0].node.encode();
+               let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
+               let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_2).encode();
+               reload_node!(nodes[0], test_default_channel_config(), &nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, chain_monitor, nodes_0_deserialized);
+
+               nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+               nodes[2].node.peer_disconnected(&nodes[0].node.get_our_node_id());
+
+               reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1]));
+               reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[2]));
+       }
+
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 4);
+       if let Event::PaymentSent { payment_preimage, .. } = events[0] {
+               assert!(payment_preimage == our_payment_preimage || payment_preimage == payment_preimage_2);
+       } else { panic!(); }
+       if let Event::PaymentSent { payment_preimage, .. } = events[1] {
+               assert!(payment_preimage == our_payment_preimage || payment_preimage == payment_preimage_2);
+       } else { panic!(); }
+       if let Event::PaymentPathSuccessful { .. } = events[2] {} else { panic!(); }
+       if let Event::PaymentPathSuccessful { .. } = events[3] {} else { panic!(); }
+
+       // After the events are processed, the ChannelMonitorUpdates will be released and, upon their
+       // completion, we'll respond to nodes[1] with an RAA + CS.
+       get_revoke_commit_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
+       check_added_monitors(&nodes[0], 3);
+}
+
+#[test]
+fn test_multi_post_event_actions() {
+       do_test_multi_post_event_actions(true);
+       do_test_multi_post_event_actions(false);
 }