Add geo-aware mixnet topology provider (#3713)

* WIP: initial work

* wupwup

* WIP: experiments

* Move topology provider and requests to own crate

* Make sure we use the new crate everywhere

* Sort Cargo.toml

* Extract out some functions in geo_aware_provider

* rustfmt

* Add CountryGroup type

* Assign unknown as well

* wipwip

* Add command line flag to socks5-client

* Use geo-aware mixnode selection in nym-connect when in medium mode

* rustfmt

* clippy

* Fix nym-connect build

* wasm fix

* Spelling
This commit is contained in:
Jon Häggblad
2023-07-28 14:48:33 +02:00
committed by benedettadavico
parent a86c1a6a60
commit e00910bcb8
30 changed files with 568 additions and 96 deletions
@@ -1,9 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::mix_nodes::location::Location;
use crate::state::ExplorerApiStateContext;
use log::{info, warn};
use nym_explorer_api_requests::Location;
use nym_task::TaskClient;
pub(crate) struct GeoLocateTask {
@@ -64,7 +64,7 @@ impl GeoLocateTask {
) {
Ok(opt) => match opt {
Some(location) => {
let location = Location::new(location);
let location: Location = location.into();
trace!(
"{} mix nodes already located. Ip {} is located in {:#?}",
+12
View File
@@ -42,6 +42,18 @@ pub(crate) struct Location {
pub(crate) longitude: Option<f64>,
}
impl From<Location> for nym_explorer_api_requests::Location {
fn from(location: Location) -> Self {
nym_explorer_api_requests::Location {
country_name: location.name,
two_letter_iso_country_code: location.iso_alpha2,
three_letter_iso_country_code: location.iso_alpha3,
latitude: location.latitude,
longitude: location.longitude,
}
}
}
impl GeoIp {
pub fn new() -> Self {
let db_path = std::env::var("GEOIP_DB_PATH").unwrap_or_else(|e| {
+2 -1
View File
@@ -6,9 +6,10 @@ use crate::mix_node::delegations::{
};
use crate::mix_node::econ_stats::retrieve_mixnode_econ_stats;
use crate::mix_node::models::{
EconomicDynamicsStats, NodeDescription, NodeStats, PrettyDetailedMixNodeBond, SummedDelegations,
EconomicDynamicsStats, NodeDescription, NodeStats, SummedDelegations,
};
use crate::state::ExplorerApiStateContext;
use nym_explorer_api_requests::PrettyDetailedMixNodeBond;
use nym_mixnet_contract_common::{Delegation, MixId};
use reqwest::Error as ReqwestError;
use rocket::response::status::NotFound;
+1 -1
View File
@@ -1,4 +1,4 @@
pub(crate) mod delegations;
pub(crate) mod econ_stats;
pub(crate) mod http;
pub(crate) mod models;
pub mod models;
+2 -36
View File
@@ -2,49 +2,15 @@
// SPDX-License-Identifier: Apache-2.0
use crate::cache::Cache;
use crate::mix_nodes::location::Location;
use nym_contracts_common::Percent;
use nym_mixnet_contract_common::Delegation;
use nym_mixnet_contract_common::{Addr, Coin, Layer, MixId, MixNode};
use nym_validator_client::models::{NodePerformance, SelectionChance};
use nym_mixnet_contract_common::{Addr, Coin, MixId};
use nym_validator_client::models::SelectionChance;
use serde::Deserialize;
use serde::Serialize;
use std::sync::Arc;
use std::time::SystemTime;
use tokio::sync::RwLock;
#[derive(Clone, Debug, Serialize, JsonSchema, PartialEq)]
#[serde(rename_all = "snake_case")]
pub(crate) enum MixnodeStatus {
Active, // in both the active set and the rewarded set
Standby, // only in the rewarded set
Inactive, // in neither the rewarded set nor the active set
}
#[derive(Clone, Debug, Serialize, JsonSchema)]
pub(crate) struct PrettyDetailedMixNodeBond {
// I leave this to @MS to refactor this type as a lot of things here are redundant thanks to
// the existence of `MixNodeDetails`
pub mix_id: MixId,
pub location: Option<Location>,
pub status: MixnodeStatus,
pub pledge_amount: Coin,
pub total_delegation: Coin,
pub owner: Addr,
pub layer: Layer,
pub mix_node: MixNode,
pub stake_saturation: f32,
pub uncapped_saturation: f32,
pub avg_uptime: u8,
pub node_performance: NodePerformance,
pub estimated_operator_apy: f64,
pub estimated_delegators_apy: f64,
pub operating_cost: Coin,
pub profit_margin_percent: Percent,
pub family_id: Option<u16>,
pub blacklisted: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, JsonSchema)]
pub struct SummedDelegations {
pub owner: Addr,
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::mix_node::models::{MixnodeStatus, PrettyDetailedMixNodeBond};
use crate::mix_nodes::models::{MixNodeActiveSetSummary, MixNodeSummary};
use crate::state::ExplorerApiStateContext;
use nym_explorer_api_requests::{MixnodeStatus, PrettyDetailedMixNodeBond};
use rocket::serde::json::Json;
use rocket::{Route, State};
use rocket_okapi::okapi::openapi3::OpenApi;
+1 -22
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::geo_ip::location;
use nym_explorer_api_requests::Location;
use nym_mixnet_contract_common::MixId;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -31,27 +31,6 @@ pub(crate) struct LocationCacheItem {
pub(crate) valid_until: SystemTime,
}
#[derive(Clone, Debug, JsonSchema, Serialize, Deserialize)]
pub(crate) struct Location {
pub(crate) two_letter_iso_country_code: String,
pub(crate) three_letter_iso_country_code: String,
pub(crate) country_name: String,
pub(crate) latitude: Option<f64>,
pub(crate) longitude: Option<f64>,
}
impl Location {
pub(crate) fn new(location: location::Location) -> Self {
Location {
country_name: location.name,
two_letter_iso_country_code: location.iso_alpha2,
three_letter_iso_country_code: location.iso_alpha3,
latitude: location.latitude,
longitude: location.longitude,
}
}
}
impl LocationCacheItem {
pub(crate) fn new_from_location(location: Option<Location>) -> Self {
LocationCacheItem {
+2 -2
View File
@@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use nym_explorer_api_requests::{Location, MixnodeStatus, PrettyDetailedMixNodeBond};
use nym_mixnet_contract_common::rewarding::helpers::truncate_reward;
use nym_mixnet_contract_common::MixId;
use serde::Serialize;
@@ -14,8 +15,7 @@ use crate::helpers::best_effort_small_dec_to_f64;
use nym_validator_client::models::MixNodeBondAnnotated;
use super::utils::family_numerical_id;
use crate::mix_node::models::{MixnodeStatus, PrettyDetailedMixNodeBond};
use crate::mix_nodes::location::{Location, LocationCache, LocationCacheItem};
use crate::mix_nodes::location::{LocationCache, LocationCacheItem};
use crate::mix_nodes::CACHE_ENTRY_TTL;
#[derive(Clone, Debug, Serialize, JsonSchema)]