diff --git a/CHANGELOG.md b/CHANGELOG.md index 5783c61..d418f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Reject messages from invalid peers (P1.10-3) + ### Changed - Move to stable MSRV 1.85 - Move to rust edition 2024 +- Limit the number of peers accepted in a single Nodes message (P1.10-4) +- Increase the POW produced during ID generation (P1.10-2) ## [0.7.0] - 2024-10-21 diff --git a/src/handling.rs b/src/handling.rs index e0378ac..579c6f2 100644 --- a/src/handling.rs +++ b/src/handling.rs @@ -115,6 +115,7 @@ impl MessageHandler { let src = remote_peer_addr.ip(); if !PeerNode::verify_header(header, &src) { error!("Invalid Id {header:?} - from {src}"); + continue; } let remote_peer = PeerNode::from_socket( @@ -278,6 +279,9 @@ impl MessageHandler { .iter() //filter out my ID to avoid loopback .filter(|&n| &n.id != self.my_header.binary_id().as_binary()) + // Limit the number of peers accepted in a single Nodes message to a + // reasonable bound + .take(K_K * 2) .filter(|&n| { let h = self.my_header.binary_id().calculate_distance(&n.id); match h { diff --git a/src/kbucket/bucket.rs b/src/kbucket/bucket.rs index beef4e0..fca274f 100644 --- a/src/kbucket/bucket.rs +++ b/src/kbucket/bucket.rs @@ -56,7 +56,7 @@ pub enum NodeInsertError { MismatchVersion(TNode, Version), } -impl<'a, TNode> NodeInsertOk<'a, TNode> { +impl NodeInsertOk<'_, TNode> { /// Returns an optional reference to the node pending eviction. pub fn pending_eviction(&self) -> Option<&TNode> { match self { @@ -325,7 +325,25 @@ mod tests { #[test] fn test_lru_base_5secs() -> Result<()> { + // Create all the nodes at the beginning to ensure that PoW is not a + // factor in the test timing. let root = PeerNode::generate("127.0.0.1:666", 0)?; + let node1 = PeerNode::generate("192.168.1.1:8080", 0)?; + let node1_copy = PeerNode::generate("192.168.1.1:8080", 0)?; + let node1_copy2 = PeerNode::generate("192.168.1.1:8080", 0)?; + let node2 = PeerNode::generate("192.168.1.2:8080", 0)?; + + let mut additionals = vec![]; + for i in 2..21 { + additionals.push(PeerNode::generate( + &format!("192.168.1.{}:8080", i)[..], + 0, + )?); + } + + let pending = PeerNode::generate("192.168.1.21:8080", 0)?; + let pending_2 = PeerNode::generate("192.168.1.21:8080", 0)?; + let mut config = BucketConfig::default(); config.node_evict_after = Duration::from_millis(1000); config.node_ttl = Duration::from_secs(5); @@ -333,9 +351,7 @@ mod tests { let mut route_table = Tree::new(root, config); let bucket = route_table.bucket_for_test(); - let node1 = PeerNode::generate("192.168.1.1:8080", 0)?; let id_node1 = node1.id().as_binary().clone(); - let node1_copy = PeerNode::generate("192.168.1.1:8080", 0)?; match bucket.insert(node1).expect("This should return an ok()") { NodeInsertOk::Inserted { .. } => {} _ => assert!(false), @@ -351,7 +367,6 @@ mod tests { _ => assert!(false), } assert_eq!(Some(&id_node1), bucket.last_id()); - let node2 = PeerNode::generate("192.168.1.2:8080", 0)?; let id_node2 = node2.id().as_binary().clone(); match bucket.insert(node2).expect("This should return an ok()") { @@ -364,7 +379,7 @@ mod tests { assert_eq!(Some(&id_node1), bucket.least_used_id()); match bucket - .insert(PeerNode::generate("192.168.1.1:8080", 0)?) + .insert(node1_copy2) .expect("This should return an ok()") { NodeInsertOk::Updated { .. } => {} @@ -378,14 +393,8 @@ mod tests { assert_eq!(&id_node2, a.unwrap().id().as_binary()); assert_eq!(Some(&id_node1), bucket.last_id()); assert_eq!(Some(&id_node1), bucket.least_used_id()); - for i in 2..21 { - match bucket - .insert(PeerNode::generate( - &format!("192.168.1.{}:8080", i)[..], - 0, - )?) - .expect("This should return an ok()") - { + for n in additionals { + match bucket.insert(n).expect("This should return an ok()") { NodeInsertOk::Inserted { .. } => { assert!(bucket.pick::().count() <= K_BETA); } @@ -393,7 +402,6 @@ mod tests { } } assert_eq!(bucket.pick::().count(), K_BETA); - let pending = PeerNode::generate("192.168.1.21:8080", 0)?; let pending_id = pending.id().as_binary().clone(); match bucket.insert(pending).expect_err("this should be error") { NodeInsertError::Full(pending) => { @@ -409,9 +417,9 @@ mod tests { &pending_id ); thread::sleep(Duration::from_secs(1)); - let pending = - PeerNode::generate("192.168.1.21:8080", 0)?; - match bucket.insert(pending).expect("this should be ok") + match bucket + .insert(pending_2) + .expect("this should be ok") { NodeInsertOk::Inserted { inserted: _ } => {} v => { diff --git a/src/lib.rs b/src/lib.rs index 03621fa..6da59e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ const K_K: usize = get_k_k(); const K_ID_LEN_BYTES: usize = 16; const K_NONCE_LEN: usize = 4; const K_DIFF_MIN_BIT: usize = 8; -const K_DIFF_PRODUCED_BIT: usize = 8; +const K_DIFF_PRODUCED_BIT: usize = 20; const fn get_k_k() -> usize { match option_env!("KADCAST_K") { diff --git a/src/transport/encoding/raptorq.rs b/src/transport/encoding/raptorq.rs index 3144046..01e9560 100644 --- a/src/transport/encoding/raptorq.rs +++ b/src/transport/encoding/raptorq.rs @@ -62,7 +62,7 @@ impl BroadcastPayload { Ok(hasher.finalize().into()) } } -impl<'a> ChunkedPayload<'a> { +impl ChunkedPayload<'_> { fn ray_id(&self) -> [u8; RAY_ID_SIZE] { self.0.gossip_frame[0..RAY_ID_SIZE] .try_into()