From 60012f5dedaaad4181a67ff0cc2e781a80070372 Mon Sep 17 00:00:00 2001 From: Utkarsh Gupta <32920299+utkarshg6@users.noreply.github.com> Date: Sat, 31 Dec 2022 16:19:19 +0530 Subject: [PATCH] GH-647: HOTFIX: Prevent duplication of records of connection-progress (#213) * GH-647: make the ip addresses of initial node descriptors as part of previous pass targets * GH-647: test drive the case where the pass target is a duplicate of peer address present in a different connection progress * GH-647: remove the commented test in overall_connection_status.rs * Revert "GH-647: make the ip addresses of initial node descriptors as part of previous pass targets" This reverts commit afd43da7ea3f89d1626725ea7de59822b458f639. * GH-647: pass the vector of peer_addrs to the handle() of GossipAcceptor and GossipHandler * GH-647: test drive the function to get current peer addrs * GH-647: add test in neighborhood that the gossip is being ignored * GH-647: remove the warnings * GH-647: remove clippy warnings * GH-647: remove clippy warnings * GH-647: Review 1 (#214) * GH-647: rename peers_addrs to connection_progress_peers * GH-647: provide the accurate name inside the constructor of System in the test * GH-647: reword the trace logs for the unnecessary connection progress * GH-647: use a unique number to generate a unique socket address for peer 2 * GH-647: add review changes for overall_connection_status.rs * GH-647: add connection_progress_peers as a param in the mock (#216) --- node/src/neighborhood/gossip_acceptor.rs | 165 ++++++++++++++-- node/src/neighborhood/mod.rs | 181 ++++++++++++++---- .../neighborhood/overall_connection_status.rs | 54 +++++- port_exposer/Cargo.lock | 2 +- 4 files changed, 343 insertions(+), 59 deletions(-) diff --git a/node/src/neighborhood/gossip_acceptor.rs b/node/src/neighborhood/gossip_acceptor.rs index d050f689a..d3f756f9f 100644 --- a/node/src/neighborhood/gossip_acceptor.rs +++ b/node/src/neighborhood/gossip_acceptor.rs @@ -63,6 +63,7 @@ trait GossipHandler: NamedType + Send /* Send because lazily-written tests requi database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + connection_progress_peers: &[IpAddr], cpm_recipient: &Recipient, ) -> GossipAcceptanceResult; } @@ -132,6 +133,7 @@ impl GossipHandler for DebutHandler { database: &mut NeighborhoodDatabase, mut agrs: Vec, gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], _cpm_recipient: &Recipient, ) -> GossipAcceptanceResult { let source_agr = { @@ -508,6 +510,7 @@ impl GossipHandler for PassHandler { database: &mut NeighborhoodDatabase, agrs: Vec, _gossip_source: SocketAddr, + connection_progress_peers: &[IpAddr], cpm_recipient: &Recipient, ) -> GossipAcceptanceResult { let pass_agr = &agrs[0]; // empty Gossip shouldn't get here @@ -538,13 +541,19 @@ impl GossipHandler for PassHandler { let mut hash_map = self.previous_pass_targets.borrow_mut(); let gossip_acceptance_result = match hash_map.get_mut(&pass_target_ip_addr) { - None => { - hash_map.insert(pass_target_ip_addr, SystemTime::now()); - send_cpm(ConnectionProgressEvent::PassGossipReceived( - pass_target_ip_addr, - )); - gossip_acceptance_reply() - } + None => match connection_progress_peers.contains(&pass_target_ip_addr) { + true => { + send_cpm(ConnectionProgressEvent::PassLoopFound); + GossipAcceptanceResult::Ignored + } + false => { + hash_map.insert(pass_target_ip_addr, SystemTime::now()); + send_cpm(ConnectionProgressEvent::PassGossipReceived( + pass_target_ip_addr, + )); + gossip_acceptance_reply() + } + }, Some(timestamp) => { let duration_since = SystemTime::now() .duration_since(*timestamp) @@ -619,6 +628,7 @@ impl GossipHandler for IntroductionHandler { database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], cpm_recipient: &Recipient, ) -> GossipAcceptanceResult { if database.root().full_neighbor_keys(database).len() >= MAX_DEGREE { @@ -923,6 +933,7 @@ impl GossipHandler for StandardGossipHandler { database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], cpm_recipient: &Recipient, ) -> GossipAcceptanceResult { let initial_neighborship_status = @@ -1180,6 +1191,7 @@ impl GossipHandler for RejectHandler { _database: &mut NeighborhoodDatabase, _agrs: Vec, _gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], _cpm_recipient: &Recipient, ) -> GossipAcceptanceResult { panic!("Should never be called") @@ -1198,6 +1210,7 @@ pub trait GossipAcceptor: Send /* Send because lazily-written tests require it * database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + connection_progress_peers: &[IpAddr], ) -> GossipAcceptanceResult; } @@ -1214,6 +1227,7 @@ impl<'a> GossipAcceptor for GossipAcceptorReal<'a> { database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + connection_progress_peers: &[IpAddr], ) -> GossipAcceptanceResult { let (qualification, handler_ref) = self .gossip_handlers @@ -1233,6 +1247,7 @@ impl<'a> GossipAcceptor for GossipAcceptorReal<'a> { database, agrs, gossip_source, + connection_progress_peers, &self.cpm_recipient, ) } @@ -1353,6 +1368,7 @@ mod tests { &mut db, agrs_vec, gossip_source_opt, + &vec![], &cpm_recipient, ); @@ -1384,8 +1400,14 @@ mod tests { let subject = DebutHandler::new(Logger::new("test")); let qualifies_result = subject.qualifies(&db, agrs_vec.as_slice(), gossip_source.clone()); - let handle_result = - subject.handle(&cryptde, &mut db, agrs_vec, gossip_source, &cpm_recipient); + let handle_result = subject.handle( + &cryptde, + &mut db, + agrs_vec, + gossip_source, + &vec![], + &cpm_recipient, + ); assert_eq!(Qualification::Matched, qualifies_result); let introduction = GossipBuilder::new(&db) @@ -1438,6 +1460,7 @@ mod tests { &mut dest_db, agrs_vec, src_root.node_addr_opt().unwrap().into(), + &vec![], &cpm_recipient, ); @@ -1471,6 +1494,7 @@ mod tests { &mut dest_db, agrs_vec, src_root.node_addr_opt().unwrap().into(), + &vec![], &cpm_recipient, ); @@ -1584,6 +1608,7 @@ mod tests { &mut dest_db, agrs_vec, dest_root.node_addr_opt().clone().unwrap().into(), + &vec![], &cpm_recipient, ); @@ -1605,6 +1630,7 @@ mod tests { &mut dest_db, agrs_vec, gossip_source, + &vec![], &cpm_recipient, ); @@ -1863,6 +1889,7 @@ mod tests { &mut dest_db, agrs.clone(), gossip_source, + &vec![], &cpm_recipient, ); @@ -1909,6 +1936,7 @@ mod tests { &mut dest_db, agrs.clone(), gossip_source, + &vec![], &cpm_recipient, ); @@ -1958,6 +1986,7 @@ mod tests { &mut dest_db, agrs.clone(), gossip_source, + &vec![], &cpm_recipient, ); @@ -1987,6 +2016,7 @@ mod tests { &mut dest_db, agrs.clone(), gossip_source, + &vec![], &cpm_recipient, ); @@ -2043,6 +2073,7 @@ mod tests { &mut dest_db, agrs.clone(), gossip_source, + &vec![], &cpm_recipient, ); @@ -2294,6 +2325,7 @@ mod tests { &mut dest_db, agrs_vec, gossip_source, + &vec![], &cpm_recipient, ); @@ -2524,7 +2556,14 @@ mod tests { .build(); let agrs: Vec = gossip.try_into().unwrap(); - let result = subject.handle(cryptde, &mut node_a_db, agrs, gossip_source, &cpm_recipient); + let result = subject.handle( + cryptde, + &mut node_a_db, + agrs, + gossip_source, + &vec![], + &cpm_recipient, + ); assert_eq!(result, GossipAcceptanceResult::Ignored); } @@ -2556,6 +2595,7 @@ mod tests { &mut root_db, agrs, src_node_socket_addr, + &vec![], &cpm_recipient, ); @@ -2594,6 +2634,7 @@ mod tests { &mut root_db, agrs, src_node_socket_addr, + &vec![], &cpm_recipient, ); @@ -2639,6 +2680,7 @@ mod tests { &mut root_db, agrs, src_node_socket_addr, + &vec![], &cpm_recipient, ); @@ -2678,6 +2720,7 @@ mod tests { &mut root_db, agrs, src_node_socket_addr, + &vec![], &cpm_recipient, ); @@ -2721,6 +2764,7 @@ mod tests { &mut dest_db, gossip.try_into().unwrap(), src_root.node_addr_opt().clone().unwrap().into(), + &vec![], ); assert_eq!(result, GossipAcceptanceResult::Ignored); @@ -2804,6 +2848,7 @@ mod tests { &mut dest_db, gossip.try_into().unwrap(), src_node.node_addr_opt().unwrap().into(), + &vec![], ); assert_eq!(GossipAcceptanceResult::Ignored, result); @@ -2818,7 +2863,12 @@ mod tests { let subject = make_subject(&root_node_cryptde); let before = time_t_timestamp(); - let result = subject.handle(&mut dest_db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + gossip.try_into().unwrap(), + gossip_source, + &vec![], + ); let after = time_t_timestamp(); assert_eq!(GossipAcceptanceResult::Accepted, result); @@ -2852,7 +2902,12 @@ mod tests { let subject = make_subject(&root_node_cryptde); let before = time_t_timestamp(); - let result = subject.handle(&mut dest_db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + gossip.try_into().unwrap(), + gossip_source, + &vec![], + ); let after = time_t_timestamp(); let expected_acceptance_gossip = GossipBuilder::new(&dest_db) @@ -2918,7 +2973,12 @@ mod tests { let subject = make_subject(&root_node_cryptde); let before = time_t_timestamp(); - let result = subject.handle(&mut dest_db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + gossip.try_into().unwrap(), + gossip_source, + &vec![], + ); let after = time_t_timestamp(); let expected_acceptance_gossip_1 = GossipBuilder::new(&dest_db) @@ -3009,7 +3069,12 @@ mod tests { let (gossip, debut_node, gossip_source) = make_debut(2345, Mode::Standard); let subject = make_subject(&root_node_cryptde); - let result = subject.handle(&mut dest_db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + gossip.try_into().unwrap(), + gossip_source, + &vec![], + ); let expected_acceptance_gossip_2 = GossipBuilder::new(&dest_db) .node(existing_node_2_key, true) @@ -3093,7 +3158,12 @@ mod tests { let (gossip, debut_node, gossip_source) = make_debut(2345, Mode::Standard); let subject = make_subject(&root_node_cryptde); - let result = subject.handle(&mut dest_db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + gossip.try_into().unwrap(), + gossip_source, + &vec![], + ); let expected_acceptance_gossip = GossipBuilder::new(&dest_db) .node(existing_node_5_key, true) @@ -3143,7 +3213,12 @@ mod tests { let gossip_source: SocketAddr = src_node.node_addr_opt().unwrap().into(); let subject = make_subject(main_cryptde()); - let result = subject.handle(&mut dest_db, debut.try_into().unwrap(), gossip_source); + let result = subject.handle( + &mut dest_db, + debut.try_into().unwrap(), + gossip_source, + &vec![], + ); assert_eq!(GossipAcceptanceResult::Ignored, result); assert_eq!( @@ -3177,7 +3252,7 @@ mod tests { let subject = make_subject(main_cryptde()); let begin_at = time_t_timestamp(); - let result = subject.handle(&mut dest_db, debut_agrs, gossip_source); + let result = subject.handle(&mut dest_db, debut_agrs, gossip_source, &vec![]); let end_at = time_t_timestamp(); assert_eq!(GossipAcceptanceResult::Accepted, result); @@ -3205,7 +3280,7 @@ mod tests { let gossip_source = src_node.node_addr_opt().unwrap().into(); let subject = make_subject(main_cryptde()); - let result = subject.handle(&mut dest_db, debut_agrs, gossip_source); + let result = subject.handle(&mut dest_db, debut_agrs, gossip_source, &vec![]); assert_eq!(result, GossipAcceptanceResult::Accepted); assert_eq!( @@ -3235,7 +3310,7 @@ mod tests { let gossip_source = src_node.node_addr_opt().unwrap().into(); let subject = make_subject(main_cryptde()); - let result = subject.handle(&mut dest_db, debut_agrs, gossip_source); + let result = subject.handle(&mut dest_db, debut_agrs, gossip_source, &vec![]); assert_eq!(result, GossipAcceptanceResult::Accepted); assert_eq!( @@ -3262,7 +3337,14 @@ mod tests { let system = System::new("introduction_gossip_handler_sends_cpm_for_neighborship_established"); - subject.handle(cryptde, &mut db, agrs, gossip_source, &cpm_recipient); + subject.handle( + cryptde, + &mut db, + agrs, + gossip_source, + &vec![], + &cpm_recipient, + ); System::current().stop(); assert_eq!(system.run(), 0); @@ -3297,7 +3379,7 @@ mod tests { let (gossip, pass_target, gossip_source) = make_pass(2345); let subject = make_subject(main_cryptde()); - let result = subject.handle(&mut db, gossip.try_into().unwrap(), gossip_source); + let result = subject.handle(&mut db, gossip.try_into().unwrap(), gossip_source, &vec![]); let expected_relay_gossip = GossipBuilder::new(&db) .node(root_node.public_key(), true) @@ -3329,6 +3411,7 @@ mod tests { &mut db, gossip.try_into().unwrap(), gossip_source, + &vec![], &cpm_recipient, ); @@ -3381,6 +3464,7 @@ mod tests { &mut db, gossip.try_into().unwrap(), gossip_source, + &vec![], &cpm_recipient, ); @@ -3403,6 +3487,41 @@ mod tests { assert!(initial_timestamp <= *timestamp && *timestamp <= final_timestamp); } + #[test] + fn handles_pass_target_that_is_a_part_of_a_different_connection_progress() { + let cryptde = main_cryptde(); + let root_node = make_node_record(1234, true); + let mut db = db_from_node(&root_node); + let subject = PassHandler::new(); + let (gossip, pass_target, gossip_source) = make_pass(2345); + let pass_target_ip_addr = pass_target.node_addr_opt().unwrap().ip_addr(); + let system = + System::new("handles_pass_target_that_is_a_part_of_a_different_connection_progress"); + let (cpm_recipient, recording_arc) = make_cpm_recipient(); + + let result = subject.handle( + cryptde, + &mut db, + gossip.try_into().unwrap(), + gossip_source, + &vec![pass_target_ip_addr], + &cpm_recipient, + ); + + System::current().stop(); + assert_eq!(system.run(), 0); + assert_eq!(result, GossipAcceptanceResult::Ignored); + let recording = recording_arc.lock().unwrap(); + let received_message: &ConnectionProgressMessage = recording.get_record(0); + assert_eq!( + received_message, + &ConnectionProgressMessage { + peer_addr: gossip_source.ip(), + event: ConnectionProgressEvent::PassLoopFound + } + ); + } + #[test] fn handles_pass_target_that_has_expired() { let cryptde = main_cryptde(); @@ -3425,6 +3544,7 @@ mod tests { &mut db, gossip.try_into().unwrap(), gossip_source, + &vec![], &cpm_recipient, ); @@ -3507,6 +3627,7 @@ mod tests { &mut dest_db, gossip.try_into().unwrap(), node_a.node_addr_opt().unwrap().into(), + &vec![], ); let after = time_t_timestamp(); @@ -3622,6 +3743,7 @@ mod tests { &mut dest_db, gossip.try_into().unwrap(), src_node.node_addr_opt().unwrap().into(), + &vec![], ); let after = time_t_timestamp(); @@ -3708,6 +3830,7 @@ mod tests { &mut dest_db, gossip.try_into().unwrap(), src_root.node_addr_opt().unwrap().into(), + &vec![], ); let after = time_t_timestamp(); diff --git a/node/src/neighborhood/mod.rs b/node/src/neighborhood/mod.rs index 9d7ee2078..b8d09ebbc 100644 --- a/node/src/neighborhood/mod.rs +++ b/node/src/neighborhood/mod.rs @@ -266,38 +266,41 @@ impl Handler for Neighborhood { type Result = (); fn handle(&mut self, msg: ConnectionProgressMessage, ctx: &mut Self::Context) -> Self::Result { - if let Ok(connection_progress) = self + match self .overall_connection_status - .get_connection_progress_by_ip(msg.peer_addr) + .get_connection_progress_to_modify(&msg) { - OverallConnectionStatus::update_connection_stage( - connection_progress, - msg.event.clone(), - &self.logger, - ); - match msg.event { - ConnectionProgressEvent::TcpConnectionSuccessful => { - self.send_ask_about_debut_gossip_message(ctx, msg.peer_addr); - } - ConnectionProgressEvent::IntroductionGossipReceived(_) - | ConnectionProgressEvent::StandardGossipReceived => { - self.overall_connection_status - .update_ocs_stage_and_send_message_to_ui( - OverallConnectionStage::ConnectedToNeighbor, - self.node_to_ui_recipient_opt - .as_ref() - .expect("UI Gateway is unbound"), - &self.logger, - ); + Ok(connection_progress) => { + OverallConnectionStatus::update_connection_stage( + connection_progress, + msg.event.clone(), + &self.logger, + ); + match msg.event { + ConnectionProgressEvent::TcpConnectionSuccessful => { + self.send_ask_about_debut_gossip_message(ctx, msg.peer_addr); + } + ConnectionProgressEvent::IntroductionGossipReceived(_) + | ConnectionProgressEvent::StandardGossipReceived => { + self.overall_connection_status + .update_ocs_stage_and_send_message_to_ui( + OverallConnectionStage::ConnectedToNeighbor, + self.node_to_ui_recipient_opt + .as_ref() + .expect("UI Gateway is unbound"), + &self.logger, + ); + } + _ => (), } - _ => (), } - } else { - trace!( - self.logger, - "An unnecessary ConnectionProgressMessage received from IP Address: {:?}", - msg.peer_addr - ); + Err(e) => { + trace!( + self.logger, + "Found unnecessary connection progress message - {}", + e + ); + } } } } @@ -723,11 +726,17 @@ impl Neighborhood { fn handle_agrs(&mut self, agrs: Vec, gossip_source: SocketAddr) { let ignored_node_name = self.gossip_source_name(&agrs, gossip_source); let gossip_record_count = agrs.len(); + let connection_progress_peers = self.overall_connection_status.get_peer_addrs(); let acceptance_result = self .gossip_acceptor_opt .as_ref() .expect("Gossip Acceptor wasn't created.") - .handle(&mut self.neighborhood_database, agrs, gossip_source); + .handle( + &mut self.neighborhood_database, + agrs, + gossip_source, + &connection_progress_peers, + ); match acceptance_result { GossipAcceptanceResult::Accepted => self.gossip_to_neighbors(), GossipAcceptanceResult::Reply(next_debut, target_key, target_node_addr) => { @@ -1808,7 +1817,7 @@ mod tests { } #[test] - pub fn neighborhood_logs_with_trace_if_it_receives_a_cpm_with_an_unknown_peer_addr() { + fn neighborhood_logs_with_trace_if_it_receives_a_cpm_with_an_unknown_peer_addr() { init_test_logging(); let known_peer = make_ip(1); let unknown_peer = make_ip(2); @@ -1835,11 +1844,59 @@ mod tests { System::current().stop(); assert_eq!(system.run(), 0); TestLogHandler::new().exists_log_containing(&format!( - "TRACE: Neighborhood: An unnecessary ConnectionProgressMessage received from IP Address: {:?}", + "TRACE: Neighborhood: Found unnecessary connection progress message - No peer found with the IP Address: {:?}", unknown_peer )); } + #[test] + fn neighborhood_logs_with_trace_if_it_receives_a_cpm_with_a_pass_target_that_is_a_part_of_a_different_connection_progress( + ) { + init_test_logging(); + let peer_1 = make_ip(1); + let peer_2 = make_ip(2); + let this_node_addr = NodeAddr::new(&IpAddr::from_str("111.111.111.111").unwrap(), &[8765]); + let initial_node_descriptors = + vec![make_node_descriptor(peer_1), make_node_descriptor(peer_2)]; + let neighborhood_config = NeighborhoodConfig { + mode: NeighborhoodMode::Standard( + this_node_addr, + initial_node_descriptors, + rate_pack(100), + ), + }; + let bootstrap_config = + bc_from_nc_plus(neighborhood_config, make_wallet("earning"), None, "test"); + let mut subject = Neighborhood::new(main_cryptde(), &bootstrap_config); + subject + .overall_connection_status + .get_connection_progress_by_ip(peer_1) + .unwrap() + .connection_stage = ConnectionStage::TcpConnectionEstablished; + subject + .overall_connection_status + .get_connection_progress_by_ip(peer_2) + .unwrap() + .connection_stage = ConnectionStage::TcpConnectionEstablished; + let addr = subject.start(); + let cpm_recipient = addr.clone().recipient::(); + let system = System::new("testing"); + let cpm = ConnectionProgressMessage { + peer_addr: peer_2, + event: ConnectionProgressEvent::PassGossipReceived(peer_1), + }; + + cpm_recipient.try_send(cpm).unwrap(); + + System::current().stop(); + assert_eq!(system.run(), 0); + TestLogHandler::new().exists_log_containing(&format!( + "TRACE: Neighborhood: Found unnecessary connection progress message - Pass target with \ + IP Address: {:?} is already a part of different connection progress.", + peer_1 + )); + } + #[test] pub fn neighborhood_handles_connection_progress_message_with_tcp_connection_established() { let (node_ip_addr, node_descriptor) = make_node(1); @@ -3456,7 +3513,8 @@ mod tests { System::current().stop(); system.run(); let mut handle_params = handle_params_arc.lock().unwrap(); - let (call_database, call_agrs, call_gossip_source) = handle_params.remove(0); + let (call_database, call_agrs, call_gossip_source, connection_progress_peers) = + handle_params.remove(0); assert!(handle_params.is_empty()); assert_eq!(&subject_node, call_database.root()); assert_eq!(1, call_database.keys().len()); @@ -3464,6 +3522,8 @@ mod tests { assert_eq!(agrs, call_agrs); let actual_gossip_source: SocketAddr = subject_node.node_addr_opt().unwrap().into(); assert_eq!(actual_gossip_source, call_gossip_source); + let neighbor_ip = neighbor.node_addr_opt().unwrap().ip_addr(); + assert_eq!(connection_progress_peers, vec![neighbor_ip]); } #[test] @@ -3568,6 +3628,7 @@ mod tests { database: &mut NeighborhoodDatabase, _agrs: Vec, _gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], ) -> GossipAcceptanceResult { let non_root_database_keys = database .keys() @@ -3678,6 +3739,48 @@ mod tests { assert_eq!(accountant_recording.len(), 1); } + #[test] + fn neighborhood_ignores_gossip_if_it_receives_a_pass_target_which_is_a_part_of_a_different_connection_progress( + ) { + init_test_logging(); + let handle_params_arc = Arc::new(Mutex::new(vec![])); + let gossip_acceptor = GossipAcceptorMock::new() + .handle_params(&handle_params_arc) + .handle_result(GossipAcceptanceResult::Ignored); + let (node_to_ui_recipient, _) = make_node_to_ui_recipient(); + let peer_1 = make_node_record(1234, true); + let peer_2 = make_node_record(6721, true); + let desc_1 = peer_1.node_descriptor(Chain::Dev, main_cryptde()); + let desc_2 = peer_2.node_descriptor(Chain::Dev, main_cryptde()); + let this_node = make_node_record(7777, true); + let initial_node_descriptors = vec![desc_1, desc_2]; + let neighborhood_config = NeighborhoodConfig { + mode: NeighborhoodMode::Standard( + this_node.node_addr_opt().unwrap(), + initial_node_descriptors, + rate_pack(100), + ), + }; + let bootstrap_config = + bc_from_nc_plus(neighborhood_config, make_wallet("earning"), None, "test"); + let mut subject = Neighborhood::new(main_cryptde(), &bootstrap_config); + subject.node_to_ui_recipient_opt = Some(node_to_ui_recipient); + subject.gossip_acceptor_opt = Some(Box::new(gossip_acceptor)); + let mut peer_2_db = db_from_node(&peer_2); + peer_2_db.add_node(peer_1.clone()).unwrap(); + peer_2_db.add_arbitrary_full_neighbor(peer_2.public_key(), peer_1.public_key()); + let peer_2_socket_addr: SocketAddr = peer_2.metadata.node_addr_opt.unwrap().into(); + let pass_gossip = GossipBuilder::new(&peer_2_db) + .node(peer_1.public_key(), true) + .build(); + let agrs: Vec = pass_gossip.try_into().unwrap(); + + subject.handle_agrs(agrs, peer_2_socket_addr); + + TestLogHandler::new() + .exists_log_containing(&format!("Gossip from {} ignored", peer_2_socket_addr)); + } + #[test] fn neighborhood_updates_ocs_stage_and_sends_message_to_the_ui_when_first_route_can_be_made() { init_test_logging(); @@ -3757,6 +3860,7 @@ mod tests { database: &mut NeighborhoodDatabase, _agrs: Vec, _gossip_source: SocketAddr, + _connection_progress_peers: &[IpAddr], ) -> GossipAcceptanceResult { let half_neighbor_keys = database .root() @@ -5405,6 +5509,7 @@ mod tests { NeighborhoodDatabase, Vec, SocketAddr, + Vec, )>, >, >, @@ -5417,11 +5522,14 @@ mod tests { database: &mut NeighborhoodDatabase, agrs: Vec, gossip_source: SocketAddr, + connection_progress_peers: &[IpAddr], ) -> GossipAcceptanceResult { - self.handle_params - .lock() - .unwrap() - .push((database.clone(), agrs, gossip_source)); + self.handle_params.lock().unwrap().push(( + database.clone(), + agrs, + gossip_source, + connection_progress_peers.to_vec(), + )); self.handle_results.borrow_mut().remove(0) } } @@ -5442,6 +5550,7 @@ mod tests { NeighborhoodDatabase, Vec, SocketAddr, + Vec, )>, >, >, diff --git a/node/src/neighborhood/overall_connection_status.rs b/node/src/neighborhood/overall_connection_status.rs index 9bbc63d40..7bec57187 100644 --- a/node/src/neighborhood/overall_connection_status.rs +++ b/node/src/neighborhood/overall_connection_status.rs @@ -3,7 +3,9 @@ use crate::neighborhood::overall_connection_status::ConnectionStageErrors::{ NoGossipResponseReceived, PassLoopFound, TcpConnectionFailed, }; -use crate::sub_lib::neighborhood::{ConnectionProgressEvent, NodeDescriptor}; +use crate::sub_lib::neighborhood::{ + ConnectionProgressEvent, ConnectionProgressMessage, NodeDescriptor, +}; use actix::Recipient; use masq_lib::logger::Logger; use masq_lib::messages::{ToMessageBody, UiConnectionChangeBroadcast, UiConnectionStage}; @@ -224,6 +226,40 @@ impl OverallConnectionStatus { } } + pub fn get_peer_addrs(&self) -> Vec { + self.progress + .iter() + .map(|connection_progress| connection_progress.current_peer_addr) + .collect() + } + + pub fn get_connection_progress_to_modify( + &mut self, + msg: &ConnectionProgressMessage, + ) -> Result<&mut ConnectionProgress, String> { + if let ConnectionProgressEvent::PassGossipReceived(pass_target) = msg.event { + // Check if Pass Target can potentially create a duplicate ConnectionProgress + let is_duplicate = self.get_peer_addrs().contains(&pass_target); + + if is_duplicate { + return Err(format!( + "Pass target with IP Address: {:?} is already a \ + part of different connection progress.", + pass_target + )); + } + }; + + if let Ok(connection_progress) = self.get_connection_progress_by_ip(msg.peer_addr) { + Ok(connection_progress) + } else { + Err(format!( + "No peer found with the IP Address: {:?}", + msg.peer_addr + )) + } + } + pub fn update_ocs_stage_and_send_message_to_ui( &mut self, new_stage: OverallConnectionStage, @@ -467,6 +503,22 @@ mod tests { ); } + #[test] + fn can_receive_current_peer_addrs() { + let peer_1 = make_ip(1); + let peer_2 = make_ip(2); + let peer_3 = make_ip(3); + let subject = OverallConnectionStatus::new(vec![ + make_node_descriptor(peer_1), + make_node_descriptor(peer_2), + make_node_descriptor(peer_3), + ]); + + let result = subject.get_peer_addrs(); + + assert_eq!(result, vec![peer_1, peer_2, peer_3]); + } + #[test] fn receives_an_error_in_receiving_connection_progress_from_unknown_initial_node_desc() { let known_desc = make_node_descriptor(make_ip(1)); diff --git a/port_exposer/Cargo.lock b/port_exposer/Cargo.lock index c9ee1705d..5161d3815 100644 --- a/port_exposer/Cargo.lock +++ b/port_exposer/Cargo.lock @@ -20,7 +20,7 @@ checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "port_exposer" -version = "0.6.3" +version = "0.7.0" dependencies = [ "default-net", ]