-
Notifications
You must be signed in to change notification settings - Fork 4
feat: Kademlia DHT lookup for closest-peer chunk routing #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -33,6 +33,9 @@ use tracing::{debug, info, warn}; | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Default timeout for network operations in seconds. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const DEFAULT_TIMEOUT_SECS: u64 = 30; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Number of closest peers to consider for chunk routing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const CLOSE_GROUP_SIZE: usize = 8; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Default number of replicas for data redundancy. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const DEFAULT_REPLICA_COUNT: u8 = 4; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -126,7 +129,7 @@ impl QuantumClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::Network("P2P node not configured".into())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let target_peer = Self::pick_target_peer(node).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let target_peer = Self::pick_target_peer(node, address).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create and send GET request | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let request_id = self.next_request_id.fetch_add(1, Ordering::Relaxed); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -231,11 +234,11 @@ impl QuantumClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::Network("P2P node not configured".into())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let target_peer = Self::pick_target_peer(node).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Compute content address using SHA-256 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Compute content address using SHA-256 (before peer selection so we can route by it) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let address = crate::client::compute_address(&content); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let target_peer = Self::pick_target_peer(node, &address).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create PUT request with empty payment proof | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let empty_payment = rmp_serde::to_vec(&ant_evm::ProofOfPayment { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| peer_quotes: vec![], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -320,13 +323,37 @@ impl QuantumClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.get_chunk(address).await.map(|opt| opt.is_some()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Pick a target peer from the connected peers list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async fn pick_target_peer(node: &P2PNode) -> Result<String> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let peers = node.connected_peers().await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| peers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Pick the closest peer to `target` using an iterative Kademlia network lookup. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Queries the DHT for the `CLOSE_GROUP_SIZE` closest nodes to the target | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// address and returns the single closest remote peer (excluding ourselves). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async fn pick_target_peer(node: &P2PNode, target: &XorName) -> Result<String> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+326
to
+330
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let local_peer_id = node.peer_id(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let local_transport_id = node.transport_peer_id(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+331
to
+333
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let closest_nodes = node | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .dht() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .find_closest_nodes(target, CLOSE_GROUP_SIZE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|e| Error::Network(format!("Kademlia closest-nodes lookup failed: {e}")))?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let closest = closest_nodes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .into_iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .next() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or_else(|| Error::Network("No connected peers available".into())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .find(|n| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| n.peer_id != *local_peer_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| && local_transport_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .as_ref() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_or(true, |tid| n.peer_id != *tid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+342
to
+347
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or_else(|| Error::Network("No remote peers found near target address".into()))?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+340
to
+348
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let closest = closest_nodes | |
| .into_iter() | |
| .next() | |
| .ok_or_else(|| Error::Network("No connected peers available".into())) | |
| .find(|n| { | |
| n.peer_id != *local_peer_id | |
| && local_transport_id | |
| .as_ref() | |
| .map_or(true, |tid| n.peer_id != *tid) | |
| }) | |
| .ok_or_else(|| Error::Network("No remote peers found near target address".into()))?; | |
| let closest = closest_nodes | |
| .into_iter() | |
| .filter(|n| { | |
| n.peer_id != *local_peer_id | |
| && local_transport_id | |
| .as_ref() | |
| .map_or(true, |tid| n.peer_id != *tid) | |
| }) | |
| .filter_map(|n| { | |
| crate::client::peer_id_to_xor_name(&n.peer_id) | |
| .map(|xor| (n, crate::client::xor_distance(&xor, target))) | |
| }) | |
| .min_by(|(_, dist_a), (_, dist_b)| dist_a.cmp(dist_b)) | |
| .map(|(n, _)| n) | |
| .ok_or_else(|| Error::Network("No remote peers found near target address".into()))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CLOSE_GROUP_SIZEis a routing-critical constant but is hard-coded. Consider making it configurable viaQuantumConfig(or a node/DHT config) so deployments can tune lookup breadth without code changes.