- 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);