From 6e42cd38e499facecdbf0d3030ccf3629f770bf4 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 09:00:52 +0300 Subject: [PATCH 01/12] feat(homeserver): internal server errors should be logged first --- pubky-homeserver/src/error.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pubky-homeserver/src/error.rs b/pubky-homeserver/src/error.rs index b6e5a14..8aa58d2 100644 --- a/pubky-homeserver/src/error.rs +++ b/pubky-homeserver/src/error.rs @@ -5,6 +5,7 @@ use axum::{ http::StatusCode, response::IntoResponse, }; +use tracing::debug; pub type Result = core::result::Result; @@ -86,36 +87,42 @@ impl From for Error { impl From for Error { fn from(error: std::io::Error) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } impl From for Error { fn from(error: heed::Error) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } impl From for Error { fn from(error: anyhow::Error) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } impl From for Error { fn from(error: postcard::Error) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } impl From for Error { fn from(error: axum::Error) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } impl From> for Error { fn from(error: flume::SendError) -> Self { + debug!(?error); Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.into()) } } From e01a9c456831e2e5982919f086dd11db48981172 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 09:09:13 +0300 Subject: [PATCH 02/12] fix(homeserver): increase the LMDB map size to 10TB to avoid MDB_MAP_FULL --- pubky-homeserver/src/database.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index 4adc73d..b655a45 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -10,6 +10,7 @@ pub mod tables; use tables::{Tables, TABLES_COUNT}; pub const MAX_LIST_LIMIT: u16 = 100; +pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) #[derive(Debug, Clone)] pub struct DB { @@ -21,7 +22,13 @@ impl DB { pub fn open(storage: &Path) -> anyhow::Result { fs::create_dir_all(storage).unwrap(); - let env = unsafe { EnvOpenOptions::new().max_dbs(TABLES_COUNT).open(storage) }?; + let env = unsafe { + EnvOpenOptions::new() + .max_dbs(TABLES_COUNT) + // TODO: Add a configuration option? + .map_size(DEFAULT_MAP_SIZE) + .open(storage) + }?; let tables = migrations::run(&env)?; From 560972cead7792980aa94698f2ece3835ee8585c Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 12:33:35 +0300 Subject: [PATCH 03/12] fix(pubky): unit test bug --- pubky/src/shared/auth.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pubky/src/shared/auth.rs b/pubky/src/shared/auth.rs index 60ae1ae..aa8cfa9 100644 --- a/pubky/src/shared/auth.rs +++ b/pubky/src/shared/auth.rs @@ -305,10 +305,9 @@ mod tests { .unwrap(); } - let session = pubkyauth_response.await.unwrap().unwrap(); + let public_key = pubkyauth_response.await.unwrap(); - assert_eq!(session.pubky(), &pubky); - assert_eq!(session.capabilities(), &capabilities.0); + assert_eq!(&public_key, &pubky); // Test access control enforcement From f0291719485854c8fb02efb9870e364405bc1afb Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 12:53:11 +0300 Subject: [PATCH 04/12] feat(homeserver): add DEFAULT_LIST_LIMIT and DEFAULT_MAX_LIST_LIMIT --- pubky-homeserver/src/database.rs | 1 - .../src/database/tables/events.rs | 50 +++++++++++++++++ pubky-homeserver/src/routes/feed.rs | 53 ++----------------- 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index b655a45..9eb291f 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -9,7 +9,6 @@ pub mod tables; use tables::{Tables, TABLES_COUNT}; -pub const MAX_LIST_LIMIT: u16 = 100; pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) #[derive(Debug, Clone)] diff --git a/pubky-homeserver/src/database/tables/events.rs b/pubky-homeserver/src/database/tables/events.rs index cf82e18..c04554b 100644 --- a/pubky-homeserver/src/database/tables/events.rs +++ b/pubky-homeserver/src/database/tables/events.rs @@ -10,6 +10,8 @@ use heed::{ use postcard::{from_bytes, to_allocvec}; use serde::{Deserialize, Serialize}; +use crate::database::DB; + /// Event [Timestamp] base32 => Encoded event. pub type EventsTable = Database; @@ -56,3 +58,51 @@ impl Event { } } } + +const MAX_LIST_LIMIT: u16 = 1000; +const DEFAULT_LIST_LIMIT: u16 = 100; + +impl DB { + pub fn list_events( + &self, + limit: Option, + cursor: Option<&str>, + ) -> anyhow::Result> { + let txn = self.env.read_txn()?; + + let limit = limit.unwrap_or(DEFAULT_LIST_LIMIT).min(MAX_LIST_LIMIT); + + let mut cursor = cursor.unwrap_or("0000000000000"); + + // Cursor smaller than 13 character is invalid + // TODO: should we send an error instead? + if cursor.len() < 13 { + cursor = "0000000000000" + } + + let mut result: Vec = vec![]; + let mut next_cursor = cursor.to_string(); + + for _ in 0..limit { + match self.tables.events.get_greater_than(&txn, &next_cursor)? { + Some((timestamp, event_bytes)) => { + let event = Event::deserialize(event_bytes)?; + + let line = format!("{} {}", event.operation(), event.url()); + next_cursor = timestamp.to_string(); + + result.push(line); + } + None => break, + }; + } + + if !result.is_empty() { + result.push(format!("cursor: {next_cursor}")) + } + + txn.commit()?; + + Ok(result) + } +} diff --git a/pubky-homeserver/src/routes/feed.rs b/pubky-homeserver/src/routes/feed.rs index bd426f3..0afe504 100644 --- a/pubky-homeserver/src/routes/feed.rs +++ b/pubky-homeserver/src/routes/feed.rs @@ -7,61 +7,16 @@ use axum::{ response::IntoResponse, }; -use crate::{ - database::{tables::events::Event, MAX_LIST_LIMIT}, - error::Result, - server::AppState, -}; +use crate::{error::Result, server::AppState}; pub async fn feed( State(state): State, Query(params): Query>, ) -> Result { - let txn = state.db.env.read_txn()?; + let limit = params.get("limit").and_then(|l| l.parse::().ok()); + let cursor = params.get("cursor").map(|c| c.as_str()); - let limit = params - .get("limit") - .and_then(|l| l.parse::().ok()) - .unwrap_or(MAX_LIST_LIMIT) - .min(MAX_LIST_LIMIT); - - let mut cursor = params - .get("cursor") - .map(|c| c.as_str()) - .unwrap_or("0000000000000"); - - // Guard against bad cursor - if cursor.len() < 13 { - cursor = "0000000000000" - } - - let mut result: Vec = vec![]; - let mut next_cursor = cursor.to_string(); - - for _ in 0..limit { - match state - .db - .tables - .events - .get_greater_than(&txn, &next_cursor)? - { - Some((timestamp, event_bytes)) => { - let event = Event::deserialize(event_bytes)?; - - let line = format!("{} {}", event.operation(), event.url()); - next_cursor = timestamp.to_string(); - - result.push(line); - } - None => break, - }; - } - - if !result.is_empty() { - result.push(format!("cursor: {next_cursor}")) - } - - txn.commit()?; + let result = state.db.list_events(limit, cursor)?; Ok(Response::builder() .status(StatusCode::OK) From d129e4bb6dad2015ff59b4b620c54bf59e7368d3 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 14:43:30 +0300 Subject: [PATCH 05/12] fix(homeserver): add list limits in config --- pubky-homeserver/src/config.rs | 29 ++++++++++-- pubky-homeserver/src/database.rs | 28 +++++++----- .../src/database/tables/entries.rs | 8 ++-- .../src/database/tables/events.rs | 19 ++++---- pubky-homeserver/src/pkarr.rs | 4 +- pubky-homeserver/src/routes/feed.rs | 21 ++++++++- pubky-homeserver/src/server.rs | 45 +++++++++---------- 7 files changed, 97 insertions(+), 57 deletions(-) diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index 55f015c..362db0b 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -15,6 +15,9 @@ use pubky_common::timestamp::Timestamp; const DEFAULT_HOMESERVER_PORT: u16 = 6287; const DEFAULT_STORAGE_DIR: &str = "pubky"; +pub const DEFAULT_LIST_LIMIT: u16 = 100; +pub const DEFAULT_MAX_LIST_LIMIT: u16 = 1000; + /// Server configuration #[derive(Serialize, Deserialize, Clone)] pub struct Config { @@ -30,6 +33,14 @@ pub struct Config { secret_key: Option<[u8; 32]>, dht_request_timeout: Option, + /// The default limit of a list api if no `limit` query parameter is provided. + /// + /// Defaults to `100` + default_list_limit: u16, + /// The maximum limit of a list api, even if a `limit` query parameter is provided. + /// + /// Defaults to `1000` + max_list_limit: u16, } impl Config { @@ -102,6 +113,18 @@ impl Config { &self.domain } + pub fn keypair(&self) -> Keypair { + Keypair::from_secret_key(&self.secret_key.unwrap_or_default()) + } + + pub fn default_list_limit(&self) -> u16 { + self.default_list_limit + } + + pub fn max_list_limit(&self) -> u16 { + self.max_list_limit + } + /// Get the path to the storage directory pub fn storage(&self) -> Result { let dir = if let Some(storage) = &self.storage { @@ -116,10 +139,6 @@ impl Config { Ok(dir.join("homeserver")) } - pub fn keypair(&self) -> Keypair { - Keypair::from_secret_key(&self.secret_key.unwrap_or_default()) - } - pub(crate) fn dht_request_timeout(&self) -> Option { self.dht_request_timeout } @@ -135,6 +154,8 @@ impl Default for Config { storage: None, secret_key: None, dht_request_timeout: None, + default_list_limit: DEFAULT_LIST_LIMIT, + max_list_limit: DEFAULT_MAX_LIST_LIMIT, } } } diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index 9eb291f..4b282a1 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -1,12 +1,12 @@ use std::fs; -use std::path::Path; - use heed::{Env, EnvOpenOptions}; mod migrations; pub mod tables; +use crate::config::Config; + use tables::{Tables, TABLES_COUNT}; pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) @@ -15,11 +15,14 @@ pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space us pub struct DB { pub(crate) env: Env, pub(crate) tables: Tables, + pub(crate) config: Config, } impl DB { - pub fn open(storage: &Path) -> anyhow::Result { - fs::create_dir_all(storage).unwrap(); + pub fn open(config: Config) -> anyhow::Result { + let storage = config.storage()?; + + fs::create_dir_all(&storage).unwrap(); let env = unsafe { EnvOpenOptions::new() @@ -31,7 +34,11 @@ impl DB { let tables = migrations::run(&env)?; - let db = DB { env, tables }; + let db = DB { + env, + tables, + config, + }; Ok(db) } @@ -40,18 +47,15 @@ impl DB { #[cfg(test)] mod tests { use bytes::Bytes; - use pkarr::Keypair; - use pubky_common::timestamp::Timestamp; + use pkarr::{mainline::Testnet, Keypair}; + + use crate::config::Config; use super::DB; #[tokio::test] async fn entries() { - let storage = std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join("pubky"); - - let db = DB::open(&storage).unwrap(); + let db = DB::open(Config::test(&Testnet::new(0))).unwrap(); let keypair = Keypair::random(); let path = "/pub/foo.txt"; diff --git a/pubky-homeserver/src/database/tables/entries.rs b/pubky-homeserver/src/database/tables/entries.rs index 081f606..b1c7039 100644 --- a/pubky-homeserver/src/database/tables/entries.rs +++ b/pubky-homeserver/src/database/tables/entries.rs @@ -13,7 +13,7 @@ use pubky_common::{ timestamp::Timestamp, }; -use crate::database::{DB, MAX_LIST_LIMIT}; +use crate::database::DB; use super::events::Event; @@ -157,7 +157,7 @@ impl DB { /// Return a list of pubky urls. /// - /// - limit defaults to and capped by [MAX_LIST_LIMIT] + /// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit] pub fn list( &self, txn: &RoTxn, @@ -170,7 +170,9 @@ impl DB { // Vector to store results let mut results = Vec::new(); - let limit = limit.unwrap_or(MAX_LIST_LIMIT).min(MAX_LIST_LIMIT); + let limit = limit + .unwrap_or(self.config.default_list_limit()) + .min(self.config.max_list_limit()); // TODO: make this more performant than split and allocations? diff --git a/pubky-homeserver/src/database/tables/events.rs b/pubky-homeserver/src/database/tables/events.rs index c04554b..1829765 100644 --- a/pubky-homeserver/src/database/tables/events.rs +++ b/pubky-homeserver/src/database/tables/events.rs @@ -59,10 +59,11 @@ impl Event { } } -const MAX_LIST_LIMIT: u16 = 1000; -const DEFAULT_LIST_LIMIT: u16 = 100; - impl DB { + /// Returns a list of events formatted as ` `. + /// + /// - limit defaults to [Config::default_list_limit] and capped by [Config::max_list_limit] + /// - cursor is a 13 character string encoding of a timestamp pub fn list_events( &self, limit: Option, @@ -70,15 +71,11 @@ impl DB { ) -> anyhow::Result> { let txn = self.env.read_txn()?; - let limit = limit.unwrap_or(DEFAULT_LIST_LIMIT).min(MAX_LIST_LIMIT); + let limit = limit + .unwrap_or(self.config.default_list_limit()) + .min(self.config.max_list_limit()); - let mut cursor = cursor.unwrap_or("0000000000000"); - - // Cursor smaller than 13 character is invalid - // TODO: should we send an error instead? - if cursor.len() < 13 { - cursor = "0000000000000" - } + let cursor = cursor.unwrap_or("0000000000000"); let mut result: Vec = vec![]; let mut next_cursor = cursor.to_string(); diff --git a/pubky-homeserver/src/pkarr.rs b/pubky-homeserver/src/pkarr.rs index cf4d7b7..c23755e 100644 --- a/pubky-homeserver/src/pkarr.rs +++ b/pubky-homeserver/src/pkarr.rs @@ -5,8 +5,8 @@ use pkarr::{ Keypair, PkarrClientAsync, SignedPacket, }; -pub async fn publish_server_packet( - pkarr_client: PkarrClientAsync, +pub(crate) async fn publish_server_packet( + pkarr_client: &PkarrClientAsync, keypair: &Keypair, domain: &str, port: u16, diff --git a/pubky-homeserver/src/routes/feed.rs b/pubky-homeserver/src/routes/feed.rs index 0afe504..627eb3e 100644 --- a/pubky-homeserver/src/routes/feed.rs +++ b/pubky-homeserver/src/routes/feed.rs @@ -6,8 +6,12 @@ use axum::{ http::{header, Response, StatusCode}, response::IntoResponse, }; +use pubky_common::timestamp::{Timestamp, TimestampError}; -use crate::{error::Result, server::AppState}; +use crate::{ + error::{Error, Result}, + server::AppState, +}; pub async fn feed( State(state): State, @@ -16,6 +20,21 @@ pub async fn feed( let limit = params.get("limit").and_then(|l| l.parse::().ok()); let cursor = params.get("cursor").map(|c| c.as_str()); + if let Some(cursor) = cursor { + if let Err(timestmap_error) = Timestamp::try_from(cursor.to_string()) { + let cause = match timestmap_error { + TimestampError::InvalidEncoding => { + "Cursor should be valid base32 Crockford encoding of a timestamp" + } + TimestampError::InvalidBytesLength(size) => { + &format!("Cursor should be 13 characters long, got: {size}") + } + }; + + Err(Error::new(StatusCode::BAD_REQUEST, cause.into()))? + } + } + let result = state.db.list_events(limit, cursor)?; Ok(Response::builder() diff --git a/pubky-homeserver/src/server.rs b/pubky-homeserver/src/server.rs index c94a803..44716f7 100644 --- a/pubky-homeserver/src/server.rs +++ b/pubky-homeserver/src/server.rs @@ -14,16 +14,17 @@ use crate::{config::Config, database::DB, pkarr::publish_server_packet}; #[derive(Debug)] pub struct Homeserver { - port: u16, - config: Config, + state: AppState, tasks: JoinSet>, } #[derive(Clone, Debug)] pub(crate) struct AppState { - pub verifier: AuthVerifier, - pub db: DB, - pub pkarr_client: PkarrClientAsync, + pub(crate) verifier: AuthVerifier, + pub(crate) db: DB, + pub(crate) pkarr_client: PkarrClientAsync, + pub(crate) config: Config, + pub(crate) port: u16, } impl Homeserver { @@ -32,7 +33,7 @@ impl Homeserver { let keypair = config.keypair(); - let db = DB::open(&config.storage()?)?; + let db = DB::open(config.clone())?; let pkarr_client = PkarrClient::new(Settings { dht: DhtSettings { @@ -44,22 +45,22 @@ impl Homeserver { })? .as_async(); - let state = AppState { - verifier: AuthVerifier::default(), - db, - pkarr_client: pkarr_client.clone(), - }; - - let app = crate::routes::create_app(state); - let mut tasks = JoinSet::new(); - let app = app.clone(); - let listener = TcpListener::bind(SocketAddr::from(([0, 0, 0, 0], config.port()))).await?; let port = listener.local_addr()?.port(); + let state = AppState { + verifier: AuthVerifier::default(), + db, + pkarr_client, + config, + port, + }; + + let app = crate::routes::create_app(state.clone()); + // Spawn http server task tasks.spawn( axum::serve( @@ -72,15 +73,11 @@ impl Homeserver { info!("Homeserver listening on http://localhost:{port}"); - publish_server_packet(pkarr_client, &keypair, config.domain(), port).await?; + publish_server_packet(&state.pkarr_client, &keypair, state.config.domain(), port).await?; info!("Homeserver listening on pubky://{}", keypair.public_key()); - Ok(Self { - tasks, - config, - port, - }) + Ok(Self { tasks, state }) } /// Test version of [Homeserver::start], using mainline Testnet, and a temporary storage. @@ -93,11 +90,11 @@ impl Homeserver { // === Getters === pub fn port(&self) -> u16 { - self.port + self.state.port } pub fn public_key(&self) -> PublicKey { - self.config.keypair().public_key() + self.state.config.keypair().public_key() } // === Public Methods === From 6897671612d1039c7be45612371e90cd13de0e3a Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 27 Sep 2024 15:44:58 +0300 Subject: [PATCH 06/12] feat(homeserver): allow empty config file --- pubky-homeserver/src/config.rs | 194 ++++++++++++++++++++----------- pubky-homeserver/src/database.rs | 6 +- pubky-homeserver/src/server.rs | 21 +++- 3 files changed, 142 insertions(+), 79 deletions(-) diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index 362db0b..f182a52 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Context, Result}; use pkarr::Keypair; -use serde::{Deserialize, Deserializer, Serialize}; +use serde::{Deserialize, Serialize}; use std::{ fmt::Debug, path::{Path, PathBuf}, @@ -18,20 +18,41 @@ const DEFAULT_STORAGE_DIR: &str = "pubky"; pub const DEFAULT_LIST_LIMIT: u16 = 100; pub const DEFAULT_MAX_LIST_LIMIT: u16 = 1000; -/// Server configuration -#[derive(Serialize, Deserialize, Clone)] -pub struct Config { - testnet: bool, +#[derive(Serialize, Deserialize, Clone, PartialEq)] +struct ConfigToml { + testnet: Option, port: Option, bootstrap: Option>, - domain: String, - /// Path to the storage directory + domain: Option, + storage: Option, + secret_key: Option, + dht_request_timeout: Option, + default_list_limit: Option, + max_list_limit: Option, +} + +/// Server configuration +#[derive(Debug, Clone)] +pub struct Config { + /// Whether or not this server is running in a testnet. + testnet: bool, + /// The configured port for this server. + port: Option, + /// Bootstrapping DHT nodes. + /// + /// Helpful to run the server locally or in testnet. + bootstrap: Option>, + /// A public domain for this server + /// necessary for web browsers running in https environment. + domain: Option, + /// Path to the storage directory. /// /// Defaults to a directory in the OS data directory - storage: Option, - #[serde(deserialize_with = "secret_key_deserialize")] - secret_key: Option<[u8; 32]>, - + storage: PathBuf, + /// Server keypair. + /// + /// Defaults to a random keypair. + keypair: Keypair, dht_request_timeout: Option, /// The default limit of a list api if no `limit` query parameter is provided. /// @@ -44,13 +65,42 @@ pub struct Config { } impl Config { - /// Load the config from a file. - pub async fn load(path: impl AsRef) -> Result { - let s = tokio::fs::read_to_string(path.as_ref()) - .await - .with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?; + fn try_from_str(value: &str) -> Result { + let config_toml: ConfigToml = toml::from_str(value)?; - let config: Config = toml::from_str(&s)?; + let keypair = if let Some(secret_key) = config_toml.secret_key { + let secret_key = deserialize_secret_key(secret_key)?; + Keypair::from_secret_key(&secret_key) + } else { + Keypair::random() + }; + + let storage = { + let dir = if let Some(storage) = config_toml.storage { + storage + } else { + let path = dirs_next::data_dir().ok_or_else(|| { + anyhow!("operating environment provides no directory for application data") + })?; + path.join(DEFAULT_STORAGE_DIR) + }; + + dir.join("homeserver") + }; + + let config = Config { + testnet: config_toml.testnet.unwrap_or(false), + port: config_toml.port, + bootstrap: config_toml.bootstrap, + domain: config_toml.domain, + keypair, + storage, + dht_request_timeout: config_toml.dht_request_timeout, + default_list_limit: config_toml.default_list_limit.unwrap_or(DEFAULT_LIST_LIMIT), + max_list_limit: config_toml + .default_list_limit + .unwrap_or(DEFAULT_MAX_LIST_LIMIT), + }; if config.testnet { let testnet_config = Config::testnet(); @@ -64,17 +114,24 @@ impl Config { Ok(config) } + /// Load the config from a file. + pub async fn load(path: impl AsRef) -> Result { + let s = tokio::fs::read_to_string(path.as_ref()) + .await + .with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?; + + Config::try_from_str(&s) + } + /// Testnet configurations pub fn testnet() -> Self { let testnet = pkarr::mainline::Testnet::new(10); info!(?testnet.bootstrap, "Testnet bootstrap nodes"); let bootstrap = Some(testnet.bootstrap.to_owned()); - let storage = Some( - std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join(DEFAULT_STORAGE_DIR), - ); + let storage = std::env::temp_dir() + .join(Timestamp::now().to_string()) + .join(DEFAULT_STORAGE_DIR); Self { bootstrap, @@ -88,11 +145,9 @@ impl Config { /// Test configurations pub fn test(testnet: &pkarr::mainline::Testnet) -> Self { let bootstrap = Some(testnet.bootstrap.to_owned()); - let storage = Some( - std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join(DEFAULT_STORAGE_DIR), - ); + let storage = std::env::temp_dir() + .join(Timestamp::now().to_string()) + .join(DEFAULT_STORAGE_DIR); Self { bootstrap, @@ -109,12 +164,12 @@ impl Config { self.bootstrap.to_owned() } - pub fn domain(&self) -> &str { + pub fn domain(&self) -> &Option { &self.domain } - pub fn keypair(&self) -> Keypair { - Keypair::from_secret_key(&self.secret_key.unwrap_or_default()) + pub fn keypair(&self) -> &Keypair { + &self.keypair } pub fn default_list_limit(&self) -> u16 { @@ -126,17 +181,8 @@ impl Config { } /// Get the path to the storage directory - pub fn storage(&self) -> Result { - let dir = if let Some(storage) = &self.storage { - PathBuf::from(storage) - } else { - let path = dirs_next::data_dir().ok_or_else(|| { - anyhow!("operating environment provides no directory for application data") - })?; - path.join(DEFAULT_STORAGE_DIR) - }; - - Ok(dir.join("homeserver")) + pub fn storage(&self) -> &PathBuf { + &self.storage } pub(crate) fn dht_request_timeout(&self) -> Option { @@ -150,9 +196,10 @@ impl Default for Config { testnet: false, port: Some(0), bootstrap: None, - domain: "localhost".to_string(), - storage: None, - secret_key: None, + domain: None, + storage: storage(None) + .expect("operating environment provides no directory for application data"), + keypair: Keypair::random(), dht_request_timeout: None, default_list_limit: DEFAULT_LIST_LIMIT, max_list_limit: DEFAULT_MAX_LIST_LIMIT, @@ -160,35 +207,42 @@ impl Default for Config { } } -fn secret_key_deserialize<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let opt: Option = Option::deserialize(deserializer)?; +fn deserialize_secret_key(s: String) -> anyhow::Result<[u8; 32]> { + let bytes = + hex::decode(s).map_err(|_| anyhow!("secret_key in config.toml should hex encoded"))?; - match opt { - Some(s) => { - let bytes = hex::decode(s).map_err(serde::de::Error::custom)?; - - if bytes.len() != 32 { - return Err(serde::de::Error::custom("Expected a 32-byte array")); - } - - let mut arr = [0u8; 32]; - arr.copy_from_slice(&bytes); - Ok(Some(arr)) - } - None => Ok(None), + if bytes.len() != 32 { + return Err(anyhow!(format!( + "secret_key in config.toml should be 32 bytes in hex (64 characters), got: {}", + bytes.len() + ))); } + + let mut arr = [0u8; 32]; + arr.copy_from_slice(&bytes); + + Ok(arr) } -impl Debug for Config { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_map() - .entry(&"testnet", &self.testnet) - .entry(&"port", &self.port()) - .entry(&"storage", &self.storage()) - .entry(&"public_key", &self.keypair().public_key()) - .finish() +fn storage(storage: Option) -> Result { + let dir = if let Some(storage) = storage { + PathBuf::from(storage) + } else { + let path = dirs_next::data_dir().ok_or_else(|| { + anyhow!("operating environment provides no directory for application data") + })?; + path.join(DEFAULT_STORAGE_DIR) + }; + + Ok(dir.join("homeserver")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_empty() { + Config::try_from_str("").unwrap(); } } diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index 4b282a1..ef82d0b 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -20,16 +20,14 @@ pub struct DB { impl DB { pub fn open(config: Config) -> anyhow::Result { - let storage = config.storage()?; - - fs::create_dir_all(&storage).unwrap(); + fs::create_dir_all(config.storage())?; let env = unsafe { EnvOpenOptions::new() .max_dbs(TABLES_COUNT) // TODO: Add a configuration option? .map_size(DEFAULT_MAP_SIZE) - .open(storage) + .open(config.storage()) }?; let tables = migrations::run(&env)?; diff --git a/pubky-homeserver/src/server.rs b/pubky-homeserver/src/server.rs index 44716f7..d44d346 100644 --- a/pubky-homeserver/src/server.rs +++ b/pubky-homeserver/src/server.rs @@ -31,8 +31,6 @@ impl Homeserver { pub async fn start(config: Config) -> Result { debug!(?config); - let keypair = config.keypair(); - let db = DB::open(config.clone())?; let pkarr_client = PkarrClient::new(Settings { @@ -55,7 +53,7 @@ impl Homeserver { verifier: AuthVerifier::default(), db, pkarr_client, - config, + config: config.clone(), port, }; @@ -73,9 +71,22 @@ impl Homeserver { info!("Homeserver listening on http://localhost:{port}"); - publish_server_packet(&state.pkarr_client, &keypair, state.config.domain(), port).await?; + publish_server_packet( + &state.pkarr_client, + config.keypair(), + &state + .config + .domain() + .clone() + .unwrap_or("localhost".to_string()), + port, + ) + .await?; - info!("Homeserver listening on pubky://{}", keypair.public_key()); + info!( + "Homeserver listening on pubky://{}", + config.keypair().public_key() + ); Ok(Self { tasks, state }) } From f2a4fe39026d3efb21262dac4da80d7fafd165fa Mon Sep 17 00:00:00 2001 From: nazeh Date: Sat, 28 Sep 2024 08:05:21 +0300 Subject: [PATCH 07/12] feat(pubky): add [PubkyClient::pkarr] method to return ref to pkarr client --- pubky/src/native.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pubky/src/native.rs b/pubky/src/native.rs index 2a77039..81924ba 100644 --- a/pubky/src/native.rs +++ b/pubky/src/native.rs @@ -11,7 +11,7 @@ use reqwest::{RequestBuilder, Response}; use tokio::sync::oneshot; use url::Url; -use pkarr::Keypair; +use pkarr::{Keypair, PkarrClientAsync}; use ::pkarr::{mainline::dht::Testnet, PkarrClient, PublicKey, SignedPacket}; @@ -112,6 +112,13 @@ impl PubkyClient { builder.build() } + // === Getters === + + /// Returns a reference to the internal [pkarr] Client. + pub fn pkarr(&self) -> &PkarrClientAsync { + &self.pkarr + } + // === Auth === /// Signup to a homeserver and update Pkarr accordingly. From e031c7a9dd32454961d903bd7813273c10cddab3 Mon Sep 17 00:00:00 2001 From: nazeh Date: Sat, 28 Sep 2024 08:13:42 +0300 Subject: [PATCH 08/12] fix(common): Session::deserialize better error for empty payloads --- pubky-common/src/session.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pubky-common/src/session.rs b/pubky-common/src/session.rs index 5ce64d0..494265f 100644 --- a/pubky-common/src/session.rs +++ b/pubky-common/src/session.rs @@ -68,6 +68,10 @@ impl Session { } pub fn deserialize(bytes: &[u8]) -> Result { + if bytes.is_empty() { + return Err(Error::EmptyPayload); + } + if bytes[0] > 0 { return Err(Error::UnknownVersion); } @@ -82,6 +86,8 @@ pub type Result = core::result::Result; #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Empty payload")] + EmptyPayload, #[error("Unknown version")] UnknownVersion, #[error(transparent)] @@ -123,4 +129,9 @@ mod tests { assert_eq!(deseiralized, session) } + + #[test] + fn deserialize() { + let deseiralized = Session::deserialize(&[]).unwrap(); + } } From 842b9f32c80a572b8e764127f431e34ba25c133c Mon Sep 17 00:00:00 2001 From: nazeh Date: Sat, 28 Sep 2024 08:35:43 +0300 Subject: [PATCH 09/12] feat(homeserver): treat (empty) as None' --- pubky-common/src/session.rs | 6 ++- .../src/database/tables/events.rs | 4 +- pubky-homeserver/src/extractors.rs | 49 ++++++++++++++++++- pubky-homeserver/src/routes/feed.rs | 14 ++---- pubky-homeserver/src/routes/public.rs | 16 +++--- 5 files changed, 66 insertions(+), 23 deletions(-) diff --git a/pubky-common/src/session.rs b/pubky-common/src/session.rs index 494265f..972652c 100644 --- a/pubky-common/src/session.rs +++ b/pubky-common/src/session.rs @@ -84,7 +84,7 @@ impl Session { pub type Result = core::result::Result; -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, PartialEq)] pub enum Error { #[error("Empty payload")] EmptyPayload, @@ -132,6 +132,8 @@ mod tests { #[test] fn deserialize() { - let deseiralized = Session::deserialize(&[]).unwrap(); + let result = Session::deserialize(&[]); + + assert_eq!(result, Err(Error::EmptyPayload)); } } diff --git a/pubky-homeserver/src/database/tables/events.rs b/pubky-homeserver/src/database/tables/events.rs index 1829765..76a4d46 100644 --- a/pubky-homeserver/src/database/tables/events.rs +++ b/pubky-homeserver/src/database/tables/events.rs @@ -67,7 +67,7 @@ impl DB { pub fn list_events( &self, limit: Option, - cursor: Option<&str>, + cursor: Option, ) -> anyhow::Result> { let txn = self.env.read_txn()?; @@ -75,7 +75,7 @@ impl DB { .unwrap_or(self.config.default_list_limit()) .min(self.config.max_list_limit()); - let cursor = cursor.unwrap_or("0000000000000"); + let cursor = cursor.unwrap_or("0000000000000".to_string()); let mut result: Vec = vec![]; let mut next_cursor = cursor.to_string(); diff --git a/pubky-homeserver/src/extractors.rs b/pubky-homeserver/src/extractors.rs index 567ca6b..779ce65 100644 --- a/pubky-homeserver/src/extractors.rs +++ b/pubky-homeserver/src/extractors.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use axum::{ async_trait, - extract::{FromRequestParts, Path}, + extract::{FromRequestParts, Path, Query}, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, RequestPartsExt, @@ -74,3 +74,50 @@ where Ok(EntryPath(path.to_string())) } } + +#[derive(Debug)] +pub struct ListQueryParams { + pub limit: Option, + pub cursor: Option, + pub reverse: bool, + pub shallow: bool, +} + +#[async_trait] +impl FromRequestParts for ListQueryParams +where + S: Send + Sync, +{ + type Rejection = Response; + + async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { + let params: Query> = + parts.extract().await.map_err(IntoResponse::into_response)?; + + let reverse = params.contains_key("reverse"); + let shallow = params.contains_key("shallow"); + let limit = params + .get("limit") + // Treat `limit=` as None + .and_then(|l| if l.is_empty() { None } else { Some(l) }) + .and_then(|l| l.parse::().ok()); + let cursor = params + .get("cursor") + .map(|c| c.as_str()) + // Treat `cursor=` as None + .and_then(|c| { + if c.is_empty() { + None + } else { + Some(c.to_string()) + } + }); + + Ok(ListQueryParams { + reverse, + shallow, + limit, + cursor, + }) + } +} diff --git a/pubky-homeserver/src/routes/feed.rs b/pubky-homeserver/src/routes/feed.rs index 627eb3e..6271aeb 100644 --- a/pubky-homeserver/src/routes/feed.rs +++ b/pubky-homeserver/src/routes/feed.rs @@ -1,8 +1,6 @@ -use std::collections::HashMap; - use axum::{ body::Body, - extract::{Query, State}, + extract::State, http::{header, Response, StatusCode}, response::IntoResponse, }; @@ -10,17 +8,15 @@ use pubky_common::timestamp::{Timestamp, TimestampError}; use crate::{ error::{Error, Result}, + extractors::ListQueryParams, server::AppState, }; pub async fn feed( State(state): State, - Query(params): Query>, + params: ListQueryParams, ) -> Result { - let limit = params.get("limit").and_then(|l| l.parse::().ok()); - let cursor = params.get("cursor").map(|c| c.as_str()); - - if let Some(cursor) = cursor { + if let Some(ref cursor) = params.cursor { if let Err(timestmap_error) = Timestamp::try_from(cursor.to_string()) { let cause = match timestmap_error { TimestampError::InvalidEncoding => { @@ -35,7 +31,7 @@ pub async fn feed( } } - let result = state.db.list_events(limit, cursor)?; + let result = state.db.list_events(params.limit, params.cursor)?; Ok(Response::builder() .status(StatusCode::OK) diff --git a/pubky-homeserver/src/routes/public.rs b/pubky-homeserver/src/routes/public.rs index 4cf2eed..8c6b2b9 100644 --- a/pubky-homeserver/src/routes/public.rs +++ b/pubky-homeserver/src/routes/public.rs @@ -1,8 +1,6 @@ -use std::collections::HashMap; - use axum::{ body::{Body, Bytes}, - extract::{Query, State}, + extract::State, http::{header, Response, StatusCode}, response::IntoResponse, }; @@ -12,7 +10,7 @@ use tower_cookies::Cookies; use crate::{ error::{Error, Result}, - extractors::{EntryPath, Pubky}, + extractors::{EntryPath, ListQueryParams, Pubky}, server::AppState, }; @@ -65,7 +63,7 @@ pub async fn get( State(state): State, pubky: Pubky, path: EntryPath, - Query(params): Query>, + params: ListQueryParams, ) -> Result { verify(path.as_str())?; let public_key = pubky.public_key(); @@ -88,10 +86,10 @@ pub async fn get( let vec = state.db.list( &txn, &path, - params.contains_key("reverse"), - params.get("limit").and_then(|l| l.parse::().ok()), - params.get("cursor").map(|cursor| cursor.into()), - params.contains_key("shallow"), + params.reverse, + params.limit, + params.cursor, + params.shallow, )?; return Ok(Response::builder() From f48f5f69bc7e8147c3c8216a4361b273bbbef8b3 Mon Sep 17 00:00:00 2001 From: nazeh Date: Sun, 29 Sep 2024 14:04:39 +0300 Subject: [PATCH 10/12] docs: small fix in Auth spec --- docs/src/spec/auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/spec/auth.md b/docs/src/spec/auth.md index 62c57bf..92a3041 100644 --- a/docs/src/spec/auth.md +++ b/docs/src/spec/auth.md @@ -79,7 +79,7 @@ pubkyauth:/// ```abnf AuthToken = signature namespace version timestamp pubky capabilities -signature = 64OCTET ; ed25519 signature over encoded DNS packet +signature = 64OCTET ; ed25519 signature over the rest of the token. namespace = %x50.55.42.4b.59.3a.41.55.54.48 ; "PUBKY:AUTH" in UTF-8 (10 bytes) version = 1*OCTET ; Version of the AuthToken for future proofing. timestamp = 8OCTET ; Big-endian UNIX timestamp in microseconds From b9ce4bc49cfb03146f5bff36f73a1d970c66a81f Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 30 Sep 2024 12:37:17 +0300 Subject: [PATCH 11/12] feat(homeserver): add Config::db_map_size and set it to 10mb in Config::test; --- Cargo.lock | 51 +++++++++++++----- Cargo.toml | 2 +- pubky-homeserver/src/config.rs | 93 +++++++++++++++++++++++++------- pubky-homeserver/src/database.rs | 5 +- 4 files changed, 114 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a712105..72ff022 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1425,7 +1425,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkarr" version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=v3#17975121c809d97dcad907fbb2ffc782e994d270" +source = "git+https://github.com/Pubky/pkarr?branch=serde#680ec9303f5f3ee4b40dc53c0071c4088d4eb6ff" dependencies = [ "base32", "bytes", @@ -1734,9 +1734,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", @@ -1773,7 +1773,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "webpki-roots", - "winreg", + "windows-registry", ] [[package]] @@ -2148,6 +2148,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synchronoise" @@ -2646,6 +2649,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2794,16 +2827,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "zeroize" version = "1.8.1" diff --git a/Cargo.toml b/Cargo.toml index 8514809..acd72a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ resolver = "2" [workspace.dependencies] -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr", features = ["async"] } +pkarr = { git = "https://github.com/Pubky/pkarr", branch = "serde", package = "pkarr", features = ["async"] } serde = { version = "^1.0.209", features = ["derive"] } [profile.release] diff --git a/pubky-homeserver/src/config.rs b/pubky-homeserver/src/config.rs index f182a52..6065306 100644 --- a/pubky-homeserver/src/config.rs +++ b/pubky-homeserver/src/config.rs @@ -12,9 +12,11 @@ use tracing::info; use pubky_common::timestamp::Timestamp; -const DEFAULT_HOMESERVER_PORT: u16 = 6287; +// === Database === const DEFAULT_STORAGE_DIR: &str = "pubky"; +pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) +// === Server == pub const DEFAULT_LIST_LIMIT: u16 = 100; pub const DEFAULT_MAX_LIST_LIMIT: u16 = 1000; @@ -29,15 +31,16 @@ struct ConfigToml { dht_request_timeout: Option, default_list_limit: Option, max_list_limit: Option, + db_map_size: Option, } /// Server configuration -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Config { /// Whether or not this server is running in a testnet. testnet: bool, /// The configured port for this server. - port: Option, + port: u16, /// Bootstrapping DHT nodes. /// /// Helpful to run the server locally or in testnet. @@ -62,6 +65,9 @@ pub struct Config { /// /// Defaults to `1000` max_list_limit: u16, + + // === Database params === + db_map_size: usize, } impl Config { @@ -90,7 +96,7 @@ impl Config { let config = Config { testnet: config_toml.testnet.unwrap_or(false), - port: config_toml.port, + port: config_toml.port.unwrap_or(0), bootstrap: config_toml.bootstrap, domain: config_toml.domain, keypair, @@ -100,6 +106,7 @@ impl Config { max_list_limit: config_toml .default_list_limit .unwrap_or(DEFAULT_MAX_LIST_LIMIT), + db_map_size: config_toml.db_map_size.unwrap_or(DEFAULT_MAP_SIZE), }; if config.testnet { @@ -128,17 +135,11 @@ impl Config { let testnet = pkarr::mainline::Testnet::new(10); info!(?testnet.bootstrap, "Testnet bootstrap nodes"); - let bootstrap = Some(testnet.bootstrap.to_owned()); - let storage = std::env::temp_dir() - .join(Timestamp::now().to_string()) - .join(DEFAULT_STORAGE_DIR); - - Self { - bootstrap, - storage, - port: Some(15411), - dht_request_timeout: Some(Duration::from_millis(10)), - ..Default::default() + Config { + port: 15411, + dht_request_timeout: None, + db_map_size: DEFAULT_MAP_SIZE, + ..Self::test(&testnet) } } @@ -150,14 +151,17 @@ impl Config { .join(DEFAULT_STORAGE_DIR); Self { + testnet: true, bootstrap, storage, + db_map_size: 10485760, + dht_request_timeout: Some(Duration::from_millis(10)), ..Default::default() } } pub fn port(&self) -> u16 { - self.port.unwrap_or(DEFAULT_HOMESERVER_PORT) + self.port } pub fn bootstsrap(&self) -> Option> { @@ -188,13 +192,17 @@ impl Config { pub(crate) fn dht_request_timeout(&self) -> Option { self.dht_request_timeout } + + pub(crate) fn db_map_size(&self) -> usize { + self.db_map_size + } } impl Default for Config { fn default() -> Self { Self { testnet: false, - port: Some(0), + port: 0, bootstrap: None, domain: None, storage: storage(None) @@ -203,6 +211,7 @@ impl Default for Config { dht_request_timeout: None, default_list_limit: DEFAULT_LIST_LIMIT, max_list_limit: DEFAULT_MAX_LIST_LIMIT, + db_map_size: DEFAULT_MAP_SIZE, } } } @@ -239,10 +248,58 @@ fn storage(storage: Option) -> Result { #[cfg(test)] mod tests { + use pkarr::mainline::Testnet; + use super::*; #[test] fn parse_empty() { - Config::try_from_str("").unwrap(); + let config = Config::try_from_str("").unwrap(); + + assert_eq!( + config, + Config { + keypair: config.keypair.clone(), + ..Default::default() + } + ) + } + + #[test] + fn config_test() { + let testnet = Testnet::new(3); + let config = Config::test(&testnet); + + assert_eq!( + config, + Config { + testnet: true, + bootstrap: testnet.bootstrap.into(), + db_map_size: 10485760, + dht_request_timeout: Some(Duration::from_millis(10)), + + storage: config.storage.clone(), + keypair: config.keypair.clone(), + ..Default::default() + } + ) + } + + #[test] + fn config_testnet() { + let config = Config::testnet(); + + assert_eq!( + config, + Config { + testnet: true, + port: 15411, + + bootstrap: config.bootstrap.clone(), + storage: config.storage.clone(), + keypair: config.keypair.clone(), + ..Default::default() + } + ) } } diff --git a/pubky-homeserver/src/database.rs b/pubky-homeserver/src/database.rs index ef82d0b..e95d1d2 100644 --- a/pubky-homeserver/src/database.rs +++ b/pubky-homeserver/src/database.rs @@ -9,8 +9,6 @@ use crate::config::Config; use tables::{Tables, TABLES_COUNT}; -pub const DEFAULT_MAP_SIZE: usize = 10995116277760; // 10TB (not = disk-space used) - #[derive(Debug, Clone)] pub struct DB { pub(crate) env: Env, @@ -25,8 +23,7 @@ impl DB { let env = unsafe { EnvOpenOptions::new() .max_dbs(TABLES_COUNT) - // TODO: Add a configuration option? - .map_size(DEFAULT_MAP_SIZE) + .map_size(config.db_map_size()) .open(config.storage()) }?; From 4730927226614361a45d2fbadd92e22f2f8d0801 Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 30 Sep 2024 13:37:29 +0300 Subject: [PATCH 12/12] chore: update Cargo.lock --- Cargo.lock | 379 +++++++++++++++++++++++++++++------------------------ 1 file changed, 205 insertions(+), 174 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72ff022..d5af9d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "argon2" @@ -105,21 +105,21 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -151,15 +151,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -192,9 +192,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -205,7 +205,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" +checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" dependencies = [ "axum", "axum-core", @@ -238,11 +238,10 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", "syn", @@ -250,17 +249,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -316,9 +315,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -350,15 +349,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.3" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e2d530f35b40a84124146478cd16f34225306a8441998836466a2e2961c950" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -379,9 +381,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", "clap_derive", @@ -389,9 +391,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstream", "anstyle", @@ -401,11 +403,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn", @@ -437,9 +439,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "cookie" @@ -471,9 +473,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -495,9 +497,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "crossbeam-queue" @@ -674,6 +676,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "equivalent" version = "1.0.1" @@ -828,9 +836,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "hash32" @@ -885,12 +893,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -899,9 +901,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "heed" -version = "0.20.3" +version = "0.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc30da4a93ff8cb98e535d595d6de42731d4719d707bc1c86f579158751a24e" +checksum = "7d4f449bab7320c56003d37732a917e18798e2f1709d80263face2b4f9436ddb" dependencies = [ "bitflags", "byteorder", @@ -1015,9 +1017,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", @@ -1033,9 +1035,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -1046,7 +1048,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1073,9 +1074,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1092,9 +1093,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is_terminal_polyfill" @@ -1125,9 +1126,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libredox" @@ -1147,9 +1148,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lmdb-master-sys" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57640c190703d5ccf4a86aff4aeb749b2d287a8cb1723c76b51f39d77ab53b24" +checksum = "472c3760e2a8d0f61f322fb36788021bb36d573c502b50fa3e2bcaac3ec326c9" dependencies = [ "cc", "doxygen-rs", @@ -1174,9 +1175,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" [[package]] name = "mainline" @@ -1227,11 +1228,11 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1273,18 +1274,21 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "object" -version = "0.36.1" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "opaque-debug" @@ -1390,26 +1394,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1470,13 +1454,20 @@ dependencies = [ ] [[package]] -name = "postcard" -version = "1.0.8" +name = "portable-atomic" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" dependencies = [ "cobs", - "embedded-io", + "embedded-io 0.4.0", + "embedded-io 0.6.1", "heapless", "serde", ] @@ -1489,9 +1480,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" @@ -1583,9 +1577,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ "bytes", "pin-project-lite", @@ -1601,9 +1595,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand", @@ -1618,22 +1612,22 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1670,18 +1664,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -1690,14 +1684,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -1711,13 +1705,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -1728,9 +1722,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -1826,18 +1820,18 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "once_cell", "ring", @@ -1859,15 +1853,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -1915,9 +1909,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -1943,9 +1937,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1954,11 +1948,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1975,9 +1970,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2007,9 +2002,9 @@ dependencies = [ [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -2031,6 +2026,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -2128,9 +2129,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.71" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2163,18 +2164,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -2279,9 +2280,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -2313,9 +2314,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -2326,14 +2327,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -2376,15 +2377,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2468,15 +2469,15 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -2522,9 +2523,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -2569,9 +2570,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -2620,9 +2621,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -2697,6 +2698,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -2820,13 +2830,34 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.8.1"