Different entry/exit selection criteria
This commit is contained in:
@@ -11,7 +11,6 @@ use axum::{
|
||||
Json, Router,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nym_validator_client::nym_nodes::NodeRole;
|
||||
use tracing::instrument;
|
||||
|
||||
pub(crate) fn routes() -> Router<AppState> {
|
||||
@@ -43,11 +42,8 @@ pub async fn get_entry_gateways(state: State<AppState>) -> HttpResult<Json<Vec<D
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|gw| matches!(gw.role, NodeRole::EntryGateway))
|
||||
.collect(),
|
||||
.get_entry_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -67,16 +63,10 @@ pub async fn get_entry_gateway_countries(state: State<AppState>) -> HttpResult<J
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.get_entry_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|gw| {
|
||||
if matches!(gw.role, NodeRole::EntryGateway) {
|
||||
Some(gw.location.two_letter_iso_country_code.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|gw| gw.location.two_letter_iso_country_code.to_string())
|
||||
// dedup relies on iterator being sorted by country, but we already do that
|
||||
.dedup()
|
||||
.collect(),
|
||||
@@ -108,13 +98,10 @@ pub async fn get_entry_gateways_by_country(
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.get_entry_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|gw| {
|
||||
matches!(gw.role, NodeRole::EntryGateway)
|
||||
&& gw.location.two_letter_iso_country_code.to_lowercase() == country_filter
|
||||
})
|
||||
.filter(|gw| gw.location.two_letter_iso_country_code.to_lowercase() == country_filter)
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ use axum::{
|
||||
Json, Router,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nym_validator_client::nym_nodes::NodeRole;
|
||||
use tracing::instrument;
|
||||
|
||||
pub(crate) fn routes() -> Router<AppState> {
|
||||
@@ -43,11 +42,8 @@ pub async fn get_exit_gateways(state: State<AppState>) -> HttpResult<Json<Vec<DV
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|gw| matches!(gw.role, NodeRole::ExitGateway))
|
||||
.collect(),
|
||||
.get_exit_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -67,16 +63,10 @@ pub async fn get_entry_gateway_countries(state: State<AppState>) -> HttpResult<J
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.get_exit_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|gw| {
|
||||
if matches!(gw.role, NodeRole::ExitGateway) {
|
||||
Some(gw.location.two_letter_iso_country_code.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|gw| gw.location.two_letter_iso_country_code.to_string())
|
||||
// dedup relies on iterator being sorted by country, but we already do that
|
||||
.dedup()
|
||||
.collect(),
|
||||
@@ -108,13 +98,10 @@ pub async fn get_exit_gateways_by_country(
|
||||
Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.get_exit_dvpn_gateways(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|gw| {
|
||||
matches!(gw.role, NodeRole::ExitGateway)
|
||||
&& gw.location.two_letter_iso_country_code.to_lowercase() == country_filter
|
||||
})
|
||||
.filter(|gw| gw.location.two_letter_iso_country_code.to_lowercase() == country_filter)
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::monitor::ExplorerPrettyBond;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal};
|
||||
use nym_mixnet_contract_common::CoinSchema;
|
||||
use nym_node_requests::api::v1::node::models::NodeDescription;
|
||||
@@ -15,8 +16,6 @@ use utoipa::ToSchema;
|
||||
|
||||
pub(crate) use nym_node_status_client::models::TestrunAssignment;
|
||||
|
||||
use crate::monitor::ExplorerPrettyBond;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct Gateway {
|
||||
pub gateway_identity_key: String,
|
||||
@@ -65,6 +64,37 @@ pub struct DVpnGateway {
|
||||
pub build_information: BinaryBuildInformationOwned,
|
||||
}
|
||||
|
||||
impl DVpnGateway {
|
||||
pub fn can_route_entry(&self) -> bool {
|
||||
self.last_probe
|
||||
.as_ref()
|
||||
.map(|probe| match &probe.outcome.as_entry {
|
||||
directory_gw_probe_outcome::Entry::Tested(entry_test_result) => {
|
||||
entry_test_result.can_route
|
||||
}
|
||||
directory_gw_probe_outcome::Entry::NotTested
|
||||
| directory_gw_probe_outcome::Entry::EntryFailure => false,
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn can_route_exit(&self) -> bool {
|
||||
self.last_probe
|
||||
.as_ref()
|
||||
.map(|probe| {
|
||||
probe
|
||||
.outcome
|
||||
.as_exit
|
||||
.as_ref()
|
||||
.map(|outcome| {
|
||||
outcome.can_route_ip_external_v4 && outcome.can_route_ip_external_v6
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// based on
|
||||
/// https://github.com/nymtech/nym-vpn-client/blob/nym-vpn-core-v1.10.0/nym-vpn-core/crates/nym-gateway-probe/src/types.rs
|
||||
/// TODO: long term types should be moved into this repo because nym-vpn-client
|
||||
@@ -109,11 +139,11 @@ pub mod directory_gw_probe_outcome {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
|
||||
pub struct Exit {
|
||||
can_connect: bool,
|
||||
can_route_ip_v4: bool,
|
||||
can_route_ip_external_v4: bool,
|
||||
can_route_ip_v6: bool,
|
||||
can_route_ip_external_v6: bool,
|
||||
pub can_connect: bool,
|
||||
pub can_route_ip_v4: bool,
|
||||
pub can_route_ip_external_v4: bool,
|
||||
pub can_route_ip_v6: bool,
|
||||
pub can_route_ip_external_v6: bool,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ impl AppState {
|
||||
}
|
||||
|
||||
static GATEWAYS_LIST_KEY: &str = "gateways";
|
||||
static DVPN_GATEWAYS_LIST_KEY: &str = "dvpn_gateways";
|
||||
static MIXNODES_LIST_KEY: &str = "mixnodes";
|
||||
static NYM_NODES_LIST_KEY: &str = "nym_nodes";
|
||||
static MIXSTATS_LIST_KEY: &str = "mixstats";
|
||||
@@ -92,8 +93,7 @@ const MIXNODE_STATS_HISTORY_DAYS: usize = 30;
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct HttpCache {
|
||||
gateways: Cache<String, Arc<RwLock<Vec<Gateway>>>>,
|
||||
// each min_version has their own cached list
|
||||
dvpn_gateways: Cache<Version, Arc<RwLock<Vec<DVpnGateway>>>>,
|
||||
dvpn_gateways: Cache<String, Arc<RwLock<Vec<DVpnGateway>>>>,
|
||||
mixnodes: Cache<String, Arc<RwLock<Vec<Mixnode>>>>,
|
||||
nym_nodes: Cache<String, Arc<RwLock<Vec<ExtendedNymNode>>>>,
|
||||
mixstats: Cache<String, Arc<RwLock<Vec<DailyStats>>>>,
|
||||
@@ -183,10 +183,9 @@ impl HttpCache {
|
||||
pub async fn upsert_dvpn_gateway_list(
|
||||
&self,
|
||||
new_gateway_list: Vec<DVpnGateway>,
|
||||
min_node_version: &Version,
|
||||
) -> Entry<Version, Arc<RwLock<Vec<DVpnGateway>>>> {
|
||||
) -> Entry<String, Arc<RwLock<Vec<DVpnGateway>>>> {
|
||||
self.dvpn_gateways
|
||||
.entry_by_ref(min_node_version)
|
||||
.entry_by_ref(DVPN_GATEWAYS_LIST_KEY)
|
||||
.and_upsert_with(|maybe_entry| async {
|
||||
if let Some(entry) = maybe_entry {
|
||||
let v = entry.into_value();
|
||||
@@ -205,7 +204,7 @@ impl HttpCache {
|
||||
db: &DbPool,
|
||||
min_node_version: &Version,
|
||||
) -> Vec<DVpnGateway> {
|
||||
match self.dvpn_gateways.get(min_node_version).await {
|
||||
match self.dvpn_gateways.get(DVPN_GATEWAYS_LIST_KEY).await {
|
||||
Some(guard) => {
|
||||
tracing::trace!("Fetching from cache...");
|
||||
let read_lock = guard.read().await;
|
||||
@@ -297,8 +296,7 @@ impl HttpCache {
|
||||
if res_gws.is_empty() && started_with > 0 {
|
||||
tracing::warn!("Started with {}, got 0 gateways", started_with);
|
||||
} else {
|
||||
self.upsert_dvpn_gateway_list(res_gws.clone(), min_node_version)
|
||||
.await;
|
||||
self.upsert_dvpn_gateway_list(res_gws.clone()).await;
|
||||
}
|
||||
|
||||
res_gws
|
||||
@@ -306,6 +304,30 @@ impl HttpCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_entry_dvpn_gateways(
|
||||
&self,
|
||||
db: &DbPool,
|
||||
min_node_version: &Version,
|
||||
) -> Vec<DVpnGateway> {
|
||||
self.get_dvpn_gateway_list(db, min_node_version)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(DVpnGateway::can_route_entry)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn get_exit_dvpn_gateways(
|
||||
&self,
|
||||
db: &DbPool,
|
||||
min_node_version: &Version,
|
||||
) -> Vec<DVpnGateway> {
|
||||
self.get_dvpn_gateway_list(db, min_node_version)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(DVpnGateway::can_route_exit)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn upsert_mixnode_list(
|
||||
&self,
|
||||
new_mixnode_list: Vec<Mixnode>,
|
||||
|
||||
Reference in New Issue
Block a user