diff --git a/common/clients/directory-client/src/presence.rs b/common/clients/directory-client/src/presence.rs deleted file mode 100644 index 664274007a..0000000000 --- a/common/clients/directory-client/src/presence.rs +++ /dev/null @@ -1,392 +0,0 @@ -use crate::requests::presence_topology_get::PresenceTopologyGetRequester; -use crate::{Client, Config, DirectoryClient}; -use log::*; -use serde::{Deserialize, Serialize}; -use std::collections::HashSet; -use std::convert::TryInto; -use std::io; -use std::net::ToSocketAddrs; -use topology::coco; -use topology::mix; -use topology::provider; -use topology::NymTopology; - -// special version of 'PartialEq' that does not care about last_seen field -//(where applicable) or order of elements in vectors -trait PresenceEq { - fn presence_eq(&self, other: &Self) -> bool; -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CocoPresence { - pub host: String, - pub pub_key: String, - pub last_seen: u64, - pub version: String, -} - -impl Into for CocoPresence { - fn into(self) -> topology::coco::Node { - topology::coco::Node { - host: self.host, - pub_key: self.pub_key, - last_seen: self.last_seen, - version: self.version, - } - } -} - -impl From for CocoPresence { - fn from(cn: coco::Node) -> Self { - CocoPresence { - host: cn.host, - pub_key: cn.pub_key, - last_seen: cn.last_seen, - version: cn.version, - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MixNodePresence { - pub host: String, - pub pub_key: String, - pub layer: u64, - pub last_seen: u64, - pub version: String, -} - -impl TryInto for MixNodePresence { - type Error = io::Error; - - fn try_into(self) -> Result { - let resolved_hostname = self.host.to_socket_addrs()?.next(); - if resolved_hostname.is_none() { - return Err(io::Error::new( - io::ErrorKind::Other, - "no valid socket address", - )); - } - - Ok(topology::mix::Node { - host: resolved_hostname.unwrap(), - pub_key: self.pub_key, - layer: self.layer, - last_seen: self.last_seen, - version: self.version, - }) - } -} - -impl From for MixNodePresence { - fn from(mn: mix::Node) -> Self { - MixNodePresence { - host: mn.host.to_string(), - pub_key: mn.pub_key, - layer: mn.layer, - last_seen: mn.last_seen, - version: mn.version, - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MixProviderPresence { - pub client_listener: String, - pub mixnet_listener: String, - pub pub_key: String, - pub registered_clients: Vec, - pub last_seen: u64, - pub version: String, -} - -impl PresenceEq for MixProviderPresence { - fn presence_eq(&self, other: &Self) -> bool { - if self.registered_clients.len() != other.registered_clients.len() { - return false; - } - - if self.client_listener != other.client_listener - || self.mixnet_listener != other.mixnet_listener - || self.pub_key != other.pub_key - || self.version != other.version - { - return false; - } - - let clients_self_set: HashSet<_> = - self.registered_clients.iter().map(|c| &c.pub_key).collect(); - let clients_other_set: HashSet<_> = other - .registered_clients - .iter() - .map(|c| &c.pub_key) - .collect(); - - clients_self_set == clients_other_set - } -} - -impl Into for MixProviderPresence { - fn into(self) -> topology::provider::Node { - topology::provider::Node { - client_listener: self.client_listener.parse().unwrap(), - mixnet_listener: self.mixnet_listener.parse().unwrap(), - pub_key: self.pub_key, - registered_clients: self - .registered_clients - .into_iter() - .map(|c| c.into()) - .collect(), - last_seen: self.last_seen, - version: self.version, - } - } -} - -impl From for MixProviderPresence { - fn from(mpn: provider::Node) -> Self { - MixProviderPresence { - client_listener: mpn.client_listener.to_string(), - mixnet_listener: mpn.mixnet_listener.to_string(), - pub_key: mpn.pub_key, - registered_clients: mpn - .registered_clients - .into_iter() - .map(|c| c.into()) - .collect(), - last_seen: mpn.last_seen, - version: mpn.version, - } - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MixProviderClient { - pub pub_key: String, -} - -impl Into for MixProviderClient { - fn into(self) -> topology::provider::Client { - topology::provider::Client { - pub_key: self.pub_key, - } - } -} - -impl From for MixProviderClient { - fn from(mpc: topology::provider::Client) -> Self { - MixProviderClient { - pub_key: mpc.pub_key, - } - } -} - -impl PresenceEq for Vec { - fn presence_eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - // we can't take the whole thing into set as it does not implement 'Eq' and we can't - // derive it as we don't want to take 'last_seen' into consideration - let self_set: HashSet<_> = self - .iter() - .map(|c| (&c.host, &c.pub_key, &c.version)) - .collect(); - let other_set: HashSet<_> = other - .iter() - .map(|c| (&c.host, &c.pub_key, &c.version)) - .collect(); - - self_set == other_set - } -} - -impl PresenceEq for Vec { - fn presence_eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - // we can't take the whole thing into set as it does not implement 'Eq' and we can't - // derive it as we don't want to take 'last_seen' into consideration - let self_set: HashSet<_> = self - .iter() - .map(|m| (&m.host, &m.pub_key, &m.version, &m.layer)) - .collect(); - let other_set: HashSet<_> = other - .iter() - .map(|m| (&m.host, &m.pub_key, &m.version, &m.layer)) - .collect(); - - self_set == other_set - } -} - -impl PresenceEq for Vec { - fn presence_eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - - // we can't take the whole thing into set as it does not implement 'Eq' and we can't - // derive it as we don't want to take 'last_seen' into consideration. - // We also don't care about order of registered_clients - - // since we're going to be getting rid of this very soon anyway, just clone registered - // clients vector and sort it - - let self_set: HashSet<_> = self - .iter() - .map(|p| { - ( - &p.client_listener, - &p.mixnet_listener, - &p.pub_key, - &p.version, - p.registered_clients - .iter() - .cloned() - .map(|c| c.pub_key) - .collect::>() - .sort(), - ) - }) - .collect(); - let other_set: HashSet<_> = other - .iter() - .map(|p| { - ( - &p.client_listener, - &p.mixnet_listener, - &p.pub_key, - &p.version, - p.registered_clients - .iter() - .cloned() - .map(|c| c.pub_key) - .collect::>() - .sort(), - ) - }) - .collect(); - - self_set == other_set - } -} - -// Topology shows us the current state of the overall Nym network -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct Topology { - pub coco_nodes: Vec, - pub mix_nodes: Vec, - pub mix_provider_nodes: Vec, -} - -impl PartialEq for Topology { - // we need a custom implementation as the order of nodes does not matter - // also we do not care about 'last_seen' when comparing topologies - fn eq(&self, other: &Self) -> bool { - if !self.coco_nodes.presence_eq(&other.coco_nodes) - || !self.mix_nodes.presence_eq(&other.mix_nodes) - || !self - .mix_provider_nodes - .presence_eq(&other.mix_provider_nodes) - { - return false; - } - - true - } -} - -impl NymTopology for Topology { - fn new(directory_server: String) -> Self { - debug!("Using directory server: {:?}", directory_server); - let directory_config = Config { - base_url: directory_server, - }; - let directory = Client::new(directory_config); - - let topology = directory - .presence_topology - .get() - .expect("Failed to retrieve network topology."); - topology - } - - fn new_from_nodes( - mix_nodes: Vec, - mix_provider_nodes: Vec, - coco_nodes: Vec, - ) -> Self { - Topology { - coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(), - mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(), - mix_provider_nodes: mix_provider_nodes - .into_iter() - .map(|node| node.into()) - .collect(), - } - } - - fn mix_nodes(&self) -> Vec { - self.mix_nodes - .iter() - .filter_map(|x| x.clone().try_into().ok()) - .collect() - } - - fn providers(&self) -> Vec { - self.mix_provider_nodes - .iter() - .map(|x| x.clone().into()) - .collect() - } - - fn coco_nodes(&self) -> Vec { - self.coco_nodes.iter().map(|x| x.clone().into()).collect() - } -} - -#[cfg(test)] -mod converting_mixnode_presence_into_topology_mixnode { - use super::*; - - #[test] - fn it_returns_error_on_unresolvable_hostname() { - let unresolvable_hostname = "foomp.foomp.foomp:1234"; - - let mix_presence = MixNodePresence { - host: unresolvable_hostname.to_string(), - pub_key: "".to_string(), - layer: 0, - last_seen: 0, - version: "".to_string(), - }; - - let result: Result = mix_presence.try_into(); - assert!(result.is_err()) - } - - #[test] - fn it_returns_resolved_ip_on_resolvable_hostname() { - let resolvable_hostname = "nymtech.net:1234"; - - let mix_presence = MixNodePresence { - host: resolvable_hostname.to_string(), - pub_key: "".to_string(), - layer: 0, - last_seen: 0, - version: "".to_string(), - }; - - let result: Result = mix_presence.try_into(); - assert!(result.is_ok()) - } -} diff --git a/common/clients/directory-client/src/presence/coconodes.rs b/common/clients/directory-client/src/presence/coconodes.rs new file mode 100644 index 0000000000..ff1d6c80f0 --- /dev/null +++ b/common/clients/directory-client/src/presence/coconodes.rs @@ -0,0 +1,56 @@ +use super::PresenceEq; +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use topology::coco; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CocoPresence { + pub host: String, + pub pub_key: String, + pub last_seen: u64, + pub version: String, +} + +impl Into for CocoPresence { + fn into(self) -> topology::coco::Node { + topology::coco::Node { + host: self.host, + pub_key: self.pub_key, + last_seen: self.last_seen, + version: self.version, + } + } +} + +impl From for CocoPresence { + fn from(cn: coco::Node) -> Self { + CocoPresence { + host: cn.host, + pub_key: cn.pub_key, + last_seen: cn.last_seen, + version: cn.version, + } + } +} + +impl PresenceEq for Vec { + fn presence_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + + // we can't take the whole thing into set as it does not implement 'Eq' and we can't + // derive it as we don't want to take 'last_seen' into consideration + let self_set: HashSet<_> = self + .iter() + .map(|c| (&c.host, &c.pub_key, &c.version)) + .collect(); + let other_set: HashSet<_> = other + .iter() + .map(|c| (&c.host, &c.pub_key, &c.version)) + .collect(); + + self_set == other_set + } +} diff --git a/common/clients/directory-client/src/presence/mixnodes.rs b/common/clients/directory-client/src/presence/mixnodes.rs new file mode 100644 index 0000000000..aba2d73cf9 --- /dev/null +++ b/common/clients/directory-client/src/presence/mixnodes.rs @@ -0,0 +1,72 @@ +use super::PresenceEq; +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use std::convert::TryInto; +use std::io; +use std::net::ToSocketAddrs; +use topology::mix; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MixNodePresence { + pub host: String, + pub pub_key: String, + pub layer: u64, + pub last_seen: u64, + pub version: String, +} + +impl TryInto for MixNodePresence { + type Error = io::Error; + + fn try_into(self) -> Result { + let resolved_hostname = self.host.to_socket_addrs()?.next(); + if resolved_hostname.is_none() { + return Err(io::Error::new( + io::ErrorKind::Other, + "no valid socket address", + )); + } + + Ok(topology::mix::Node { + host: resolved_hostname.unwrap(), + pub_key: self.pub_key, + layer: self.layer, + last_seen: self.last_seen, + version: self.version, + }) + } +} + +impl From for MixNodePresence { + fn from(mn: mix::Node) -> Self { + MixNodePresence { + host: mn.host.to_string(), + pub_key: mn.pub_key, + layer: mn.layer, + last_seen: mn.last_seen, + version: mn.version, + } + } +} + +impl PresenceEq for Vec { + fn presence_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + + // we can't take the whole thing into set as it does not implement 'Eq' and we can't + // derive it as we don't want to take 'last_seen' into consideration + let self_set: HashSet<_> = self + .iter() + .map(|m| (&m.host, &m.pub_key, &m.version, &m.layer)) + .collect(); + let other_set: HashSet<_> = other + .iter() + .map(|m| (&m.host, &m.pub_key, &m.version, &m.layer)) + .collect(); + + self_set == other_set + } +} diff --git a/common/clients/directory-client/src/presence/mod.rs b/common/clients/directory-client/src/presence/mod.rs new file mode 100644 index 0000000000..10d8b1a5e4 --- /dev/null +++ b/common/clients/directory-client/src/presence/mod.rs @@ -0,0 +1,134 @@ +use crate::requests::presence_topology_get::PresenceTopologyGetRequester; +use crate::{Client, Config, DirectoryClient}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use std::convert::TryInto; +use std::io; +use std::net::ToSocketAddrs; +use topology::coco; +use topology::mix; +use topology::provider; +use topology::NymTopology; + +pub mod coconodes; +pub mod mixnodes; +pub mod providers; + +// special version of 'PartialEq' that does not care about last_seen field +//(where applicable) or order of elements in vectors +trait PresenceEq { + fn presence_eq(&self, other: &Self) -> bool; +} + +// Topology shows us the current state of the overall Nym network +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Topology { + pub coco_nodes: Vec, + pub mix_nodes: Vec, + pub mix_provider_nodes: Vec, +} + +impl PartialEq for Topology { + // we need a custom implementation as the order of nodes does not matter + // also we do not care about 'last_seen' when comparing topologies + fn eq(&self, other: &Self) -> bool { + if !self.coco_nodes.presence_eq(&other.coco_nodes) + || !self.mix_nodes.presence_eq(&other.mix_nodes) + || !self + .mix_provider_nodes + .presence_eq(&other.mix_provider_nodes) + { + return false; + } + + true + } +} + +impl NymTopology for Topology { + fn new(directory_server: String) -> Self { + debug!("Using directory server: {:?}", directory_server); + let directory_config = Config { + base_url: directory_server, + }; + let directory = Client::new(directory_config); + + let topology = directory + .presence_topology + .get() + .expect("Failed to retrieve network topology."); + topology + } + + fn new_from_nodes( + mix_nodes: Vec, + mix_provider_nodes: Vec, + coco_nodes: Vec, + ) -> Self { + Topology { + coco_nodes: coco_nodes.into_iter().map(|node| node.into()).collect(), + mix_nodes: mix_nodes.into_iter().map(|node| node.into()).collect(), + mix_provider_nodes: mix_provider_nodes + .into_iter() + .map(|node| node.into()) + .collect(), + } + } + + fn mix_nodes(&self) -> Vec { + self.mix_nodes + .iter() + .filter_map(|x| x.clone().try_into().ok()) + .collect() + } + + fn providers(&self) -> Vec { + self.mix_provider_nodes + .iter() + .map(|x| x.clone().into()) + .collect() + } + + fn coco_nodes(&self) -> Vec { + self.coco_nodes.iter().map(|x| x.clone().into()).collect() + } +} + +#[cfg(test)] +mod converting_mixnode_presence_into_topology_mixnode { + use super::*; + + #[test] + fn it_returns_error_on_unresolvable_hostname() { + let unresolvable_hostname = "foomp.foomp.foomp:1234"; + + let mix_presence = mixnodes::MixNodePresence { + host: unresolvable_hostname.to_string(), + pub_key: "".to_string(), + layer: 0, + last_seen: 0, + version: "".to_string(), + }; + + let result: Result = mix_presence.try_into(); + assert!(result.is_err()) + } + + #[test] + fn it_returns_resolved_ip_on_resolvable_hostname() { + let resolvable_hostname = "nymtech.net:1234"; + + let mix_presence = mixnodes::MixNodePresence { + host: resolvable_hostname.to_string(), + pub_key: "".to_string(), + layer: 0, + last_seen: 0, + version: "".to_string(), + }; + + let result: Result = mix_presence.try_into(); + assert!(result.is_ok()) + } +} diff --git a/common/clients/directory-client/src/presence/providers.rs b/common/clients/directory-client/src/presence/providers.rs new file mode 100644 index 0000000000..b96bcf6a9e --- /dev/null +++ b/common/clients/directory-client/src/presence/providers.rs @@ -0,0 +1,149 @@ +use super::PresenceEq; +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use topology::provider; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MixProviderPresence { + pub client_listener: String, + pub mixnet_listener: String, + pub pub_key: String, + pub registered_clients: Vec, + pub last_seen: u64, + pub version: String, +} + +impl PresenceEq for MixProviderPresence { + fn presence_eq(&self, other: &Self) -> bool { + if self.registered_clients.len() != other.registered_clients.len() { + return false; + } + + if self.client_listener != other.client_listener + || self.mixnet_listener != other.mixnet_listener + || self.pub_key != other.pub_key + || self.version != other.version + { + return false; + } + + let clients_self_set: HashSet<_> = + self.registered_clients.iter().map(|c| &c.pub_key).collect(); + let clients_other_set: HashSet<_> = other + .registered_clients + .iter() + .map(|c| &c.pub_key) + .collect(); + + clients_self_set == clients_other_set + } +} + +impl Into for MixProviderPresence { + fn into(self) -> topology::provider::Node { + topology::provider::Node { + client_listener: self.client_listener.parse().unwrap(), + mixnet_listener: self.mixnet_listener.parse().unwrap(), + pub_key: self.pub_key, + registered_clients: self + .registered_clients + .into_iter() + .map(|c| c.into()) + .collect(), + last_seen: self.last_seen, + version: self.version, + } + } +} + +impl From for MixProviderPresence { + fn from(mpn: provider::Node) -> Self { + MixProviderPresence { + client_listener: mpn.client_listener.to_string(), + mixnet_listener: mpn.mixnet_listener.to_string(), + pub_key: mpn.pub_key, + registered_clients: mpn + .registered_clients + .into_iter() + .map(|c| c.into()) + .collect(), + last_seen: mpn.last_seen, + version: mpn.version, + } + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MixProviderClient { + pub pub_key: String, +} + +impl Into for MixProviderClient { + fn into(self) -> topology::provider::Client { + topology::provider::Client { + pub_key: self.pub_key, + } + } +} + +impl From for MixProviderClient { + fn from(mpc: topology::provider::Client) -> Self { + MixProviderClient { + pub_key: mpc.pub_key, + } + } +} + +impl PresenceEq for Vec { + fn presence_eq(&self, other: &Self) -> bool { + if self.len() != other.len() { + return false; + } + + // we can't take the whole thing into set as it does not implement 'Eq' and we can't + // derive it as we don't want to take 'last_seen' into consideration. + // We also don't care about order of registered_clients + + // since we're going to be getting rid of this very soon anyway, just clone registered + // clients vector and sort it + + let self_set: HashSet<_> = self + .iter() + .map(|p| { + ( + &p.client_listener, + &p.mixnet_listener, + &p.pub_key, + &p.version, + p.registered_clients + .iter() + .cloned() + .map(|c| c.pub_key) + .collect::>() + .sort(), + ) + }) + .collect(); + let other_set: HashSet<_> = other + .iter() + .map(|p| { + ( + &p.client_listener, + &p.mixnet_listener, + &p.pub_key, + &p.version, + p.registered_clients + .iter() + .cloned() + .map(|c| c.pub_key) + .collect::>() + .sort(), + ) + }) + .collect(); + + self_set == other_set + } +} diff --git a/common/clients/directory-client/src/requests/presence_coconodes_post.rs b/common/clients/directory-client/src/requests/presence_coconodes_post.rs index 40fe4bd2e2..cc34c13272 100644 --- a/common/clients/directory-client/src/requests/presence_coconodes_post.rs +++ b/common/clients/directory-client/src/requests/presence_coconodes_post.rs @@ -1,4 +1,4 @@ -use crate::presence::CocoPresence; +use crate::presence::coconodes::CocoPresence; use reqwest::Response; pub struct Request { @@ -73,7 +73,7 @@ mod metrics_get_request { #[cfg(test)] mod fixtures { - use crate::presence::CocoPresence; + use crate::presence::coconodes::CocoPresence; pub fn new_presence() -> CocoPresence { CocoPresence { diff --git a/common/clients/directory-client/src/requests/presence_mixnodes_post.rs b/common/clients/directory-client/src/requests/presence_mixnodes_post.rs index 3b5d942332..df110c2fea 100644 --- a/common/clients/directory-client/src/requests/presence_mixnodes_post.rs +++ b/common/clients/directory-client/src/requests/presence_mixnodes_post.rs @@ -1,4 +1,4 @@ -use crate::presence::MixNodePresence; +use crate::presence::mixnodes::MixNodePresence; use reqwest::Response; pub struct Request { @@ -73,7 +73,7 @@ mod metrics_get_request { #[cfg(test)] mod fixtures { - use crate::presence::MixNodePresence; + use crate::presence::mixnodes::MixNodePresence; pub fn new_presence() -> MixNodePresence { MixNodePresence { diff --git a/common/clients/directory-client/src/requests/presence_providers_post.rs b/common/clients/directory-client/src/requests/presence_providers_post.rs index f5f522fa93..d926700334 100644 --- a/common/clients/directory-client/src/requests/presence_providers_post.rs +++ b/common/clients/directory-client/src/requests/presence_providers_post.rs @@ -1,4 +1,4 @@ -use crate::presence::MixProviderPresence; +use crate::presence::providers::MixProviderPresence; use reqwest::Response; pub struct Request { @@ -72,7 +72,7 @@ mod metrics_get_request { } #[cfg(test)] mod fixtures { - use crate::presence::MixProviderPresence; + use crate::presence::providers::MixProviderPresence; pub fn new_presence() -> MixProviderPresence { MixProviderPresence { diff --git a/mixnode/src/node/presence.rs b/mixnode/src/node/presence.rs index 283a6a3afe..b017bacdea 100644 --- a/mixnode/src/node/presence.rs +++ b/mixnode/src/node/presence.rs @@ -1,5 +1,5 @@ use crate::node; -use directory_client::presence::MixNodePresence; +use directory_client::presence::mixnodes::MixNodePresence; use directory_client::requests::presence_mixnodes_post::PresenceMixNodesPoster; use directory_client::DirectoryClient; use log::{debug, error}; diff --git a/sfw-provider/src/provider/mod.rs b/sfw-provider/src/provider/mod.rs index bc32073da8..539ecbe463 100644 --- a/sfw-provider/src/provider/mod.rs +++ b/sfw-provider/src/provider/mod.rs @@ -2,7 +2,7 @@ use crate::provider::client_handling::{ClientProcessingData, ClientRequestProces use crate::provider::mix_handling::{MixPacketProcessor, MixProcessingData}; use crate::provider::storage::ClientStorage; use crypto::identity::{DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey}; -use directory_client::presence::MixProviderClient; +use directory_client::presence::providers::MixProviderClient; use futures::io::Error; use futures::lock::Mutex as FMutex; use log::*; diff --git a/sfw-provider/src/provider/presence.rs b/sfw-provider/src/provider/presence.rs index 567b0a56dc..d2ec3c1970 100644 --- a/sfw-provider/src/provider/presence.rs +++ b/sfw-provider/src/provider/presence.rs @@ -1,6 +1,6 @@ use crate::provider::ClientLedger; use crypto::identity::DummyMixIdentityPublicKey; -use directory_client::presence::MixProviderPresence; +use directory_client::presence::providers::MixProviderPresence; use directory_client::requests::presence_providers_post::PresenceMixProviderPoster; use directory_client::DirectoryClient; use futures::lock::Mutex as FMutex;