Fix Gossip Pushes going to invalid addresses (#1858)
This commit is contained in:
		| @@ -189,7 +189,7 @@ impl ClusterInfo { | ||||
|             .values() | ||||
|             .filter_map(|x| x.value.contact_info()) | ||||
|             .filter(|x| x.id != me) | ||||
|             .filter(|x| ClusterInfo::is_valid_address(&x.rpc)) | ||||
|             .filter(|x| ContactInfo::is_valid_address(&x.rpc)) | ||||
|             .cloned() | ||||
|             .collect() | ||||
|     } | ||||
| @@ -202,7 +202,7 @@ impl ClusterInfo { | ||||
|             .values() | ||||
|             .filter_map(|x| x.value.contact_info()) | ||||
|             .filter(|x| x.id != me) | ||||
|             .filter(|x| ClusterInfo::is_valid_address(&x.ncp)) | ||||
|             .filter(|x| ContactInfo::is_valid_address(&x.ncp)) | ||||
|             .cloned() | ||||
|             .collect() | ||||
|     } | ||||
| @@ -216,7 +216,7 @@ impl ClusterInfo { | ||||
|             .values() | ||||
|             .filter_map(|x| x.value.contact_info()) | ||||
|             .filter(|x| x.id != me) | ||||
|             .filter(|x| ClusterInfo::is_valid_address(&x.tvu)) | ||||
|             .filter(|x| ContactInfo::is_valid_address(&x.tvu)) | ||||
|             .cloned() | ||||
|             .collect() | ||||
|     } | ||||
| @@ -230,7 +230,7 @@ impl ClusterInfo { | ||||
|             .values() | ||||
|             .filter_map(|x| x.value.contact_info()) | ||||
|             .filter(|x| x.id != me) | ||||
|             .filter(|x| ClusterInfo::is_valid_address(&x.tpu)) | ||||
|             .filter(|x| ContactInfo::is_valid_address(&x.tpu)) | ||||
|             .cloned() | ||||
|             .collect() | ||||
|     } | ||||
| @@ -898,18 +898,6 @@ impl ClusterInfo { | ||||
|             }).unwrap() | ||||
|     } | ||||
|  | ||||
|     fn is_valid_ip(addr: IpAddr) -> bool { | ||||
|         !(addr.is_unspecified() || addr.is_multicast()) | ||||
|         // || (addr.is_loopback() && !cfg_test)) | ||||
|         // TODO: boot loopback in production networks | ||||
|     } | ||||
|     /// port must not be 0 | ||||
|     /// ip must be specified and not mulitcast | ||||
|     /// loopback ip is only allowed in tests | ||||
|     pub fn is_valid_address(addr: &SocketAddr) -> bool { | ||||
|         (addr.port() != 0) && Self::is_valid_ip(addr.ip()) | ||||
|     } | ||||
|  | ||||
|     pub fn spy_node() -> (NodeInfo, UdpSocket) { | ||||
|         let (_, gossip_socket) = bind_in_range(FULLNODE_PORT_RANGE).unwrap(); | ||||
|         let pubkey = Keypair::new().pubkey(); | ||||
| @@ -1057,6 +1045,29 @@ mod tests { | ||||
|     use std::sync::{Arc, RwLock}; | ||||
|     use window::default_window; | ||||
|  | ||||
|     #[test] | ||||
|     fn test_cluster_spy_gossip() { | ||||
|         //check that gossip doesn't try to push to invalid addresses | ||||
|         let node = Node::new_localhost(); | ||||
|         let (spy, _) = ClusterInfo::spy_node(); | ||||
|         let cluster_info = Arc::new(RwLock::new( | ||||
|             ClusterInfo::new(node.info).expect("ClusterInfo::new"), | ||||
|         )); | ||||
|         cluster_info.write().unwrap().insert_info(spy); | ||||
|         cluster_info | ||||
|             .write() | ||||
|             .unwrap() | ||||
|             .gossip | ||||
|             .refresh_push_active_set(); | ||||
|         let reqs = cluster_info.write().unwrap().gossip_request(); | ||||
|         //assert none of the addrs are invalid. | ||||
|         reqs.iter().all(|(addr, _)| { | ||||
|             let res = ContactInfo::is_valid_address(addr); | ||||
|             assert!(res); | ||||
|             res | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_cluster_info_new() { | ||||
|         let d = NodeInfo::new_localhost(Keypair::new().pubkey(), timestamp()); | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
|  | ||||
| use bincode::serialized_size; | ||||
| use bloom::Bloom; | ||||
| use contact_info::ContactInfo; | ||||
| use crds::{Crds, VersionedCrdsValue}; | ||||
| use crds_gossip_error::CrdsGossipError; | ||||
| use crds_value::{CrdsValue, CrdsValueLabel}; | ||||
| @@ -177,6 +178,11 @@ impl CrdsGossipPush { | ||||
|             if new_items.get(&val.0.pubkey()).is_some() { | ||||
|                 continue; | ||||
|             } | ||||
|             if let Some(contact) = val.1.value.contact_info() { | ||||
|                 if !ContactInfo::is_valid_address(&contact.ncp) { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|             let bloom = Bloom::random(network_size, 0.1, 1024 * 8 * 4); | ||||
|             new_items.insert(val.0.pubkey(), bloom); | ||||
|             if new_items.len() == need { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ extern crate solana_sdk; | ||||
|  | ||||
| use solana::blob_fetch_stage::BlobFetchStage; | ||||
| use solana::cluster_info::{ClusterInfo, Node, NodeInfo}; | ||||
| use solana::contact_info::ContactInfo; | ||||
| use solana::entry::{reconstruct_entries_from_blobs, Entry}; | ||||
| use solana::fullnode::{Fullnode, FullnodeReturnType}; | ||||
| use solana::leader_scheduler::{make_active_set_entries, LeaderScheduler, LeaderSchedulerConfig}; | ||||
| @@ -1621,7 +1622,7 @@ fn test_broadcast_last_tick() { | ||||
|  | ||||
| fn mk_client(leader: &NodeInfo) -> ThinClient { | ||||
|     let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); | ||||
|     assert!(ClusterInfo::is_valid_address(&leader.tpu)); | ||||
|     assert!(ContactInfo::is_valid_address(&leader.tpu)); | ||||
|     ThinClient::new(leader.rpc, leader.tpu, transactions_socket) | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user