gateway: extract out PersistantStorage
This commit is contained in:
Generated
+1
@@ -3847,6 +3847,7 @@ name = "nym-gateway"
|
||||
version = "0.12.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bandwidth-claim-contract",
|
||||
"bip39",
|
||||
"bs58",
|
||||
|
||||
@@ -13,6 +13,7 @@ rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.53"
|
||||
async-trait = { version = "0.1.51" }
|
||||
bip39 = "1.0.1"
|
||||
bs58 = "0.4.0"
|
||||
clap = { version = "3.0.10", features = ["cargo", "derive"] }
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use crate::{
|
||||
commands::{override_config, OverrideConfig},
|
||||
config::{persistence::pathfinder::GatewayPathfinder, Config},
|
||||
node::Gateway,
|
||||
};
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
@@ -68,7 +67,6 @@ pub struct Init {
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
id: init_config.id,
|
||||
host: Some(init_config.host),
|
||||
wallet_address: Some(init_config.wallet_address),
|
||||
mix_port: init_config.mix_port,
|
||||
@@ -93,20 +91,23 @@ impl From<Init> for OverrideConfig {
|
||||
}
|
||||
|
||||
pub async fn execute(args: &Init) {
|
||||
let override_config_fields = OverrideConfig::from(args.clone());
|
||||
let id = &override_config_fields.id;
|
||||
println!("Initialising gateway {}...", id);
|
||||
println!("Initialising gateway {}...", args.id);
|
||||
|
||||
let already_init = if Config::default_config_file_path(Some(id)).exists() {
|
||||
println!("Gateway \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id);
|
||||
let already_init = if Config::default_config_file_path(Some(&args.id)).exists() {
|
||||
println!(
|
||||
"Gateway \"{}\" was already initialised before! Config information will be \
|
||||
overwritten (but keys will be kept)!",
|
||||
args.id
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let mut config = Config::new(id);
|
||||
let override_config_fields = OverrideConfig::from(args.clone());
|
||||
|
||||
config = override_config(config, override_config_fields);
|
||||
// Initialising the config structure is just overriding a default constructed one
|
||||
let config = override_config(Config::new(&args.id), override_config_fields);
|
||||
|
||||
// if gateway was already initialised, don't generate new keys
|
||||
if !already_init {
|
||||
@@ -143,5 +144,44 @@ pub async fn execute(args: &Init) {
|
||||
println!("Saved configuration file to {:?}", config_save_location);
|
||||
println!("Gateway configuration completed.\n\n\n");
|
||||
|
||||
Gateway::new(config).await.print_node_details();
|
||||
crate::node::create_gateway(config)
|
||||
.await
|
||||
.print_node_details();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::node::{storage::InMemStorage, Gateway};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_gateway_with_in_mem_storage() {
|
||||
let args = Init {
|
||||
id: "foo-id".to_string(),
|
||||
host: "foo-host".to_string(),
|
||||
wallet_address: "nymt1z9egw0knv47nmur0p8vk4rcx59h9gg4zuxrrr9".to_string(),
|
||||
mix_port: Some(42),
|
||||
clients_port: Some(43),
|
||||
announce_host: Some("foo-announce-host".to_string()),
|
||||
datastore: Some("foo-datastore".to_string()),
|
||||
validator_apis: None,
|
||||
};
|
||||
|
||||
let config = Config::new(&args.id);
|
||||
let config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
|
||||
let (identity_keys, sphinx_keys) = {
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
(
|
||||
identity::KeyPair::new(&mut rng),
|
||||
encryption::KeyPair::new(&mut rng),
|
||||
)
|
||||
};
|
||||
|
||||
// The test is really if this instantiates with InMemStorage without panics
|
||||
let _gateway =
|
||||
Gateway::new_from_keys_and_storage(config, identity_keys, sphinx_keys, InMemStorage)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ pub(crate) enum Commands {
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
id: String,
|
||||
host: Option<String>,
|
||||
wallet_address: Option<String>,
|
||||
mix_port: Option<u16>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{config::Config, node::Gateway};
|
||||
use crate::config::Config;
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
use log::error;
|
||||
@@ -26,5 +26,7 @@ pub async fn execute(args: &NodeDetails) {
|
||||
}
|
||||
};
|
||||
|
||||
Gateway::new(config).await.print_node_details();
|
||||
crate::node::create_gateway(config)
|
||||
.await
|
||||
.print_node_details();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use crate::{
|
||||
commands::{override_config, version_check, OverrideConfig},
|
||||
config::Config,
|
||||
node::Gateway,
|
||||
};
|
||||
use clap::Args;
|
||||
use config::NymConfig;
|
||||
@@ -68,7 +67,6 @@ pub struct Run {
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
id: run_config.id,
|
||||
host: run_config.host,
|
||||
wallet_address: run_config.wallet_address,
|
||||
mix_port: run_config.mix_port,
|
||||
@@ -133,7 +131,7 @@ pub async fn execute(args: &Run) {
|
||||
show_binding_warning(config.get_listening_address().to_string());
|
||||
}
|
||||
|
||||
let mut gateway = Gateway::new(config).await;
|
||||
let mut gateway = crate::node::create_gateway(config).await;
|
||||
println!(
|
||||
"\nTo bond your gateway you will need to install the Nym wallet, go to https://nymtech.net/get-involved and select the Download button.\n\
|
||||
Select the correct version and install it to your machine. You will need to provide the following: \n ");
|
||||
|
||||
@@ -416,11 +416,11 @@ impl Default for Gateway {
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Logging {}
|
||||
struct Logging {}
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct Debug {
|
||||
struct Debug {
|
||||
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
|
||||
/// forwarding sphinx packets.
|
||||
#[serde(with = "humantime_serde")]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::node::client_handling::websocket::connection_handler::{ClientDetails, FreshHandler};
|
||||
use crate::node::client_handling::websocket::message_receiver::MixMessageReceiver;
|
||||
use crate::node::storage::error::StorageError;
|
||||
use crate::node::storage::Storage;
|
||||
use futures::StreamExt;
|
||||
use gateway_requests::iv::IVConversionError;
|
||||
use gateway_requests::types::{BinaryRequest, ServerResponse};
|
||||
@@ -89,14 +90,14 @@ impl IntoWSMessage for Result<ServerResponse, RequestHandlingError> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AuthenticatedHandler<R, S> {
|
||||
inner: FreshHandler<R, S>,
|
||||
pub(crate) struct AuthenticatedHandler<R, S, St> {
|
||||
inner: FreshHandler<R, S, St>,
|
||||
client: ClientDetails,
|
||||
mix_receiver: MixMessageReceiver,
|
||||
}
|
||||
|
||||
// explicitly remove handle from the global store upon being dropped
|
||||
impl<R, S> Drop for AuthenticatedHandler<R, S> {
|
||||
impl<R, S, St> Drop for AuthenticatedHandler<R, S, St> {
|
||||
fn drop(&mut self) {
|
||||
self.inner
|
||||
.active_clients_store
|
||||
@@ -104,10 +105,11 @@ impl<R, S> Drop for AuthenticatedHandler<R, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, S> AuthenticatedHandler<R, S>
|
||||
impl<R, S, St> AuthenticatedHandler<R, S, St>
|
||||
where
|
||||
// TODO: those trait bounds here don't really make sense....
|
||||
R: Rng + CryptoRng,
|
||||
St: Storage,
|
||||
{
|
||||
/// Upgrades `FreshHandler` into the Authenticated variant implying the client is now authenticated
|
||||
/// and thus allowed to perform more actions with the gateway, such as redeeming bandwidth or
|
||||
@@ -119,7 +121,7 @@ where
|
||||
/// * `client`: details (i.e. address and shared keys) of the registered client
|
||||
/// * `mix_receiver`: channel used for receiving messages from the mixnet destined for this client.
|
||||
pub(crate) fn upgrade(
|
||||
fresh: FreshHandler<R, S>,
|
||||
fresh: FreshHandler<R, S, St>,
|
||||
client: ClientDetails,
|
||||
mix_receiver: MixMessageReceiver,
|
||||
) -> Self {
|
||||
@@ -410,6 +412,7 @@ where
|
||||
pub(crate) async fn listen_for_requests(mut self)
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
St: Storage,
|
||||
{
|
||||
trace!("Started listening for ALL incoming requests...");
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::node::client_handling::websocket::connection_handler::{
|
||||
AuthenticatedHandler, ClientDetails, InitialAuthResult, SocketStream,
|
||||
};
|
||||
use crate::node::storage::error::StorageError;
|
||||
use crate::node::storage::PersistentStorage;
|
||||
use crate::node::storage::Storage;
|
||||
use crypto::asymmetric::identity;
|
||||
use futures::{channel::mpsc, SinkExt, StreamExt};
|
||||
use gateway_requests::authentication::encrypted_address::{
|
||||
@@ -68,14 +68,14 @@ impl InitialAuthenticationError {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct FreshHandler<R, S> {
|
||||
pub(crate) struct FreshHandler<R, S, St> {
|
||||
rng: R,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
pub(crate) testnet_mode: bool,
|
||||
pub(crate) active_clients_store: ActiveClientsStore,
|
||||
pub(crate) outbound_mix_sender: MixForwardingSender,
|
||||
pub(crate) socket_connection: SocketStream<S>,
|
||||
pub(crate) storage: PersistentStorage,
|
||||
pub(crate) storage: St,
|
||||
|
||||
#[cfg(feature = "coconut")]
|
||||
pub(crate) aggregated_verification_key: VerificationKey,
|
||||
@@ -84,9 +84,10 @@ pub(crate) struct FreshHandler<R, S> {
|
||||
pub(crate) erc20_bridge: Arc<ERC20Bridge>,
|
||||
}
|
||||
|
||||
impl<R, S> FreshHandler<R, S>
|
||||
impl<R, S, St> FreshHandler<R, S, St>
|
||||
where
|
||||
R: Rng + CryptoRng,
|
||||
St: Storage,
|
||||
{
|
||||
// for time being we assume handle is always constructed from raw socket.
|
||||
// if we decide we want to change it, that's not too difficult
|
||||
@@ -99,7 +100,7 @@ where
|
||||
testnet_mode: bool,
|
||||
outbound_mix_sender: MixForwardingSender,
|
||||
local_identity: Arc<identity::KeyPair>,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
#[cfg(feature = "coconut")] aggregated_verification_key: VerificationKey,
|
||||
#[cfg(not(feature = "coconut"))] erc20_bridge: Arc<ERC20Bridge>,
|
||||
@@ -543,7 +544,7 @@ where
|
||||
// TODO: somehow cleanup this method
|
||||
pub(crate) async fn perform_initial_authentication(
|
||||
mut self,
|
||||
) -> Option<AuthenticatedHandler<R, S>>
|
||||
) -> Option<AuthenticatedHandler<R, S, St>>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin + Send,
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@ use rand::{CryptoRng, Rng};
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
|
||||
use crate::node::storage::Storage;
|
||||
|
||||
pub(crate) use self::authenticated::AuthenticatedHandler;
|
||||
pub(crate) use self::fresh::FreshHandler;
|
||||
|
||||
@@ -64,10 +66,11 @@ impl InitialAuthResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn handle_connection<R, S>(mut handle: FreshHandler<R, S>)
|
||||
pub(crate) async fn handle_connection<R, S, St>(mut handle: FreshHandler<R, S, St>)
|
||||
where
|
||||
R: Rng + CryptoRng,
|
||||
S: AsyncRead + AsyncWrite + Unpin + Send,
|
||||
St: Storage,
|
||||
{
|
||||
if let Err(err) = handle.perform_websocket_handshake().await {
|
||||
warn!(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
use crate::node::client_handling::websocket::connection_handler::FreshHandler;
|
||||
use crate::node::storage::PersistentStorage;
|
||||
use crate::node::storage::Storage;
|
||||
use crypto::asymmetric::identity;
|
||||
use log::*;
|
||||
use mixnet_client::forwarder::MixForwardingSender;
|
||||
@@ -52,12 +52,14 @@ impl Listener {
|
||||
|
||||
// TODO: change the signature to pub(crate) async fn run(&self, handler: Handler)
|
||||
|
||||
pub(crate) async fn run(
|
||||
pub(crate) async fn run<St>(
|
||||
&mut self,
|
||||
outbound_mix_sender: MixForwardingSender,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
) {
|
||||
) where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
info!("Starting websocket listener at {}", self.address);
|
||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
@@ -93,12 +95,15 @@ impl Listener {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(
|
||||
pub(crate) fn start<St>(
|
||||
mut self,
|
||||
outbound_mix_sender: MixForwardingSender,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
) -> JoinHandle<()> {
|
||||
) -> JoinHandle<()>
|
||||
where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
tokio::spawn(async move {
|
||||
self.run(outbound_mix_sender, storage, active_clients_store)
|
||||
.await
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
use crate::node::client_handling::websocket::message_receiver::MixMessageSender;
|
||||
use crate::node::mixnet_handling::receiver::packet_processing::PacketProcessor;
|
||||
use crate::node::storage::error::StorageError;
|
||||
use crate::node::storage::PersistentStorage;
|
||||
use crate::node::storage::Storage;
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use mixnet_client::forwarder::MixForwardingSender;
|
||||
@@ -19,7 +19,7 @@ use std::net::SocketAddr;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_util::codec::Framed;
|
||||
|
||||
pub(crate) struct ConnectionHandler {
|
||||
pub(crate) struct ConnectionHandler<St: Storage> {
|
||||
packet_processor: PacketProcessor,
|
||||
|
||||
// TODO: investigate performance trade-offs for whether this cache even makes sense
|
||||
@@ -28,11 +28,11 @@ pub(crate) struct ConnectionHandler {
|
||||
// and each `get` internally copies the channel, however, is it really that expensive?
|
||||
clients_store_cache: HashMap<DestinationAddressBytes, MixMessageSender>,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
ack_sender: MixForwardingSender,
|
||||
}
|
||||
|
||||
impl Clone for ConnectionHandler {
|
||||
impl<St: Storage + Clone> Clone for ConnectionHandler<St> {
|
||||
fn clone(&self) -> Self {
|
||||
// remove stale entries from the cache while cloning
|
||||
let mut clients_store_cache = HashMap::with_capacity(self.clients_store_cache.capacity());
|
||||
@@ -52,10 +52,10 @@ impl Clone for ConnectionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionHandler {
|
||||
impl<St: Storage> ConnectionHandler<St> {
|
||||
pub(crate) fn new(
|
||||
packet_processor: PacketProcessor,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
ack_sender: MixForwardingSender,
|
||||
active_clients_store: ActiveClientsStore,
|
||||
) -> Self {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use crate::node::storage::Storage;
|
||||
use log::*;
|
||||
use std::net::SocketAddr;
|
||||
use std::process;
|
||||
@@ -17,7 +18,10 @@ impl Listener {
|
||||
Listener { address }
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self, connection_handler: ConnectionHandler) {
|
||||
pub(crate) async fn run<St>(&mut self, connection_handler: ConnectionHandler<St>)
|
||||
where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
info!("Starting mixnet listener at {}", self.address);
|
||||
let tcp_listener = match tokio::net::TcpListener::bind(self.address).await {
|
||||
Ok(listener) => listener,
|
||||
@@ -38,7 +42,10 @@ impl Listener {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(mut self, connection_handler: ConnectionHandler) -> JoinHandle<()> {
|
||||
pub(crate) fn start<St>(mut self, connection_handler: ConnectionHandler<St>) -> JoinHandle<()>
|
||||
where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
info!("Running mix listener on {:?}", self.address.to_string());
|
||||
|
||||
tokio::spawn(async move { self.run(connection_handler).await })
|
||||
|
||||
+39
-12
@@ -7,7 +7,7 @@ use crate::config::Config;
|
||||
use crate::node::client_handling::active_clients::ActiveClientsStore;
|
||||
use crate::node::client_handling::websocket;
|
||||
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
|
||||
use crate::node::storage::PersistentStorage;
|
||||
use crate::node::storage::Storage;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use log::*;
|
||||
use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
|
||||
@@ -25,23 +25,44 @@ use coconut_interface::VerificationKey;
|
||||
#[cfg(feature = "coconut")]
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
|
||||
use self::storage::PersistentStorage;
|
||||
|
||||
pub(crate) mod client_handling;
|
||||
pub(crate) mod mixnet_handling;
|
||||
pub(crate) mod storage;
|
||||
|
||||
pub struct Gateway {
|
||||
/// Wire up and create Gateway instance
|
||||
pub(crate) async fn create_gateway(config: Config) -> Gateway<PersistentStorage> {
|
||||
let storage = initialise_storage(&config).await;
|
||||
Gateway::new(config, storage).await
|
||||
}
|
||||
|
||||
async fn initialise_storage(config: &Config) -> PersistentStorage {
|
||||
let path = config.get_persistent_store_path();
|
||||
let retrieval_limit = config.get_message_retrieval_limit();
|
||||
match PersistentStorage::init(path, retrieval_limit).await {
|
||||
Err(err) => panic!("failed to initialise gateway storage - {}", err),
|
||||
Ok(storage) => storage,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Gateway<St: Storage> {
|
||||
config: Config,
|
||||
/// ed25519 keypair used to assert one's identity.
|
||||
identity_keypair: Arc<identity::KeyPair>,
|
||||
/// x25519 keypair used for Diffie-Hellman. Currently only used for sphinx key derivation.
|
||||
sphinx_keypair: Arc<encryption::KeyPair>,
|
||||
storage: PersistentStorage,
|
||||
storage: St,
|
||||
}
|
||||
|
||||
impl Gateway {
|
||||
pub async fn new(config: Config) -> Self {
|
||||
let storage = Self::initialise_storage(&config).await;
|
||||
impl<St> Gateway<St>
|
||||
where
|
||||
St: Storage + Clone + 'static,
|
||||
{
|
||||
/// Construct from the given `Config` instance.
|
||||
pub async fn new(config: Config, storage: St) -> Self {
|
||||
let pathfinder = GatewayPathfinder::new_from_config(&config);
|
||||
// let storage = Self::initialise_storage(&config).await;
|
||||
|
||||
Gateway {
|
||||
config,
|
||||
@@ -51,12 +72,18 @@ impl Gateway {
|
||||
}
|
||||
}
|
||||
|
||||
async fn initialise_storage(config: &Config) -> PersistentStorage {
|
||||
let path = config.get_persistent_store_path();
|
||||
let retrieval_limit = config.get_message_retrieval_limit();
|
||||
match PersistentStorage::init(path, retrieval_limit).await {
|
||||
Err(err) => panic!("failed to initialise gateway storage - {}", err),
|
||||
Ok(storage) => storage,
|
||||
#[cfg(test)]
|
||||
pub async fn new_from_keys_and_storage(
|
||||
config: Config,
|
||||
identity_keypair: identity::KeyPair,
|
||||
sphinx_keypair: encryption::KeyPair,
|
||||
storage: St,
|
||||
) -> Self {
|
||||
Gateway {
|
||||
config,
|
||||
identity_keypair: Arc::new(identity_keypair),
|
||||
sphinx_keypair: Arc::new(sphinx_keypair),
|
||||
storage,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+221
-72
@@ -6,6 +6,7 @@ use crate::node::storage::error::StorageError;
|
||||
use crate::node::storage::inboxes::InboxManager;
|
||||
use crate::node::storage::models::{PersistedSharedKeys, StoredMessage};
|
||||
use crate::node::storage::shared_keys::SharedKeysManager;
|
||||
use async_trait::async_trait;
|
||||
use gateway_requests::registration::handshake::SharedKeys;
|
||||
use log::{debug, error};
|
||||
use nymsphinx::DestinationAddressBytes;
|
||||
@@ -18,6 +19,123 @@ mod inboxes;
|
||||
mod models;
|
||||
mod shared_keys;
|
||||
|
||||
#[async_trait]
|
||||
pub(crate) trait Storage: Send + Sync {
|
||||
/// Inserts provided derived shared keys into the database.
|
||||
/// If keys previously existed for the provided client, they are overwritten with the new data.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `shared_keys`: shared encryption (AES128CTR) and mac (hmac-blake3) derived shared keys to store.
|
||||
async fn insert_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
shared_keys: SharedKeys,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Tries to retrieve shared keys stored for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
async fn get_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<PersistedSharedKeys>, StorageError>;
|
||||
|
||||
/// Removes from the database shared keys derived with the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
// currently there is no code flow that causes removal (not overwriting)
|
||||
// of the stored keys. However, retain the function for consistency and completion sake
|
||||
#[allow(dead_code)]
|
||||
async fn remove_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Inserts new message to the storage for an offline client for future retrieval.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `message`: raw message to store.
|
||||
async fn store_message(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
message: Vec<u8>,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Retrieves messages stored for the particular client specified by the provided address.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `start_after`: optional starting id of the messages to grab
|
||||
///
|
||||
/// returns the retrieved messages alongside optional id of the last message retrieved if
|
||||
/// there are more messages to retrieve.
|
||||
async fn retrieve_messages(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
start_after: Option<i64>,
|
||||
) -> Result<(Vec<StoredMessage>, Option<i64>), StorageError>;
|
||||
|
||||
/// Removes messages with the specified ids
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `ids`: ids of the messages to remove
|
||||
async fn remove_messages(&self, ids: Vec<i64>) -> Result<(), StorageError>;
|
||||
|
||||
/// Creates a new bandwidth entry for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
async fn create_bandwidth_entry(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Tries to retrieve available bandwidth for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
async fn get_available_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<i64>, StorageError>;
|
||||
|
||||
/// Increases available bandwidth of the particular client by the specified amount.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `amount`: amount of available bandwidth to be added to the client.
|
||||
async fn increase_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
amount: i64,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Decreases available bandwidth of the particular client by the specified amount.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `amount`: amount of available bandwidth to be removed from the client.
|
||||
async fn consume_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
amount: i64,
|
||||
) -> Result<(), StorageError>;
|
||||
}
|
||||
|
||||
// note that clone here is fine as upon cloning the same underlying pool will be used
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct PersistentStorage {
|
||||
@@ -33,7 +151,7 @@ impl PersistentStorage {
|
||||
///
|
||||
/// * `database_path`: path to the database.
|
||||
/// * `message_retrieval_limit`: maximum number of stored client messages that can be retrieved at once.
|
||||
pub(crate) async fn init<P: AsRef<Path>>(
|
||||
pub async fn init<P: AsRef<Path> + Send>(
|
||||
database_path: P,
|
||||
message_retrieval_limit: i64,
|
||||
) -> Result<Self, StorageError> {
|
||||
@@ -72,15 +190,11 @@ impl PersistentStorage {
|
||||
bandwidth_manager: BandwidthManager::new(connection_pool),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts provided derived shared keys into the database.
|
||||
/// If keys previously existed for the provided client, they are overwritten with the new data.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `shared_keys`: shared encryption (AES128CTR) and mac (hmac-blake3) derived shared keys to store.
|
||||
pub(crate) async fn insert_shared_keys(
|
||||
#[async_trait]
|
||||
impl Storage for PersistentStorage {
|
||||
async fn insert_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
shared_keys: SharedKeys,
|
||||
@@ -95,12 +209,7 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tries to retrieve shared keys stored for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
pub(crate) async fn get_shared_keys(
|
||||
async fn get_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<PersistedSharedKeys>, StorageError> {
|
||||
@@ -111,15 +220,8 @@ impl PersistentStorage {
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
/// Removes from the database shared keys derived with the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
// currently there is no code flow that causes removal (not overwriting)
|
||||
// of the stored keys. However, retain the function for consistency and completion sake
|
||||
#[allow(dead_code)]
|
||||
pub(crate) async fn remove_shared_keys(
|
||||
async fn remove_shared_keys(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError> {
|
||||
@@ -129,13 +231,7 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inserts new message to the storage for an offline client for future retrieval.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `message`: raw message to store.
|
||||
pub(crate) async fn store_message(
|
||||
async fn store_message(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
message: Vec<u8>,
|
||||
@@ -146,16 +242,7 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieves messages stored for the particular client specified by the provided address.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `start_after`: optional starting id of the messages to grab
|
||||
///
|
||||
/// returns the retrieved messages alongside optional id of the last message retrieved if
|
||||
/// there are more messages to retrieve.
|
||||
pub(crate) async fn retrieve_messages(
|
||||
async fn retrieve_messages(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
start_after: Option<i64>,
|
||||
@@ -167,24 +254,14 @@ impl PersistentStorage {
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
/// Removes messages with the specified ids
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `ids`: ids of the messages to remove
|
||||
pub(crate) async fn remove_messages(&self, ids: Vec<i64>) -> Result<(), StorageError> {
|
||||
async fn remove_messages(&self, ids: Vec<i64>) -> Result<(), StorageError> {
|
||||
for id in ids {
|
||||
self.inbox_manager.remove_message(id).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates a new bandwidth entry for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
pub(crate) async fn create_bandwidth_entry(
|
||||
async fn create_bandwidth_entry(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError> {
|
||||
@@ -194,12 +271,7 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tries to retrieve available bandwidth for the particular client.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
pub(crate) async fn get_available_bandwidth(
|
||||
async fn get_available_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<i64>, StorageError> {
|
||||
@@ -211,13 +283,7 @@ impl PersistentStorage {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Increases available bandwidth of the particular client by the specified amount.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `amount`: amount of available bandwidth to be added to the client.
|
||||
pub(crate) async fn increase_bandwidth(
|
||||
async fn increase_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
amount: i64,
|
||||
@@ -228,13 +294,7 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Decreases available bandwidth of the particular client by the specified amount.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `client_address`: address of the client
|
||||
/// * `amount`: amount of available bandwidth to be removed from the client.
|
||||
pub(crate) async fn consume_bandwidth(
|
||||
async fn consume_bandwidth(
|
||||
&self,
|
||||
client_address: DestinationAddressBytes,
|
||||
amount: i64,
|
||||
@@ -245,3 +305,92 @@ impl PersistentStorage {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory implementation of `Storage`. The intention is primarily in testing environments.
|
||||
#[cfg(test)]
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct InMemStorage;
|
||||
|
||||
#[cfg(test)]
|
||||
impl InMemStorage {
|
||||
#[allow(unused)]
|
||||
async fn init<P: AsRef<Path> + Send>() -> Result<Self, StorageError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[async_trait]
|
||||
impl Storage for InMemStorage {
|
||||
async fn insert_shared_keys(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
_shared_keys: SharedKeys,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn get_shared_keys(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<PersistedSharedKeys>, StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn remove_shared_keys(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn store_message(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
_message: Vec<u8>,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn retrieve_messages(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
_start_after: Option<i64>,
|
||||
) -> Result<(Vec<StoredMessage>, Option<i64>), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn remove_messages(&self, _ids: Vec<i64>) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn create_bandwidth_entry(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn get_available_bandwidth(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
) -> Result<Option<i64>, StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn increase_bandwidth(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
_amount: i64,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn consume_bandwidth(
|
||||
&self,
|
||||
_client_address: DestinationAddressBytes,
|
||||
_amount: i64,
|
||||
) -> Result<(), StorageError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user