From 25e34f00758c0ca8a119ee1a8ff75a0f6d3df3f5 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 12:23:18 +0100 Subject: [PATCH 01/12] simple test --- examples/sloppyness_measure.rs | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 examples/sloppyness_measure.rs diff --git a/examples/sloppyness_measure.rs b/examples/sloppyness_measure.rs new file mode 100644 index 00000000..98fe67b4 --- /dev/null +++ b/examples/sloppyness_measure.rs @@ -0,0 +1,47 @@ +use std::{collections::HashSet, net::IpAddr}; + +use flume::Iter; +use mainline::{Dht, Id, Node}; +use tracing::Level; + + +fn distance(target: Id, node: &Node) -> u8 { + target.distance(node.id()) +} + +fn print_distances(nodes: &Vec, target: Id) { + for node in nodes.iter() { + let distance = target.distance(node.id()); + println!("Distance: {}, {}", distance, node.id()); + } +} + +fn main() { + tracing_subscriber::fmt().with_max_level(Level::WARN).init(); + + let k = 20; // Not really k but we take the k closest nodes into account. + let target = Id::random(); + let mut all_ips: HashSet = HashSet::new(); + + println!("Sloppyness test - Counting all IP addresses around a random target_key={target} k={k}. Each lookup round starts with a clear routing table and a new DHT Id."); + + for lookups in 1.. { + let mut dht = Dht::client().unwrap(); + let nodes = dht.find_node(target).unwrap(); + let closest_nodes: Vec = nodes.into_iter().take(k).collect(); + let ips = closest_nodes.iter().map(|node| node.address().ip()); + for ip in ips { + all_ips.insert(ip); + } + + let closest_node = closest_nodes.first().expect("Closest node not found."); + let closest_distance = distance(target, closest_node); + println!( + "lookup={} Ips found {}. Closest node distance: {}", + lookups, + all_ips.len(), + closest_distance + ); + dht.shutdown(); + } +} From 82d4f5b973a9393a466456c263561a6cfaab82fd Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 12:30:47 +0100 Subject: [PATCH 02/12] renamed file --- examples/{sloppyness_measure.rs => count_ips_close_to_key.rs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename examples/{sloppyness_measure.rs => count_ips_close_to_key.rs} (88%) diff --git a/examples/sloppyness_measure.rs b/examples/count_ips_close_to_key.rs similarity index 88% rename from examples/sloppyness_measure.rs rename to examples/count_ips_close_to_key.rs index 98fe67b4..16e6a429 100644 --- a/examples/sloppyness_measure.rs +++ b/examples/count_ips_close_to_key.rs @@ -23,7 +23,7 @@ fn main() { let target = Id::random(); let mut all_ips: HashSet = HashSet::new(); - println!("Sloppyness test - Counting all IP addresses around a random target_key={target} k={k}. Each lookup round starts with a clear routing table and a new DHT Id."); + println!("Count all IP addresses around a random target_key={target} k={k}. Each lookup round starts with a clear routing table and a new DHT Id."); for lookups in 1.. { let mut dht = Dht::client().unwrap(); From 71fbb5c98bdcf98a57ffe73fa7cfe15d242177eb Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 12:32:42 +0100 Subject: [PATCH 03/12] cleaned up code --- examples/count_ips_close_to_key.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 16e6a429..4996a4ed 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,20 +1,9 @@ use std::{collections::HashSet, net::IpAddr}; -use flume::Iter; use mainline::{Dht, Id, Node}; use tracing::Level; -fn distance(target: Id, node: &Node) -> u8 { - target.distance(node.id()) -} - -fn print_distances(nodes: &Vec, target: Id) { - for node in nodes.iter() { - let distance = target.distance(node.id()); - println!("Distance: {}, {}", distance, node.id()); - } -} fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); @@ -35,7 +24,7 @@ fn main() { } let closest_node = closest_nodes.first().expect("Closest node not found."); - let closest_distance = distance(target, closest_node); + let closest_distance = target.distance(closest_node.id()); println!( "lookup={} Ips found {}. Closest node distance: {}", lookups, From 02feb04bce83fc3373fde1e199986c0bae556af5 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 12:52:26 +0100 Subject: [PATCH 04/12] randomize bootstrap nodes --- examples/count_ips_close_to_key.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 4996a4ed..8dad492a 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,9 +1,23 @@ use std::{collections::HashSet, net::IpAddr}; -use mainline::{Dht, Id, Node}; +use mainline::{rpc::DEFAULT_BOOTSTRAP_NODES, Dht, Id, Node}; +use rand::{seq::SliceRandom, thread_rng}; use tracing::Level; +fn get_random_boostrap_nodes(all: &HashSet) -> Vec { + if all.len() < 4 { + let nodes = DEFAULT_BOOTSTRAP_NODES; + let nodes: Vec = nodes.into_iter().map(|node| node.to_string()).collect(); + return nodes; + } + let mut all: Vec = all.clone().into_iter().collect(); + let mut rng = thread_rng(); + all.shuffle(&mut rng); + let slice: Vec = all[..4].into_iter().map(|va| va.clone()).collect(); + slice +} + fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); @@ -11,16 +25,20 @@ fn main() { let k = 20; // Not really k but we take the k closest nodes into account. let target = Id::random(); let mut all_ips: HashSet = HashSet::new(); + let mut all_sockets: HashSet = HashSet::new(); println!("Count all IP addresses around a random target_key={target} k={k}. Each lookup round starts with a clear routing table and a new DHT Id."); for lookups in 1.. { - let mut dht = Dht::client().unwrap(); + let bootstrap = get_random_boostrap_nodes(&all_sockets); + let mut dht = Dht::builder().bootstrap(&bootstrap).build().unwrap(); let nodes = dht.find_node(target).unwrap(); let closest_nodes: Vec = nodes.into_iter().take(k).collect(); - let ips = closest_nodes.iter().map(|node| node.address().ip()); - for ip in ips { - all_ips.insert(ip); + let sockets = closest_nodes.iter().map(|node| node.address()); + for socket in sockets { + all_ips.insert(socket.ip()); + let socket_str = socket.to_string(); + all_sockets.insert(socket_str); } let closest_node = closest_nodes.first().expect("Closest node not found."); From 17591f418db874b8df004cc8720e9db1d145bc31 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 13:45:01 +0100 Subject: [PATCH 05/12] added more outputs, improved random bootstrap nodes --- examples/count_ips_close_to_key.rs | 44 ++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 8dad492a..7a5f8969 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,7 +1,7 @@ use std::{collections::HashSet, net::IpAddr}; use mainline::{rpc::DEFAULT_BOOTSTRAP_NODES, Dht, Id, Node}; -use rand::{seq::SliceRandom, thread_rng}; +use rand::{random, seq::SliceRandom, thread_rng}; use tracing::Level; @@ -18,6 +18,15 @@ fn get_random_boostrap_nodes(all: &HashSet) -> Vec { slice } +fn get_random_boostrap_nodes2() -> Vec { + let mut dht = Dht::client().unwrap(); + let nodes = dht.find_node(Id::random()).unwrap(); + dht.shutdown(); + let mut addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); + let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); + slice +} + fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); @@ -25,29 +34,40 @@ fn main() { let k = 20; // Not really k but we take the k closest nodes into account. let target = Id::random(); let mut all_ips: HashSet = HashSet::new(); - let mut all_sockets: HashSet = HashSet::new(); + let MAX_DISTANCE = 150; - println!("Count all IP addresses around a random target_key={target} k={k}. Each lookup round starts with a clear routing table and a new DHT Id."); + println!("Count all IP addresses around a random target_key={target} k={k} max_distance={MAX_DISTANCE}."); + let mut last_nodes: HashSet = HashSet::new(); for lookups in 1.. { - let bootstrap = get_random_boostrap_nodes(&all_sockets); + let bootstrap = get_random_boostrap_nodes2(); let mut dht = Dht::builder().bootstrap(&bootstrap).build().unwrap(); let nodes = dht.find_node(target).unwrap(); + let nodes: Vec = nodes.into_iter().filter(|node| target.distance(node.id()) < MAX_DISTANCE).collect(); let closest_nodes: Vec = nodes.into_iter().take(k).collect(); - let sockets = closest_nodes.iter().map(|node| node.address()); - for socket in sockets { - all_ips.insert(socket.ip()); - let socket_str = socket.to_string(); - all_sockets.insert(socket_str); + let sockets: HashSet = closest_nodes.iter().map(|node| node.address().ip()).collect(); + for socket in sockets.iter() { + all_ips.insert(socket.clone()); } - let closest_node = closest_nodes.first().expect("Closest node not found."); + if closest_nodes.is_empty() { + continue; + } + let closest_node = closest_nodes.first().unwrap(); let closest_distance = target.distance(closest_node.id()); + let furthest_node = closest_nodes.last().unwrap(); + let furthest_distance = target.distance(furthest_node.id()); + + let overlap_with_last_lookup: HashSet = sockets.intersection(&last_nodes).map(|ip| ip.clone()).collect(); + let overlap = overlap_with_last_lookup.len() as f64/k as f64; + last_nodes = sockets; println!( - "lookup={} Ips found {}. Closest node distance: {}", + "lookup={} Ips found {}. Closest node distance: {}, furthest node distance: {}, overlap with previous lookup {}%", lookups, all_ips.len(), - closest_distance + closest_distance, + furthest_distance, + (overlap*100 as f64) as usize ); dht.shutdown(); } From 676e99b997b11d7e77a802032521c09910eaf384 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Fri, 15 Nov 2024 14:26:14 +0100 Subject: [PATCH 06/12] more cleanup --- examples/count_ips_close_to_key.rs | 36 +++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 7a5f8969..0dfb6f99 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,22 +1,8 @@ use std::{collections::HashSet, net::IpAddr}; - -use mainline::{rpc::DEFAULT_BOOTSTRAP_NODES, Dht, Id, Node}; -use rand::{random, seq::SliceRandom, thread_rng}; +use mainline::{Dht, Id, Node}; use tracing::Level; -fn get_random_boostrap_nodes(all: &HashSet) -> Vec { - if all.len() < 4 { - let nodes = DEFAULT_BOOTSTRAP_NODES; - let nodes: Vec = nodes.into_iter().map(|node| node.to_string()).collect(); - return nodes; - } - let mut all: Vec = all.clone().into_iter().collect(); - let mut rng = thread_rng(); - all.shuffle(&mut rng); - let slice: Vec = all[..4].into_iter().map(|va| va.clone()).collect(); - slice -} fn get_random_boostrap_nodes2() -> Vec { let mut dht = Dht::client().unwrap(); @@ -27,21 +13,31 @@ fn get_random_boostrap_nodes2() -> Vec { slice } +fn init_dht(use_random_boostrap_nodes: bool) -> Dht { + if use_random_boostrap_nodes { + let bootstrap = get_random_boostrap_nodes2(); + return Dht::builder().bootstrap(&bootstrap).build().unwrap(); + } else { + Dht::client().unwrap() + } +} + fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); let k = 20; // Not really k but we take the k closest nodes into account. + const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. + const USE_RANDOM_BOOTSTRAP_NODES: bool = true; let target = Id::random(); let mut all_ips: HashSet = HashSet::new(); - let MAX_DISTANCE = 150; - - println!("Count all IP addresses around a random target_key={target} k={k} max_distance={MAX_DISTANCE}."); + println!("Count all IP addresses around a random target_key={target} k={k} max_distance={MAX_DISTANCE} random_boostrap={USE_RANDOM_BOOTSTRAP_NODES}."); + println!(); + let mut last_nodes: HashSet = HashSet::new(); for lookups in 1.. { - let bootstrap = get_random_boostrap_nodes2(); - let mut dht = Dht::builder().bootstrap(&bootstrap).build().unwrap(); + let mut dht = init_dht(USE_RANDOM_BOOTSTRAP_NODES); let nodes = dht.find_node(target).unwrap(); let nodes: Vec = nodes.into_iter().filter(|node| target.distance(node.id()) < MAX_DISTANCE).collect(); let closest_nodes: Vec = nodes.into_iter().take(k).collect(); From c09e2882a7fa4a656c586991efe0c223b8d14336 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Mon, 18 Nov 2024 10:22:43 +0100 Subject: [PATCH 07/12] added histogram --- Cargo.toml | 2 + examples/count_ips_close_to_key.rs | 126 ++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 601acc26..6f65385b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ document-features = "0.2.10" clap = { version = "4.4.8", features = ["derive"] } futures = "0.3.29" tracing-subscriber = "0.3" +ctrlc = "3.4.5" +histo = "1.0.0" [features] ## Enable [Dht::as_async()] to use [async_dht::AsyncDht] diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 0dfb6f99..0ac0945d 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,49 +1,51 @@ -use std::{collections::HashSet, net::IpAddr}; +use std::{collections::{HashMap, HashSet}, net::IpAddr, sync::mpsc::channel}; +use histo::Histogram; use mainline::{Dht, Id, Node}; use tracing::Level; - -fn get_random_boostrap_nodes2() -> Vec { - let mut dht = Dht::client().unwrap(); - let nodes = dht.find_node(Id::random()).unwrap(); - dht.shutdown(); - let mut addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); - let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); - slice -} - -fn init_dht(use_random_boostrap_nodes: bool) -> Dht { - if use_random_boostrap_nodes { - let bootstrap = get_random_boostrap_nodes2(); - return Dht::builder().bootstrap(&bootstrap).build().unwrap(); - } else { - Dht::client().unwrap() - } -} +const k: usize = 20; // Not really k but we take the k closest nodes into account. +const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. +const USE_RANDOM_BOOTSTRAP_NODES: bool = false; fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); - let k = 20; // Not really k but we take the k closest nodes into account. - const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. - const USE_RANDOM_BOOTSTRAP_NODES: bool = true; let target = Id::random(); - let mut all_ips: HashSet = HashSet::new(); + let mut ip_hits: HashMap = HashMap::new(); + let (tx_interrupted, rx_interrupted) = channel(); + println!("Count all IP addresses around a random target_key={target} k={k} max_distance={MAX_DISTANCE} random_boostrap={USE_RANDOM_BOOTSTRAP_NODES}."); + println!("Press CTRL+C to show the histogram"); println!(); + + ctrlc::set_handler(move || { + println!(); + println!("Received Ctrl+C! Finishing current lookup. Hold on..."); + tx_interrupted.send(()).unwrap(); + }).expect("Error setting Ctrl-C handler"); let mut last_nodes: HashSet = HashSet::new(); - for lookups in 1.. { + let mut lookup_count = 0; + while rx_interrupted.try_recv().is_err() { + lookup_count += 1; let mut dht = init_dht(USE_RANDOM_BOOTSTRAP_NODES); let nodes = dht.find_node(target).unwrap(); let nodes: Vec = nodes.into_iter().filter(|node| target.distance(node.id()) < MAX_DISTANCE).collect(); let closest_nodes: Vec = nodes.into_iter().take(k).collect(); let sockets: HashSet = closest_nodes.iter().map(|node| node.address().ip()).collect(); for socket in sockets.iter() { - all_ips.insert(socket.clone()); + let previous = ip_hits.get(socket); + match previous { + Some(val) => { + ip_hits.insert(socket.clone(), val + 1); + } + None => { + ip_hits.insert(socket.clone(), 1); + } + }; } if closest_nodes.is_empty() { @@ -58,13 +60,81 @@ fn main() { let overlap = overlap_with_last_lookup.len() as f64/k as f64; last_nodes = sockets; println!( - "lookup={} Ips found {}. Closest node distance: {}, furthest node distance: {}, overlap with previous lookup {}%", - lookups, - all_ips.len(), + "lookup={:02} Ips found {}. Closest node distance: {}, furthest node distance: {}, overlap with previous lookup {}%", + lookup_count, + ip_hits.len(), closest_distance, furthest_distance, (overlap*100 as f64) as usize ); dht.shutdown(); + }; + + println!(); + println!("Histogram"); + print_histogram(ip_hits, lookup_count); +} + + +fn get_random_boostrap_nodes2() -> Vec { + let mut dht = Dht::client().unwrap(); + let nodes = dht.find_node(Id::random()).unwrap(); + dht.shutdown(); + let addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); + let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); + slice +} + +fn init_dht(use_random_boostrap_nodes: bool) -> Dht { + if use_random_boostrap_nodes { + let bootstrap = get_random_boostrap_nodes2(); + return Dht::builder().bootstrap(&bootstrap).build().unwrap(); + } else { + Dht::client().unwrap() } } + + +/* +Prints a histogram with the collected nodes +First column are the buckets indicate the hit rate. 84 .. 93 summerizes the nodes that get hit 3 to 12% of each lookup. +Second column indicates the number of nodes that this bucket contains. [19] means 19 nodes got hit with a probability of 3 to 12%. +Third column is a visualization of the number of nodes [19]. + +Example1: +84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore foud in almost all lookups. + +Example2: + 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +Within one lookup, 19 nodes got hit in 3 to 12% of the cases. These are rarely found therefore. + +Full example: + 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +12 .. 21 [ 2 ]: ∎∎ +21 .. 30 [ 3 ]: ∎∎∎ +30 .. 39 [ 2 ]: ∎∎ +39 .. 48 [ 3 ]: ∎∎∎ +48 .. 57 [ 0 ]: +57 .. 66 [ 0 ]: +66 .. 75 [ 0 ]: +75 .. 84 [ 1 ]: ∎ +84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +*/ +fn print_histogram(hits: HashMap, lookup_count: usize) { + /* + + */ + let mut histogram = Histogram::with_buckets(10); + let percents: HashMap = hits.into_iter().map(|(ip, hits)| { + let percent = (hits as f32 / lookup_count as f32) * 100 as f32; + (ip, percent as u64) + }).collect(); + + + for (_, percent) in percents.iter() { + histogram.add(percent.clone()); + }; + + println!("{}", histogram); +} \ No newline at end of file From f1880d0d242b134d30485d5a9907dff41ff1be76 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Mon, 18 Nov 2024 11:00:51 +0100 Subject: [PATCH 08/12] fixed comment --- examples/count_ips_close_to_key.rs | 54 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 0ac0945d..49307e3b 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -6,7 +6,7 @@ use tracing::Level; const k: usize = 20; // Not really k but we take the k closest nodes into account. const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. -const USE_RANDOM_BOOTSTRAP_NODES: bool = false; +const USE_RANDOM_BOOTSTRAP_NODES: bool = true; fn main() { @@ -76,39 +76,20 @@ fn main() { } -fn get_random_boostrap_nodes2() -> Vec { - let mut dht = Dht::client().unwrap(); - let nodes = dht.find_node(Id::random()).unwrap(); - dht.shutdown(); - let addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); - let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); - slice -} - -fn init_dht(use_random_boostrap_nodes: bool) -> Dht { - if use_random_boostrap_nodes { - let bootstrap = get_random_boostrap_nodes2(); - return Dht::builder().bootstrap(&bootstrap).build().unwrap(); - } else { - Dht::client().unwrap() - } -} - - /* Prints a histogram with the collected nodes -First column are the buckets indicate the hit rate. 84 .. 93 summerizes the nodes that get hit 3 to 12% of each lookup. +First column are the buckets indicating the hit rate. 3 .. 12 summerizes the nodes that get hit with a probability of 3 to 12% in each lookup. Second column indicates the number of nodes that this bucket contains. [19] means 19 nodes got hit with a probability of 3 to 12%. Third column is a visualization of the number of nodes [19]. -Example1: -84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ -Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore foud in almost all lookups. - -Example2: +Example1: 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ Within one lookup, 19 nodes got hit in 3 to 12% of the cases. These are rarely found therefore. +Example2: +84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore found in almost all lookups. + Full example: 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 12 .. 21 [ 2 ]: ∎∎ @@ -137,4 +118,23 @@ fn print_histogram(hits: HashMap, lookup_count: usize) { }; println!("{}", histogram); -} \ No newline at end of file +} + +fn get_random_boostrap_nodes2() -> Vec { + let mut dht = Dht::client().unwrap(); + let nodes = dht.find_node(Id::random()).unwrap(); + dht.shutdown(); + let addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); + let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); + slice +} + +fn init_dht(use_random_boostrap_nodes: bool) -> Dht { + if use_random_boostrap_nodes { + let bootstrap = get_random_boostrap_nodes2(); + return Dht::builder().bootstrap(&bootstrap).build().unwrap(); + } else { + Dht::client().unwrap() + } +} + From 1231f08d1e04456ee6ef4e0a092d62dbab43ffd9 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Mon, 25 Nov 2024 10:39:16 +0100 Subject: [PATCH 09/12] removed unnecessary imports --- examples/count_ips_close_to_key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 50cdb704..5af62c7f 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -6,7 +6,7 @@ use tracing::Level; const K: usize = 20; // Not really k but we take the k closest nodes into account. const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. -const USE_RANDOM_BOOTSTRAP_NODES: bool = true; +const USE_RANDOM_BOOTSTRAP_NODES: bool = false; fn main() { From 511917072c48395da0befa28943265535475d6ba Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Mon, 25 Nov 2024 12:56:19 +0100 Subject: [PATCH 10/12] format file --- examples/count_ips_close_to_key.rs | 66 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 5af62c7f..144161a5 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,14 +1,16 @@ -use std::{collections::{HashMap, HashSet}, net::IpAddr, sync::mpsc::channel}; use histo::Histogram; use mainline::{Dht, Id, Node}; +use std::{ + collections::{HashMap, HashSet}, + net::IpAddr, + sync::mpsc::channel, +}; use tracing::Level; - const K: usize = 20; // Not really k but we take the k closest nodes into account. const MAX_DISTANCE: u8 = 150; // Health check to not include outrageously distant nodes. const USE_RANDOM_BOOTSTRAP_NODES: bool = false; - fn main() { tracing_subscriber::fmt().with_max_level(Level::WARN).init(); @@ -16,7 +18,6 @@ fn main() { let mut ip_hits: HashMap = HashMap::new(); let (tx_interrupted, rx_interrupted) = channel(); - println!("Count all IP addresses around a random target_key={target} k={K} max_distance={MAX_DISTANCE} random_boostrap={USE_RANDOM_BOOTSTRAP_NODES}."); println!("Press CTRL+C to show the histogram"); println!(); @@ -25,17 +26,24 @@ fn main() { println!(); println!("Received Ctrl+C! Finishing current lookup. Hold on..."); tx_interrupted.send(()).unwrap(); - }).expect("Error setting Ctrl-C handler"); - + }) + .expect("Error setting Ctrl-C handler"); + let mut last_nodes: HashSet = HashSet::new(); let mut lookup_count = 0; while rx_interrupted.try_recv().is_err() { lookup_count += 1; let mut dht = init_dht(USE_RANDOM_BOOTSTRAP_NODES); let nodes = dht.find_node(target).unwrap(); - let nodes: Vec = nodes.into_iter().filter(|node| target.distance(node.id()) < MAX_DISTANCE).collect(); + let nodes: Vec = nodes + .into_iter() + .filter(|node| target.distance(node.id()) < MAX_DISTANCE) + .collect(); let closest_nodes: Vec = nodes.into_iter().take(K).collect(); - let sockets: HashSet = closest_nodes.iter().map(|node| node.address().ip()).collect(); + let sockets: HashSet = closest_nodes + .iter() + .map(|node| node.address().ip()) + .collect(); for socket in sockets.iter() { let previous = ip_hits.get(socket); match previous { @@ -56,8 +64,11 @@ fn main() { let furthest_node = closest_nodes.last().unwrap(); let furthest_distance = target.distance(furthest_node.id()); - let overlap_with_last_lookup: HashSet = sockets.intersection(&last_nodes).map(|ip| ip.clone()).collect(); - let overlap = overlap_with_last_lookup.len() as f64/K as f64; + let overlap_with_last_lookup: HashSet = sockets + .intersection(&last_nodes) + .map(|ip| ip.clone()) + .collect(); + let overlap = overlap_with_last_lookup.len() as f64 / K as f64; last_nodes = sockets; println!( "lookup={:02} Ips found {}. Closest node distance: {}, furthest node distance: {}, overlap with previous lookup {}%", @@ -68,14 +79,13 @@ fn main() { (overlap*100 as f64) as usize ); dht.shutdown(); - }; + } println!(); println!("Histogram"); print_histogram(ip_hits, lookup_count); } - /* Prints a histogram with the collected nodes First column are the buckets indicating the hit rate. 3 .. 12 summerizes the nodes that get hit with a probability of 3 to 12% in each lookup. @@ -86,7 +96,7 @@ Example1: 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ Within one lookup, 19 nodes got hit in 3 to 12% of the cases. These are rarely found therefore. -Example2: +Example2: 84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore found in almost all lookups. @@ -96,26 +106,28 @@ Full example: 21 .. 30 [ 3 ]: ∎∎∎ 30 .. 39 [ 2 ]: ∎∎ 39 .. 48 [ 3 ]: ∎∎∎ -48 .. 57 [ 0 ]: -57 .. 66 [ 0 ]: -66 .. 75 [ 0 ]: +48 .. 57 [ 0 ]: +57 .. 66 [ 0 ]: +66 .. 75 [ 0 ]: 75 .. 84 [ 1 ]: ∎ 84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ */ -fn print_histogram(hits: HashMap, lookup_count: usize) { +fn print_histogram(hits: HashMap, lookup_count: usize) { /* - */ + */ let mut histogram = Histogram::with_buckets(10); - let percents: HashMap = hits.into_iter().map(|(ip, hits)| { - let percent = (hits as f32 / lookup_count as f32) * 100 as f32; - (ip, percent as u64) - }).collect(); - + let percents: HashMap = hits + .into_iter() + .map(|(ip, hits)| { + let percent = (hits as f32 / lookup_count as f32) * 100 as f32; + (ip, percent as u64) + }) + .collect(); for (_, percent) in percents.iter() { histogram.add(percent.clone()); - }; + } println!("{}", histogram); } @@ -124,7 +136,10 @@ fn get_random_boostrap_nodes2() -> Vec { let mut dht = Dht::client().unwrap(); let nodes = dht.find_node(Id::random()).unwrap(); dht.shutdown(); - let addrs: Vec = nodes.into_iter().map(|node| node.address().to_string()).collect(); + let addrs: Vec = nodes + .into_iter() + .map(|node| node.address().to_string()) + .collect(); let slice: Vec = addrs[..8].into_iter().map(|va| va.clone()).collect(); slice } @@ -137,4 +152,3 @@ fn init_dht(use_random_boostrap_nodes: bool) -> Dht { Dht::client().unwrap() } } - From a488ced587460cabae7677a8b8fa08e26e042ca4 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Mon, 25 Nov 2024 13:03:59 +0100 Subject: [PATCH 11/12] added description --- examples/count_ips_close_to_key.rs | 57 +++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 144161a5..5d120e22 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,3 +1,35 @@ +/** + * Counts all IP addresses around a random target ID and counts the number of hits, each IP gets. + * Does this by initializing a new DHT node for each lookups to reach the target from different directions. + * + * The result shows how sloppy the lookup algorithms are. + * +Prints a histogram with the collected nodes +First column are the buckets indicating the hit rate. 3 .. 12 summerizes the nodes that get hit with a probability of 3 to 12% in each lookup. +Second column indicates the number of nodes that this bucket contains. [19] means 19 nodes got hit with a probability of 3 to 12%. +Third column is a visualization of the number of nodes [19]. + +Example1: +3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +Within one lookup, 19 nodes got hit in 3 to 12% of the cases. These are rarely found therefore. + +Example2: +84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore found in almost all lookups. + +Full example: +3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +12 .. 21 [ 2 ]: ∎∎ +21 .. 30 [ 3 ]: ∎∎∎ +30 .. 39 [ 2 ]: ∎∎ +39 .. 48 [ 3 ]: ∎∎∎ +48 .. 57 [ 0 ]: +57 .. 66 [ 0 ]: +66 .. 75 [ 0 ]: +75 .. 84 [ 1 ]: ∎ +84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ +*/ + use histo::Histogram; use mainline::{Dht, Id, Node}; use std::{ @@ -86,32 +118,7 @@ fn main() { print_histogram(ip_hits, lookup_count); } -/* -Prints a histogram with the collected nodes -First column are the buckets indicating the hit rate. 3 .. 12 summerizes the nodes that get hit with a probability of 3 to 12% in each lookup. -Second column indicates the number of nodes that this bucket contains. [19] means 19 nodes got hit with a probability of 3 to 12%. -Third column is a visualization of the number of nodes [19]. - -Example1: - 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ -Within one lookup, 19 nodes got hit in 3 to 12% of the cases. These are rarely found therefore. - -Example2: -84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ -Within one lookup, 15 nodes got hit in 84 to 93% of the cases. These nodes are therefore found in almost all lookups. -Full example: - 3 .. 12 [ 19 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ -12 .. 21 [ 2 ]: ∎∎ -21 .. 30 [ 3 ]: ∎∎∎ -30 .. 39 [ 2 ]: ∎∎ -39 .. 48 [ 3 ]: ∎∎∎ -48 .. 57 [ 0 ]: -57 .. 66 [ 0 ]: -66 .. 75 [ 0 ]: -75 .. 84 [ 1 ]: ∎ -84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ -*/ fn print_histogram(hits: HashMap, lookup_count: usize) { /* From fd05a528b58b5a8bda31fe0ac7a10e6f1ec29288 Mon Sep 17 00:00:00 2001 From: Severin Buhler Date: Wed, 27 Nov 2024 13:41:30 +0100 Subject: [PATCH 12/12] fixed formating --- examples/count_ips_close_to_key.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/count_ips_close_to_key.rs b/examples/count_ips_close_to_key.rs index 5d120e22..2d40e7d0 100644 --- a/examples/count_ips_close_to_key.rs +++ b/examples/count_ips_close_to_key.rs @@ -1,9 +1,9 @@ /** - * Counts all IP addresses around a random target ID and counts the number of hits, each IP gets. + * Counts all IP addresses around a random target ID and counts the number of hits, each IP gets. * Does this by initializing a new DHT node for each lookups to reach the target from different directions. - * + * * The result shows how sloppy the lookup algorithms are. - * + * Prints a histogram with the collected nodes First column are the buckets indicating the hit rate. 3 .. 12 summerizes the nodes that get hit with a probability of 3 to 12% in each lookup. Second column indicates the number of nodes that this bucket contains. [19] means 19 nodes got hit with a probability of 3 to 12%. @@ -29,7 +29,6 @@ Full example: 75 .. 84 [ 1 ]: ∎ 84 .. 93 [ 15 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ */ - use histo::Histogram; use mainline::{Dht, Id, Node}; use std::{ @@ -118,7 +117,6 @@ fn main() { print_histogram(ip_hits, lookup_count); } - fn print_histogram(hits: HashMap, lookup_count: usize) { /*