Skip to content

Commit bd11dda

Browse files
committed
skimmed batch endpoint implemented
1 parent cddfc15 commit bd11dda

File tree

10 files changed

+81
-29
lines changed

10 files changed

+81
-29
lines changed

common/client-core/src/client/topology_control/smart_api_provider.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2024 - Nym Technologies SA <[email protected]>
22
// SPDX-License-Identifier: GPL-3.0-only
33

4-
//!
4+
//! Caching, piecewise API Topology Provider
55
//!
66
77
#![warn(missing_docs)]
@@ -16,8 +16,6 @@ use nym_validator_client::UserAgent;
1616
use rand::{prelude::SliceRandom, thread_rng};
1717
use url::Url;
1818

19-
use std::collections::HashMap;
20-
2119
/// Topology Provider build around a cached piecewise provider that uses the Nym API to
2220
/// fetch changes and node details.
2321
#[derive(Clone)]
@@ -113,8 +111,28 @@ impl PiecewiseTopologyProvider for NymApiPiecewiseProvider {
113111
Some(topology)
114112
}
115113

116-
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<HashMap<u32, RoutingNode>> {
117-
todo!("blocking on node batch endpoint")
114+
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<Vec<RoutingNode>> {
115+
// Does this need to return a hashmap of RoutingNodes? that is moderately inconvenient
116+
// especially when the nodes themselves contain their node_id unless we expect to directly
117+
// use the result of this fn for lookups where we would otherwise for example, have to
118+
// iterate over a whole vec to find a specific node_id.
119+
let descriptor_vec = self
120+
.validator_client
121+
.retrieve_basic_nodes_batch(ids)
122+
.await
123+
.inspect_err(|err| {
124+
self.use_next_nym_api();
125+
error!("failed to get current rewarded set: {err}");
126+
})
127+
.ok()?;
128+
129+
let mut out = Vec::new();
130+
for node in descriptor_vec {
131+
if let Ok(routing_node) = RoutingNode::try_from(&node) {
132+
let _ = out.push(routing_node);
133+
}
134+
}
135+
Some(out)
118136
}
119137

120138
async fn get_layer_assignments(&mut self) -> Option<EpochRewardedSet> {

common/client-libs/validator-client/src/client.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,9 +498,19 @@ impl NymApiClient {
498498
Ok(nodes)
499499
}
500500

501-
/// retrieve basic information for all bonded nodes on the network
502-
pub async fn retrieve_basic_nodes_batch(&self, node_ids: Vec<u32>) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
503-
Ok(self.nym_api.retrieve_basic_nodes_batch(&node_ids).await?.nodes)
501+
/// Batch request for node descriptors in the current topology.
502+
///
503+
/// Given the set of node IDs included in the request body, provide the descriptor for each
504+
/// associated node in if it is available in the current topology.
505+
pub async fn retrieve_basic_nodes_batch(
506+
&self,
507+
node_ids: &[u32],
508+
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
509+
Ok(self
510+
.nym_api
511+
.retrieve_basic_nodes_batch(node_ids)
512+
.await?
513+
.nodes)
504514
}
505515

506516
pub async fn health(&self) -> Result<ApiHealthResponse, ValidatorClientError> {

common/topology/src/providers/piecewise.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ use time::OffsetDateTime;
1212
use tokio::sync::Mutex;
1313
use tracing::{debug, warn};
1414

15-
use std::{
16-
cmp::min,
17-
collections::{HashMap, HashSet},
18-
sync::Arc,
19-
time::Duration,
20-
};
15+
use std::{cmp::min, collections::HashSet, sync::Arc, time::Duration};
2116

2217
/// Topology filtering and caching configuration
2318
#[derive(Debug)]
@@ -198,7 +193,7 @@ impl<M: PiecewiseTopologyProvider> NymTopologyProviderInner<M> {
198193

199194
// Add the new nodes to our cached topology
200195
if let Some(new_descriptors) = response {
201-
cached_topology.add_routing_nodes(new_descriptors.values());
196+
cached_topology.add_routing_nodes(new_descriptors);
202197
}
203198

204199
// double check that we have the expected nodes
@@ -264,7 +259,7 @@ pub trait PiecewiseTopologyProvider: Send {
264259
async fn get_full_topology(&mut self) -> Option<NymTopology>;
265260

266261
/// Fetch a node descriptors for the set of provided IDs if available.
267-
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<HashMap<u32, RoutingNode>>;
262+
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<Vec<RoutingNode>>;
268263

269264
/// Fetch the latest mapping of node IDs to Nym Network layer.
270265
async fn get_layer_assignments(&mut self) -> Option<EpochRewardedSet>;
@@ -289,11 +284,11 @@ mod test {
289284
Some(self.topo.clone())
290285
}
291286

292-
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<HashMap<u32, RoutingNode>> {
293-
let mut nodes = HashMap::new();
287+
async fn get_descriptor_batch(&mut self, ids: &[u32]) -> Option<Vec<RoutingNode>> {
288+
let mut nodes = Vec::new();
294289
ids.iter().for_each(|id| {
295290
if let Some(node) = self.topo.node_details.get(id) {
296-
nodes.insert(*id, node.clone());
291+
nodes.push(node.clone());
297292
}
298293
});
299294

nym-api/src/network_monitor/monitor/preparer.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::support::caching::cache::SharedCache;
1010
use crate::support::legacy_helpers::legacy_host_to_ips_and_hostname;
1111
use nym_api_requests::legacy::{LegacyGatewayBondWithId, LegacyMixNodeBondWithLayer};
1212
use nym_api_requests::models::{NodeAnnotation, NymNodeDescription};
13-
use nym_contracts_common::NaiveFloat;
13+
use nym_contracts_common::{NaiveFloat, Percent};
1414
use nym_crypto::asymmetric::{encryption, identity};
1515
use nym_mixnet_contract_common::{LegacyMixLayer, NodeId};
1616
use nym_node_tester_utils::node::{NodeType, TestableNode};
@@ -231,6 +231,8 @@ impl PacketPreparer {
231231
mixnet_entry: false,
232232
mixnet_exit: false,
233233
},
234+
// We have no information about performance in legacy node formats
235+
performance: Percent::hundred(),
234236
})
235237
}
236238

@@ -263,6 +265,8 @@ impl PacketPreparer {
263265
mixnet_entry: true,
264266
mixnet_exit: false,
265267
},
268+
// We have no information about performance in legacy node formats
269+
performance: Percent::hundred(),
266270
})
267271
}
268272

nym-api/src/nym_nodes/handlers/unstable/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::nym_nodes::handlers::unstable::semi_skimmed::nodes_expanded;
2626
use crate::nym_nodes::handlers::unstable::skimmed::{
2727
entry_gateways_basic_active, entry_gateways_basic_all, exit_gateways_basic_active,
2828
exit_gateways_basic_all, mixnodes_basic_active, mixnodes_basic_all, nodes_basic_active,
29-
nodes_basic_all,
29+
nodes_basic_all, nodes_basic_batch,
3030
};
3131
use crate::support::http::helpers::PaginationRequest;
3232
use crate::support::http::state::AppState;
@@ -52,6 +52,7 @@ pub(crate) fn nym_node_routes_unstable() -> Router<AppState> {
5252
"/skimmed",
5353
Router::new()
5454
.route("/", get(nodes_basic_all))
55+
.route("/batch", post(nodes_basic_batch))
5556
.route("/active", get(nodes_basic_active))
5657
.nest(
5758
"/mixnodes",

nym-api/src/nym_nodes/handlers/unstable/skimmed.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ async fn nodes_basic(
240240
state: State<AppState>,
241241
Query(_query_params): Query<NodesParams>,
242242
active_only: bool,
243-
) -> SkimmedNodes {
243+
) -> AxumResult<CachedNodesResponse<SkimmedNode>> {
244244
// unfortunately we have to build the response semi-manually here as we need to add two sources of legacy nodes
245245

246246
// 1. grab all relevant described nym-nodes
@@ -282,10 +282,10 @@ async fn nodes_basic(
282282
legacy_gateways.timestamp(),
283283
]);
284284

285-
Ok(Json(CachedNodesResponse {
285+
Ok(CachedNodesResponse {
286286
refreshed_at,
287287
nodes,
288-
}))
288+
})
289289
}
290290

291291
#[allow(dead_code)] // not dead, used in OpenAPI docs
@@ -327,7 +327,12 @@ pub(super) async fn nodes_basic_all(
327327
};
328328
}
329329

330-
nodes_basic(state, Query(query_params.into()), false).await
330+
let nodes = nodes_basic(state, Query(query_params.into()), false).await?;
331+
// We are never using pagination (always one page) anyways so just build it here.
332+
Ok(Json(PaginatedCachedNodesResponse::new_full(
333+
nodes.refreshed_at,
334+
nodes.nodes,
335+
)))
331336
}
332337

333338
/// Post request handler taking a json array of NodeId (u32) values and returning descriptors for
@@ -351,8 +356,18 @@ pub(super) async fn nodes_basic_all(
351356
pub(super) async fn nodes_basic_batch(
352357
state: State<AppState>,
353358
Query(query_params): Query<NodesParamsWithRole>,
359+
Json(ids): Json<Vec<u32>>,
354360
) -> SkimmedNodes {
355-
nodes_basic(state, Query(query_params.into()), false).await
361+
let nodes = nodes_basic(state, Query(query_params.into()), false).await?;
362+
let requested_nodes = nodes
363+
.nodes
364+
.into_iter()
365+
.filter(|node| ids.contains(&node.node_id))
366+
.collect();
367+
Ok(Json(CachedNodesResponse {
368+
nodes: requested_nodes,
369+
refreshed_at: nodes.refreshed_at,
370+
}))
356371
}
357372

358373
/// Return Nym Nodes and optionally legacy mixnodes/gateways (if `no-legacy` flag is not used)
@@ -385,7 +400,12 @@ pub(super) async fn nodes_basic_active(
385400
};
386401
}
387402

388-
nodes_basic(state, Query(query_params.into()), true).await
403+
let nodes = nodes_basic(state, Query(query_params.into()), true).await?;
404+
// We are never using pagination (always one page) anyways so just build it here.
405+
Ok(Json(PaginatedCachedNodesResponse::new_full(
406+
nodes.refreshed_at,
407+
nodes.nodes,
408+
)))
389409
}
390410

391411
async fn mixnodes_basic(

nym-node/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ nym-verloc = { path = "../common/verloc" }
7171
nym-metrics = { path = "../common/nym-metrics" }
7272
nym-gateway-stats-storage = { path = "../common/gateway-stats-storage" }
7373
nym-topology = { path = "../common/topology" }
74+
nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common", features = ["naive_float", "utoipa"] }
7475

7576

7677
# http server

nym-node/src/node/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::node::shared_network::{
3232
CachedNetwork, CachedTopologyProvider, NetworkRefresher, RoutingFilter,
3333
};
3434
use nym_bin_common::bin_info;
35+
use nym_contracts_common::Percent;
3536
use nym_crypto::asymmetric::{ed25519, x25519};
3637
use nym_gateway::node::{ActiveClientsStore, GatewayTasksBuilder};
3738
use nym_mixnet_client::client::ActiveConnections;
@@ -579,6 +580,8 @@ impl NymNode {
579580
mixnet_entry: true,
580581
mixnet_exit: true,
581582
},
583+
// Perf metrics are not meaningful in this context.
584+
performance: Percent::hundred(),
582585
})
583586
}
584587

sdk/rust/nym-sdk/src/mixnet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub use nym_statistics_common::clients::{
8383
connection::ConnectionStatsEvent, ClientStatsEvents, ClientStatsSender,
8484
};
8585
pub use nym_task::connections::TransmissionLane;
86-
pub use nym_topology::{provider_trait::TopologyProvider, NymTopology};
86+
pub use nym_topology::{providers::TopologyProvider, NymTopology};
8787
pub use paths::StoragePaths;
8888
pub use socks5_client::Socks5MixnetClient;
8989
pub use traits::MixnetMessageSender;

sdk/rust/nym-sdk/src/mixnet/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use nym_credentials_interface::TicketType;
3232
use nym_crypto::hkdf::DerivationMaterial;
3333
use nym_socks5_client_core::config::Socks5;
3434
use nym_task::{TaskClient, TaskHandle, TaskStatus};
35-
use nym_topology::provider_trait::TopologyProvider;
35+
use nym_topology::providers::TopologyProvider;
3636
use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient, UserAgent};
3737
use rand::rngs::OsRng;
3838
use std::path::Path;

0 commit comments

Comments
 (0)