From 12b9aefa9902bab0a8520aec1184578a9c41dc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 25 Nov 2024 08:39:55 +0000 Subject: [PATCH 01/11] bugfix: correctly expose ecash-related data on nym-api (#5155) * fixed signer related endpoints * fixed aggregation of partial data if the api is not a signer * fixes to swagger docs for global ecash endpoints * remove unused axum_macros * fixed test traits --- nym-api/Cargo.toml | 2 +- nym-api/src/ecash/api_routes/aggregation.rs | 32 +++++++----------- nym-api/src/ecash/api_routes/handlers.rs | 12 +++---- nym-api/src/ecash/api_routes/helpers.rs | 1 - nym-api/src/ecash/api_routes/issued.rs | 18 ++++------ .../src/ecash/api_routes/partial_signing.rs | 28 +++++----------- nym-api/src/ecash/api_routes/spending.rs | 29 +++++----------- nym-api/src/ecash/client.rs | 2 +- nym-api/src/ecash/dkg/client.rs | 8 ++--- nym-api/src/ecash/dkg/dealing.rs | 4 +-- nym-api/src/ecash/dkg/key_derivation.rs | 2 +- nym-api/src/ecash/dkg/key_validation.rs | 8 ++--- nym-api/src/ecash/error.rs | 3 ++ nym-api/src/ecash/state/mod.rs | 12 ++++--- nym-api/src/ecash/tests/fixtures.rs | 2 +- nym-api/src/ecash/tests/helpers.rs | 2 +- nym-api/src/ecash/tests/mod.rs | 13 +++++--- nym-api/src/epoch_operations/error.rs | 3 ++ nym-api/src/epoch_operations/mod.rs | 13 +++++--- nym-api/src/status/handlers.rs | 33 +++++-------------- nym-api/src/status/mod.rs | 29 +++++++++++----- nym-api/src/support/cli/run.rs | 17 ++++------ nym-api/src/support/http/router.rs | 3 ++ nym-api/src/support/http/state.rs | 18 ++++++++++ nym-api/src/support/nyxd/mod.rs | 30 ++++++++--------- 25 files changed, 154 insertions(+), 170 deletions(-) diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 6f9602eb06..ea2e3ed212 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -121,7 +121,7 @@ nym-types = { path = "../common/types" } nym-http-api-common = { path = "../common/http-api-common", features = ["utoipa"] } nym-serde-helpers = { path = "../common/serde-helpers", features = ["date"] } nym-ticketbooks-merkle = { path = "../common/ticketbooks-merkle" } -nym-statistics-common = {path ="../common/statistics" } +nym-statistics-common = { path = "../common/statistics" } [features] no-reward = [] diff --git a/nym-api/src/ecash/api_routes/aggregation.rs b/nym-api/src/ecash/api_routes/aggregation.rs index 89478fbd09..8b7baef6e6 100644 --- a/nym-api/src/ecash/api_routes/aggregation.rs +++ b/nym-api/src/ecash/api_routes/aggregation.rs @@ -6,7 +6,7 @@ use crate::ecash::error::EcashError; use crate::ecash::state::EcashState; use crate::node_status_api::models::AxumResult; use crate::support::http::state::AppState; -use axum::extract::Path; +use axum::extract::{Query, State}; use axum::{Json, Router}; use nym_api_requests::ecash::models::{ AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse, @@ -21,28 +21,19 @@ use tracing::trace; use utoipa::IntoParams; /// routes with globally aggregated keys, signatures, etc. -pub(crate) fn aggregation_routes(ecash_state: Arc) -> Router { +pub(crate) fn aggregation_routes() -> Router { Router::new() .route( "/master-verification-key", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |epoch_id| master_verification_key(epoch_id, ecash_state) - }), + axum::routing::get(master_verification_key), ) .route( "/aggregated-expiration-date-signatures", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |expiration_date| expiration_date_signatures(expiration_date, ecash_state) - }), + axum::routing::get(expiration_date_signatures), ) .route( "/aggregated-coin-indices-signatures", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |epoch_id| coin_indices_signatures(epoch_id, ecash_state) - }), + axum::routing::get(coin_indices_signatures), ) } @@ -58,8 +49,8 @@ pub(crate) fn aggregation_routes(ecash_state: Arc) -> Router, - state: Arc, + State(state): State>, + Query(EpochIdParam { epoch_id }): Query, ) -> AxumResult> { trace!("aggregated_verification_key request"); @@ -72,7 +63,6 @@ async fn master_verification_key( } #[derive(Deserialize, IntoParams)] -#[into_params(parameter_in = Path)] struct ExpirationDateParam { expiration_date: Option, } @@ -89,8 +79,8 @@ struct ExpirationDateParam { ) )] async fn expiration_date_signatures( - Path(ExpirationDateParam { expiration_date }): Path, - state: Arc, + State(state): State>, + Query(ExpirationDateParam { expiration_date }): Query, ) -> AxumResult> { trace!("aggregated_expiration_date_signatures request"); @@ -126,8 +116,8 @@ async fn expiration_date_signatures( ) )] async fn coin_indices_signatures( - Path(EpochIdParam { epoch_id }): Path, - state: Arc, + Query(EpochIdParam { epoch_id }): Query, + State(state): State>, ) -> AxumResult> { trace!("aggregated_coin_indices_signatures request"); diff --git a/nym-api/src/ecash/api_routes/handlers.rs b/nym-api/src/ecash/api_routes/handlers.rs index e9f97c48b0..9114ebba9f 100644 --- a/nym-api/src/ecash/api_routes/handlers.rs +++ b/nym-api/src/ecash/api_routes/handlers.rs @@ -5,15 +5,13 @@ use crate::ecash::api_routes::aggregation::aggregation_routes; use crate::ecash::api_routes::issued::issued_routes; use crate::ecash::api_routes::partial_signing::partial_signing_routes; use crate::ecash::api_routes::spending::spending_routes; -use crate::ecash::state::EcashState; use crate::support::http::state::AppState; use axum::Router; -use std::sync::Arc; -pub(crate) fn ecash_routes(ecash_state: Arc) -> Router { +pub(crate) fn ecash_routes() -> Router { Router::new() - .merge(aggregation_routes(Arc::clone(&ecash_state))) - .merge(issued_routes(Arc::clone(&ecash_state))) - .merge(partial_signing_routes(Arc::clone(&ecash_state))) - .merge(spending_routes(Arc::clone(&ecash_state))) + .merge(aggregation_routes()) + .merge(issued_routes()) + .merge(partial_signing_routes()) + .merge(spending_routes()) } diff --git a/nym-api/src/ecash/api_routes/helpers.rs b/nym-api/src/ecash/api_routes/helpers.rs index 0e7afa9b39..9d0270acc7 100644 --- a/nym-api/src/ecash/api_routes/helpers.rs +++ b/nym-api/src/ecash/api_routes/helpers.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-3.0-only #[derive(serde::Deserialize, utoipa::IntoParams)] -#[into_params(parameter_in = Path)] pub(super) struct EpochIdParam { pub(super) epoch_id: Option, } diff --git a/nym-api/src/ecash/api_routes/issued.rs b/nym-api/src/ecash/api_routes/issued.rs index 023b57f6a3..376b532475 100644 --- a/nym-api/src/ecash/api_routes/issued.rs +++ b/nym-api/src/ecash/api_routes/issued.rs @@ -4,7 +4,7 @@ use crate::ecash::state::EcashState; use crate::node_status_api::models::AxumResult; use crate::support::http::state::AppState; -use axum::extract::Path; +use axum::extract::{Path, State}; use axum::{Json, Router}; use nym_api_requests::ecash::models::{ IssuedTicketbooksChallengeRequest, IssuedTicketbooksChallengeResponse, @@ -17,21 +17,15 @@ use time::Date; use tracing::trace; use utoipa::{IntoParams, ToSchema}; -pub(crate) fn issued_routes(ecash_state: Arc) -> Router { +pub(crate) fn issued_routes() -> Router { Router::new() .route( "/issued-ticketbooks-for/:expiration_date", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |expiration_date| issued_ticketbooks_for(expiration_date, ecash_state) - }), + axum::routing::get(issued_ticketbooks_for), ) .route( "/issued-ticketbooks-challenge", - axum::routing::post({ - let ecash_state = Arc::clone(&ecash_state); - |body| issued_ticketbooks_challenge(body, ecash_state) - }), + axum::routing::post(issued_ticketbooks_challenge), ) } @@ -58,8 +52,8 @@ pub(crate) struct ExpirationDatePathParam { ) )] async fn issued_ticketbooks_for( + State(state): State>, Path(ExpirationDatePathParam { expiration_date }): Path, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; @@ -83,8 +77,8 @@ async fn issued_ticketbooks_for( ) )] async fn issued_ticketbooks_challenge( + State(state): State>, Json(challenge): Json, - state: Arc, ) -> AxumResult> { trace!("replying to ticketbooks challenge: {:?}", challenge); state.ensure_signer().await?; diff --git a/nym-api/src/ecash/api_routes/partial_signing.rs b/nym-api/src/ecash/api_routes/partial_signing.rs index 7deb919d4e..afe522cbee 100644 --- a/nym-api/src/ecash/api_routes/partial_signing.rs +++ b/nym-api/src/ecash/api_routes/partial_signing.rs @@ -7,7 +7,7 @@ use crate::ecash::helpers::blind_sign; use crate::ecash::state::EcashState; use crate::node_status_api::models::AxumResult; use crate::support::http::state::AppState; -use axum::extract::Query; +use axum::extract::{Query, State}; use axum::{Json, Router}; use nym_api_requests::ecash::{ BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse, @@ -22,28 +22,16 @@ use time::Date; use tracing::{debug, trace}; use utoipa::IntoParams; -pub(crate) fn partial_signing_routes(ecash_state: Arc) -> Router { +pub(crate) fn partial_signing_routes() -> Router { Router::new() - .route( - "/blind-sign", - axum::routing::post({ - let ecash_state = Arc::clone(&ecash_state); - |body| post_blind_sign(body, ecash_state) - }), - ) + .route("/blind-sign", axum::routing::post(post_blind_sign)) .route( "/partial-expiration-date-signatures", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |expiration_date| partial_expiration_date_signatures(expiration_date, ecash_state) - }), + axum::routing::get(partial_expiration_date_signatures), ) .route( "/partial-coin-indices-signatures", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - |epoch_id| partial_coin_indices_signatures(epoch_id, ecash_state) - }), + axum::routing::get(partial_coin_indices_signatures), ) } @@ -59,8 +47,8 @@ pub(crate) fn partial_signing_routes(ecash_state: Arc) -> Router>, Json(blind_sign_request_body): Json, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; @@ -134,8 +122,8 @@ struct ExpirationDateParam { ) )] async fn partial_expiration_date_signatures( + State(state): State>, Query(ExpirationDateParam { expiration_date }): Query, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; @@ -172,8 +160,8 @@ async fn partial_expiration_date_signatures( ) )] async fn partial_coin_indices_signatures( + State(state): State>, Query(EpochIdParam { epoch_id }): Query, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; diff --git a/nym-api/src/ecash/api_routes/spending.rs b/nym-api/src/ecash/api_routes/spending.rs index b9788a4585..3bda629174 100644 --- a/nym-api/src/ecash/api_routes/spending.rs +++ b/nym-api/src/ecash/api_routes/spending.rs @@ -5,6 +5,7 @@ use crate::ecash::error::EcashError; use crate::ecash::state::EcashState; use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; use crate::support::http::state::AppState; +use axum::extract::State; use axum::{Json, Router}; use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY; use nym_api_requests::ecash::models::{ @@ -21,28 +22,16 @@ use time::{OffsetDateTime, Time}; use tracing::{error, warn}; #[allow(deprecated)] -pub(crate) fn spending_routes(ecash_state: Arc) -> Router { +pub(crate) fn spending_routes() -> Router { Router::new() - .route( - "/verify-ecash-ticket", - axum::routing::post({ - let ecash_state = Arc::clone(&ecash_state); - |body| verify_ticket(body, ecash_state) - }), - ) + .route("/verify-ecash-ticket", axum::routing::post(verify_ticket)) .route( "/batch-redeem-ecash-tickets", - axum::routing::post({ - let ecash_state = Arc::clone(&ecash_state); - |body| batch_redeem_tickets(body, ecash_state) - }), + axum::routing::post(batch_redeem_tickets), ) .route( "/double-spending-filter-v1", - axum::routing::get({ - let ecash_state = Arc::clone(&ecash_state); - || double_spending_filter_v1(ecash_state) - }), + axum::routing::get(double_spending_filter_v1), ) } @@ -67,9 +56,9 @@ fn reject_ticket( ) )] async fn verify_ticket( + State(state): State>, // TODO in the future: make it send binary data rather than json Json(verify_ticket_body): Json, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; @@ -170,9 +159,9 @@ async fn verify_ticket( ) )] async fn batch_redeem_tickets( + State(state): State>, // TODO in the future: make it send binary data rather than json Json(batch_redeem_credentials_body): Json, - state: Arc, ) -> AxumResult> { state.ensure_signer().await?; @@ -244,8 +233,6 @@ async fn batch_redeem_tickets( ) )] #[deprecated] -async fn double_spending_filter_v1( - _state: Arc, -) -> AxumResult> { +async fn double_spending_filter_v1() -> AxumResult> { AxumResult::Err(AxumErrorResponse::internal_msg("permanently restricted")) } diff --git a/nym-api/src/ecash/client.rs b/nym-api/src/ecash/client.rs index 805252808a..f6887f15e7 100644 --- a/nym-api/src/ecash/client.rs +++ b/nym-api/src/ecash/client.rs @@ -27,7 +27,7 @@ use nym_validator_client::EcashApiClient; #[async_trait] pub trait Client { - async fn address(&self) -> AccountId; + async fn address(&self) -> Result; async fn dkg_contract_address(&self) -> Result; diff --git a/nym-api/src/ecash/dkg/client.rs b/nym-api/src/ecash/dkg/client.rs index 5c8f993690..4cd8d41343 100644 --- a/nym-api/src/ecash/dkg/client.rs +++ b/nym-api/src/ecash/dkg/client.rs @@ -35,7 +35,7 @@ impl DkgClient { } } - pub(crate) async fn get_address(&self) -> AccountId { + pub(crate) async fn get_address(&self) -> Result { self.inner.address().await } @@ -53,7 +53,7 @@ impl DkgClient { pub(crate) async fn group_member(&self) -> Result { self.inner - .group_member(self.get_address().await.to_string()) + .group_member(self.get_address().await?.to_string()) .await } @@ -126,7 +126,7 @@ impl DkgClient { &self, epoch_id: EpochId, ) -> Result, EcashError> { - let address = self.inner.address().await; + let address = self.inner.address().await?; self.get_verification_key_share(epoch_id, address).await } @@ -138,7 +138,7 @@ impl DkgClient { } pub(crate) async fn get_vote(&self, proposal_id: u64) -> Result { - let address = self.get_address().await.to_string(); + let address = self.get_address().await?.to_string(); self.inner.get_vote(proposal_id, address).await } diff --git a/nym-api/src/ecash/dkg/dealing.rs b/nym-api/src/ecash/dkg/dealing.rs index a0ae4ac840..31da8a0ea5 100644 --- a/nym-api/src/ecash/dkg/dealing.rs +++ b/nym-api/src/ecash/dkg/dealing.rs @@ -155,7 +155,7 @@ impl DkgController { resharing: bool, ) -> Result<(), DealingGenerationError> { let dealing_state = self.state.dealing_exchange_state(epoch_id)?; - let address = self.dkg_client.get_address().await.to_string(); + let address = self.dkg_client.get_address().await?.to_string(); let status = self .dkg_client @@ -259,7 +259,7 @@ impl DkgController { .checked_sub(1) .expect("resharing epoch invariant has been broken"); - let address = self.dkg_client.get_address().await; + let address = self.dkg_client.get_address().await?; Ok(self .dkg_client .dealer_in_epoch(previous_epoch_id, address.to_string()) diff --git a/nym-api/src/ecash/dkg/key_derivation.rs b/nym-api/src/ecash/dkg/key_derivation.rs index f3e69e1fe6..46818547d4 100644 --- a/nym-api/src/ecash/dkg/key_derivation.rs +++ b/nym-api/src/ecash/dkg/key_derivation.rs @@ -494,7 +494,7 @@ impl DkgController { // submitted proposals and find the one with our address self.get_validation_proposals() .await? - .get(self.dkg_client.get_address().await.as_ref()) + .get(self.dkg_client.get_address().await?.as_ref()) .copied() .ok_or(KeyDerivationError::UnrecoverableProposalId) } diff --git a/nym-api/src/ecash/dkg/key_validation.rs b/nym-api/src/ecash/dkg/key_validation.rs index aff0ea90ac..cde57df982 100644 --- a/nym-api/src/ecash/dkg/key_validation.rs +++ b/nym-api/src/ecash/dkg/key_validation.rs @@ -155,7 +155,7 @@ impl DkgController { }; // if this is our share, obviously vote for yes without spending time on verification - if owner.as_ref() == self.dkg_client.get_address().await.as_ref() { + if owner.as_ref() == self.dkg_client.get_address().await?.as_ref() { votes.insert(*proposal_id, true); continue; } @@ -313,7 +313,7 @@ mod tests { exchange_dealings(&mut controllers, false).await; derive_keypairs(&mut controllers, false).await; - let first_dealer = controllers[0].dkg_client.get_address().await; + let first_dealer = controllers[0].dkg_client.get_address().await?; { let mut guard = chain.lock().unwrap(); @@ -365,8 +365,8 @@ mod tests { exchange_dealings(&mut controllers, false).await; derive_keypairs(&mut controllers, false).await; - let first_dealer = controllers[0].dkg_client.get_address().await; - let second_dealer = controllers[1].dkg_client.get_address().await; + let first_dealer = controllers[0].dkg_client.get_address().await?; + let second_dealer = controllers[1].dkg_client.get_address().await?; { let mut guard = chain.lock().unwrap(); diff --git a/nym-api/src/ecash/error.rs b/nym-api/src/ecash/error.rs index 7696234ea2..68fd79622f 100644 --- a/nym-api/src/ecash/error.rs +++ b/nym-api/src/ecash/error.rs @@ -25,6 +25,9 @@ pub enum EcashError { #[error(transparent)] IOError(#[from] std::io::Error), + #[error("this instance is running without on-chain signing capabilities so no transactions can be sent")] + ChainSignerNotEnabled, + #[error("this operation couldn't be completed as this nym-api is not an active ecash signer")] NotASigner, diff --git a/nym-api/src/ecash/state/mod.rs b/nym-api/src/ecash/state/mod.rs index b27280b6a6..f262177480 100644 --- a/nym-api/src/ecash/state/mod.rs +++ b/nym-api/src/ecash/state/mod.rs @@ -139,7 +139,9 @@ impl EcashState { .local .active_signer .get_or_init(epoch_id, || async { - let address = self.aux.client.address().await; + let Ok(address) = self.aux.client.address().await else { + return Ok(false); + }; let ecash_signers = self.aux.comm_channel.ecash_clients(epoch_id).await?; // check if any ecash signers for this epoch has the same cosmos address as this api @@ -246,7 +248,7 @@ impl EcashState { let threshold = self.aux.comm_channel.ecash_threshold(epoch_id).await?; // let mut shares = Mutex::new(Vec::with_capacity(all_apis.len())); - let cosmos_address = self.aux.client.address().await; + let cosmos_address = self.aux.client.address().await.ok(); let get_partial_signatures = |api: EcashApiClient| async { // move the api into the closure @@ -256,7 +258,7 @@ impl EcashState { // check if we're attempting to query ourselves, in that case just get local signature // rather than making the http query - let partial = if api.cosmos_address == cosmos_address { + let partial = if Some(api.cosmos_address) == cosmos_address { self.partial_coin_index_signatures(Some(epoch_id)) .await? .signatures @@ -380,7 +382,7 @@ impl EcashState { let all_apis = self.aux.comm_channel.ecash_clients(epoch_id).await?; let threshold = self.aux.comm_channel.ecash_threshold(epoch_id).await?; - let cosmos_address = self.aux.client.address().await; + let cosmos_address = self.aux.client.address().await.ok(); let get_partial_signatures = |api: EcashApiClient| async { // move the api into the closure @@ -390,7 +392,7 @@ impl EcashState { // check if we're attempting to query ourselves, in that case just get local signature // rather than making the http query - let partial = if api.cosmos_address == cosmos_address { + let partial = if Some(api.cosmos_address) == cosmos_address { self.partial_expiration_date_signatures(expiration_date) .await? .signatures diff --git a/nym-api/src/ecash/tests/fixtures.rs b/nym-api/src/ecash/tests/fixtures.rs index 80ee791770..b49b9fc17e 100644 --- a/nym-api/src/ecash/tests/fixtures.rs +++ b/nym-api/src/ecash/tests/fixtures.rs @@ -263,7 +263,7 @@ pub(crate) struct TestingDkgController { impl TestingDkgController { pub async fn address(&self) -> AccountId { - self.dkg_client.get_address().await + self.dkg_client.get_address().await.unwrap() } pub async fn cw_address(&self) -> Addr { diff --git a/nym-api/src/ecash/tests/helpers.rs b/nym-api/src/ecash/tests/helpers.rs index 5cd410056f..7f7e4aaf54 100644 --- a/nym-api/src/ecash/tests/helpers.rs +++ b/nym-api/src/ecash/tests/helpers.rs @@ -51,7 +51,7 @@ pub(crate) async fn initialise_dkg(controllers: &mut [TestingDkgController], res // add every dealer to group contract for controller in controllers.iter() { - let address = controller.dkg_client.get_address().await; + let address = controller.dkg_client.get_address().await.unwrap(); let mut chain = controllers[0].chain_state.lock().unwrap(); chain.add_member(address.as_ref(), 10); } diff --git a/nym-api/src/ecash/tests/mod.rs b/nym-api/src/ecash/tests/mod.rs index 2b0ef471f9..9af4c78052 100644 --- a/nym-api/src/ecash/tests/mod.rs +++ b/nym-api/src/ecash/tests/mod.rs @@ -11,6 +11,7 @@ use crate::node_describe_cache::DescribedNodes; use crate::node_status_api::handlers::unstable; use crate::node_status_api::NodeStatusCache; use crate::nym_contract_cache::cache::NymContractCache; +use crate::status::ApiStatusState; use crate::support::caching::cache::SharedCache; use crate::support::config; use crate::support::http::state::{AppState, ForcedRefresh}; @@ -524,8 +525,8 @@ impl DummyClient { #[async_trait] impl super::client::Client for DummyClient { - async fn address(&self) -> AccountId { - self.validator_address.clone() + async fn address(&self) -> Result { + Ok(self.validator_address.clone()) } async fn dkg_contract_address(&self) -> Result { @@ -1262,7 +1263,7 @@ struct TestFixture { } impl TestFixture { - fn build_app_state(storage: NymApiStorage) -> AppState { + fn build_app_state(storage: NymApiStorage, ecash_state: EcashState) -> AppState { AppState { forced_refresh: ForcedRefresh::new(true), nym_contract_cache: NymContractCache::new(), @@ -1275,6 +1276,8 @@ impl TestFixture { NymNetworkDetails::new_empty(), ), node_info_cache: unstable::NodeInfoCache::default(), + api_status: ApiStatusState::new(None), + ecash_state: Arc::new(ecash_state), } } @@ -1337,8 +1340,8 @@ impl TestFixture { TestFixture { axum: TestServer::new( Router::new() - .nest("/v1/ecash", ecash_routes(Arc::new(ecash_state))) - .with_state(Self::build_app_state(storage.clone())), + .nest("/v1/ecash", ecash_routes()) + .with_state(Self::build_app_state(storage.clone(), ecash_state)), ) .unwrap(), storage, diff --git a/nym-api/src/epoch_operations/error.rs b/nym-api/src/epoch_operations/error.rs index 65fc822dff..a608817425 100644 --- a/nym-api/src/epoch_operations/error.rs +++ b/nym-api/src/epoch_operations/error.rs @@ -11,6 +11,9 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum RewardingError { + #[error("this instance is running without on-chain signing capabilities so no transactions can be sent")] + ChainSignerNotEnabled, + #[error("Our account ({our_address}) is not permitted to update rewarded set and perform rewarding. The allowed address is {allowed_address}")] Unauthorised { our_address: AccountId, diff --git a/nym-api/src/epoch_operations/mod.rs b/nym-api/src/epoch_operations/mod.rs index 6744679411..fe4fd5792d 100644 --- a/nym-api/src/epoch_operations/mod.rs +++ b/nym-api/src/epoch_operations/mod.rs @@ -134,9 +134,12 @@ impl EpochAdvancer { let epoch_status = self.nyxd_client.get_current_epoch_status().await?; if !epoch_status.is_in_progress() { - if epoch_status.being_advanced_by.as_str() - != self.nyxd_client.client_address().await.as_ref() - { + // SAFETY: before `EpochAdvancer` is started, `ensure_rewarding_permission` is called + // which is not allowed to progress if this instance is not using a signing client + #[allow(clippy::unwrap_used)] + let address = self.nyxd_client.client_address().await.unwrap(); + + if epoch_status.being_advanced_by.as_str() != address.as_ref() { // another nym-api is already handling error!("another nym-api ({}) is already advancing the epoch... but we shouldn't have other nym-apis yet!", epoch_status.being_advanced_by); return Ok(()); @@ -318,8 +321,10 @@ impl EpochAdvancer { pub(crate) async fn ensure_rewarding_permission( nyxd_client: &Client, ) -> Result<(), RewardingError> { + let Some(our_address) = nyxd_client.client_address().await else { + return Err(RewardingError::ChainSignerNotEnabled); + }; let allowed_address = nyxd_client.get_rewarding_validator_address().await?; - let our_address = nyxd_client.client_address().await; if allowed_address != our_address { Err(RewardingError::Unauthorised { our_address, diff --git a/nym-api/src/status/handlers.rs b/nym-api/src/status/handlers.rs index 7dc316aac2..8b177cadd6 100644 --- a/nym-api/src/status/handlers.rs +++ b/nym-api/src/status/handlers.rs @@ -4,37 +4,20 @@ use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; use crate::status::ApiStatusState; use crate::support::http::state::AppState; +use axum::extract::State; use axum::Json; use axum::Router; use nym_api_requests::models::{ApiHealthResponse, SignerInformationResponse}; use nym_bin_common::build_information::BinaryBuildInformationOwned; use nym_compact_ecash::Base58; -use std::sync::Arc; pub(crate) fn api_status_routes() -> Router { - let api_status_state = Arc::new(ApiStatusState::new()); - Router::new() - .route( - "/health", - axum::routing::get({ - let state = Arc::clone(&api_status_state); - || health(state) - }), - ) - .route( - "/build-information", - axum::routing::get({ - let state = Arc::clone(&api_status_state); - || build_information(state) - }), - ) + .route("/health", axum::routing::get(health)) + .route("/build-information", axum::routing::get(build_information)) .route( "/signer-information", - axum::routing::get({ - let state = Arc::clone(&api_status_state); - || signer_information(state) - }), + axum::routing::get(signer_information), ) } @@ -46,7 +29,7 @@ pub(crate) fn api_status_routes() -> Router { (status = 200, body = ApiHealthResponse) ) )] -async fn health(state: Arc) -> Json { +async fn health(State(state): State) -> Json { let uptime = state.startup_time.elapsed(); let health = ApiHealthResponse::new_healthy(uptime); Json(health) @@ -60,7 +43,9 @@ async fn health(state: Arc) -> Json { (status = 200, body = BinaryBuildInformationOwned) ) )] -async fn build_information(state: Arc) -> Json { +async fn build_information( + State(state): State, +) -> Json { Json(state.build_information.to_owned()) } @@ -73,7 +58,7 @@ async fn build_information(state: Arc) -> Json, + State(state): State, ) -> AxumResult> { let signer_state = state.signer_information.as_ref().ok_or_else(|| { AxumErrorResponse::internal_msg("this api does not expose zk-nym signing functionalities") diff --git a/nym-api/src/status/mod.rs b/nym-api/src/status/mod.rs index 0ed94a1819..f7ff611d6d 100644 --- a/nym-api/src/status/mod.rs +++ b/nym-api/src/status/mod.rs @@ -4,12 +4,25 @@ use crate::ecash; use nym_bin_common::bin_info; use nym_bin_common::build_information::BinaryBuildInformation; - +use std::ops::Deref; +use std::sync::Arc; use tokio::time::Instant; pub(crate) mod handlers; +#[derive(Clone)] pub(crate) struct ApiStatusState { + inner: Arc, +} + +impl Deref for ApiStatusState { + type Target = ApiStatusStateInner; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +pub(crate) struct ApiStatusStateInner { startup_time: Instant, build_information: BinaryBuildInformation, signer_information: Option, @@ -27,15 +40,13 @@ pub(crate) struct SignerState { } impl ApiStatusState { - pub fn new() -> Self { + pub fn new(signer_information: Option) -> Self { ApiStatusState { - startup_time: Instant::now(), - build_information: bin_info!(), - signer_information: None, + inner: Arc::new(ApiStatusStateInner { + startup_time: Instant::now(), + build_information: bin_info!(), + signer_information, + }), } } - - pub fn add_zk_nym_signer(&mut self, signer_information: SignerState) { - self.signer_information = Some(signer_information) - } } diff --git a/nym-api/src/support/cli/run.rs b/nym-api/src/support/cli/run.rs index e7bf4c0776..6436f19be1 100644 --- a/nym-api/src/support/cli/run.rs +++ b/nym-api/src/support/cli/run.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::circulating_supply_api::cache::CirculatingSupplyCache; -use crate::ecash::api_routes::handlers::ecash_routes; use crate::ecash::client::Client; use crate::ecash::comm::QueryCommunicationChannel; use crate::ecash::dkg::controller::keys::{ @@ -138,8 +137,6 @@ async fn start_nym_api_tasks_axum(config: &Config) -> anyhow::Result::new(); let node_info_cache = unstable::NodeInfoCache::default(); - let mut status_state = ApiStatusState::new(); - let ecash_contract = nyxd_client .get_ecash_contract_address() .await @@ -161,8 +158,8 @@ async fn start_nym_api_tasks_axum(config: &Config) -> anyhow::Result anyhow::Result anyhow::Result) -> Self { Self { unfinished_router: self.unfinished_router.nest(path, router), diff --git a/nym-api/src/support/http/state.rs b/nym-api/src/support/http/state.rs index f45d25bbd2..6c277441ea 100644 --- a/nym-api/src/support/http/state.rs +++ b/nym-api/src/support/http/state.rs @@ -2,15 +2,18 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::circulating_supply_api::cache::CirculatingSupplyCache; +use crate::ecash::state::EcashState; use crate::network::models::NetworkDetails; use crate::node_describe_cache::DescribedNodes; use crate::node_status_api::handlers::unstable; use crate::node_status_api::models::AxumErrorResponse; use crate::node_status_api::NodeStatusCache; use crate::nym_contract_cache::cache::{CachedRewardedSet, NymContractCache}; +use crate::status::ApiStatusState; use crate::support::caching::cache::SharedCache; use crate::support::caching::Cache; use crate::support::storage; +use axum::extract::FromRef; use nym_api_requests::models::{GatewayBondAnnotated, MixNodeBondAnnotated, NodeAnnotation}; use nym_mixnet_contract_common::NodeId; use nym_task::TaskManager; @@ -80,6 +83,21 @@ pub(crate) struct AppState { pub(crate) described_nodes_cache: SharedCache, pub(crate) network_details: NetworkDetails, pub(crate) node_info_cache: unstable::NodeInfoCache, + pub(crate) api_status: ApiStatusState, + // todo: refactor it into inner: Arc + pub(crate) ecash_state: Arc, +} + +impl FromRef for ApiStatusState { + fn from_ref(app_state: &AppState) -> Self { + app_state.api_status.clone() + } +} + +impl FromRef for Arc { + fn from_ref(app_state: &AppState) -> Self { + app_state.ecash_state.clone() + } } #[derive(Clone)] diff --git a/nym-api/src/support/nyxd/mod.rs b/nym-api/src/support/nyxd/mod.rs index 012f9d369d..5e129058b9 100644 --- a/nym-api/src/support/nyxd/mod.rs +++ b/nym-api/src/support/nyxd/mod.rs @@ -77,16 +77,6 @@ macro_rules! nyxd_query { }}; } -macro_rules! nyxd_signing_shared { - ($self:expr, $($op:tt)*) => {{ - let guard = $self.inner.read().await; - match &*guard { - $crate::support::nyxd::ClientInner::Signing(client) => client.$($op)*, - $crate::support::nyxd::ClientInner::Query(_) => panic!("attempted to use a signing method on a query client"), - } - }}; -} - macro_rules! nyxd_signing { ($self:expr, $($op:tt)*) => {{ let guard = $self.inner.write().await; @@ -140,13 +130,19 @@ impl Client { self.inner.read().await } - pub(crate) async fn client_address(&self) -> AccountId { - nyxd_signing_shared!(self, address()) + pub(crate) async fn client_address(&self) -> Option { + let guard = self.inner.read().await; + match &*guard { + ClientInner::Signing(client) => Some(client.address()), + ClientInner::Query(_) => None, + } } pub(crate) async fn balance>(&self, denom: S) -> Result { - let address = self.client_address().await; let denom = denom.into(); + let Some(address) = self.client_address().await else { + return Ok(Coin::new(0, denom)); + }; let balance = nyxd_query!(self, get_balance(&address, denom.clone()).await?); match balance { @@ -394,8 +390,10 @@ impl Client { #[async_trait] impl crate::ecash::client::Client for Client { - async fn address(&self) -> AccountId { - self.client_address().await + async fn address(&self) -> Result { + self.client_address() + .await + .ok_or(EcashError::ChainSignerNotEnabled) } async fn dkg_contract_address(&self) -> Result { @@ -481,7 +479,7 @@ impl crate::ecash::client::Client for Client { async fn get_self_registered_dealer_details( &self, ) -> crate::ecash::error::Result { - let self_address = &self.address().await; + let self_address = &self.address().await?; Ok(nyxd_query!(self, get_dealer_details(self_address).await?)) } From fa72f90bfab31c699ea6a7e0ad12fbe2a22c2c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 25 Nov 2024 16:44:23 +0000 Subject: [PATCH 02/11] Remove peers with no allowed ip from storage --- gateway/src/node/mod.rs | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index c399deefa9..48e7975018 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -231,22 +231,28 @@ impl Gateway { forwarding_channel, router_tx, ); - let all_peers = self.client_storage.get_all_wireguard_peers().await?; - let used_private_network_ips = all_peers - .iter() - .cloned() - .map(|wireguard_peer| { - defguard_wireguard_rs::host::Peer::try_from(wireguard_peer).map(|mut peer| { - peer.allowed_ips - .pop() - .ok_or(Box::new(GatewayError::InternalWireguardError(format!( - "no private IP set for peer {}", - peer.public_key - )))) - .map(|p| p.ip) - }) - }) - .collect::, _>, _>>()??; + let mut used_private_network_ips = vec![]; + let mut all_peers = vec![]; + for wireguard_peer in self + .client_storage + .get_all_wireguard_peers() + .await? + .into_iter() + { + let mut peer = defguard_wireguard_rs::host::Peer::try_from(wireguard_peer.clone())?; + let Some(peer) = peer.allowed_ips.pop() else { + tracing::warn!( + "Peer {} has empty allowed ips. It will be removed", + peer.public_key + ); + self.client_storage + .remove_wireguard_peer(&peer.public_key.to_string()) + .await?; + continue; + }; + used_private_network_ips.push(peer.ip); + all_peers.push(wireguard_peer); + } if let Some(wireguard_data) = self.wireguard_data.take() { let (on_start_tx, on_start_rx) = oneshot::channel(); From dcde4c8df1e7017d4dd84240115a56a4d7d0dd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 25 Nov 2024 17:54:32 +0000 Subject: [PATCH 03/11] bugfix: use default value for verloc config when deserialising missing values (#5177) --- nym-node/src/config/mixnode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-node/src/config/mixnode.rs b/nym-node/src/config/mixnode.rs index 92f9279c2f..a62ee4b075 100644 --- a/nym-node/src/config/mixnode.rs +++ b/nym-node/src/config/mixnode.rs @@ -36,7 +36,7 @@ impl MixnodeConfig { } #[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] -#[serde(deny_unknown_fields)] +#[serde(deny_unknown_fields, default)] pub struct Verloc { /// Socket address this node will use for binding its verloc API. /// default: `0.0.0.0:1790` From 2a60b2f057539a081b303dea97a7e5feb4253e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 26 Nov 2024 09:41:18 +0000 Subject: [PATCH 04/11] bugfix: fixed nym-node config migrations (again) (#5179) --- nym-node/src/config/old_configs/old_config_v1.rs | 6 ++++-- nym-node/src/config/old_configs/old_config_v2.rs | 6 ++++-- nym-node/src/config/old_configs/old_config_v3.rs | 6 ++++-- nym-node/src/config/old_configs/old_config_v4.rs | 10 ++++++---- nym-node/src/config/old_configs/old_config_v5.rs | 10 ++++++---- nym-node/src/config/upgrade_helpers.rs | 6 +++++- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/nym-node/src/config/old_configs/old_config_v1.rs b/nym-node/src/config/old_configs/old_config_v1.rs index a09eee36e7..c67f9358ae 100644 --- a/nym-node/src/config/old_configs/old_config_v1.rs +++ b/nym-node/src/config/old_configs/old_config_v1.rs @@ -11,6 +11,7 @@ use nym_pemstore::store_keypair; use old_configs::old_config_v2::*; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; +use tracing::instrument; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] @@ -756,15 +757,16 @@ fn initialise(config: &WireguardV2) -> std::io::Result<()> { Ok(()) } +#[instrument(skip_all)] pub async fn try_upgrade_config_v1>( path: P, prev_config: Option, ) -> Result { - tracing::debug!("Updating from 1.1.2"); + debug!("attempting to load v1 config..."); let old_cfg = if let Some(prev_config) = prev_config { prev_config } else { - ConfigV1::read_from_path(&path)? + ConfigV1::read_from_path(&path).inspect_err(|err| debug!("failed: {err}"))? }; let wireguard = WireguardV2 { enabled: old_cfg.wireguard.enabled, diff --git a/nym-node/src/config/old_configs/old_config_v2.rs b/nym-node/src/config/old_configs/old_config_v2.rs index 28e35e66bc..2082ed4f70 100644 --- a/nym-node/src/config/old_configs/old_config_v2.rs +++ b/nym-node/src/config/old_configs/old_config_v2.rs @@ -16,6 +16,7 @@ use nym_sphinx_acknowledgements::AckKey; use old_configs::old_config_v3::*; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; +use tracing::instrument; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] @@ -786,15 +787,16 @@ pub async fn initialise( Ok(()) } +#[instrument(skip_all)] pub async fn try_upgrade_config_v2>( path: P, prev_config: Option, ) -> Result { - tracing::debug!("Updating from 1.1.3"); + debug!("attempting to load v2 config..."); let old_cfg = if let Some(prev_config) = prev_config { prev_config } else { - ConfigV2::read_from_path(&path)? + ConfigV2::read_from_path(&path).inspect_err(|err| debug!("failed: {err}"))? }; let authenticator_paths = AuthenticatorPathsV3::new( diff --git a/nym-node/src/config/old_configs/old_config_v3.rs b/nym-node/src/config/old_configs/old_config_v3.rs index 01ce8a9e49..1301230167 100644 --- a/nym-node/src/config/old_configs/old_config_v3.rs +++ b/nym-node/src/config/old_configs/old_config_v3.rs @@ -17,6 +17,7 @@ use old_configs::old_config_v4::*; use persistence::*; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; +use tracing::instrument; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] @@ -938,15 +939,16 @@ pub async fn initialise( Ok(()) } +#[instrument(skip_all)] pub async fn try_upgrade_config_v3>( path: P, prev_config: Option, ) -> Result { - tracing::debug!("Updating from 1.1.4"); + debug!("attempting to load v3 config..."); let old_cfg = if let Some(prev_config) = prev_config { prev_config } else { - ConfigV3::read_from_path(&path)? + ConfigV3::read_from_path(&path).inspect_err(|err| debug!("failed: {err}"))? }; let exit_gateway_paths = ExitGatewayPaths::new( diff --git a/nym-node/src/config/old_configs/old_config_v4.rs b/nym-node/src/config/old_configs/old_config_v4.rs index 8e8e3758d0..03a32b2b39 100644 --- a/nym-node/src/config/old_configs/old_config_v4.rs +++ b/nym-node/src/config/old_configs/old_config_v4.rs @@ -20,6 +20,7 @@ use old_configs::old_config_v5::*; use persistence::*; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; +use tracing::instrument; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] @@ -203,7 +204,7 @@ pub struct MixnetV4 { /// If applicable, custom port announced in the self-described API that other clients and nodes /// will use. /// Useful when the node is behind a proxy. - #[serde(deserialize_with = "de_maybe_port")] + #[serde(deserialize_with = "de_maybe_port", default)] pub announce_port: Option, /// Addresses to nym APIs from which the node gets the view of the network. @@ -385,7 +386,7 @@ pub struct VerlocV4 { /// default: `0.0.0.0:1790` pub bind_address: SocketAddr, - #[serde(deserialize_with = "de_maybe_port")] + #[serde(deserialize_with = "de_maybe_port", default)] pub announce_port: Option, #[serde(default)] @@ -1060,15 +1061,16 @@ pub async fn initialise( Ok(()) } +#[instrument(skip_all)] pub async fn try_upgrade_config_v4>( path: P, prev_config: Option, ) -> Result { - tracing::debug!("Updating from 1.1.5"); + debug!("attempting to load v4 config..."); let old_cfg = if let Some(prev_config) = prev_config { prev_config } else { - ConfigV4::read_from_path(&path)? + ConfigV4::read_from_path(&path).inspect_err(|err| debug!("failed: {err}"))? }; let exit_gateway_paths = ExitGatewayPaths::new( diff --git a/nym-node/src/config/old_configs/old_config_v5.rs b/nym-node/src/config/old_configs/old_config_v5.rs index 936882f113..4a1cb57c64 100644 --- a/nym-node/src/config/old_configs/old_config_v5.rs +++ b/nym-node/src/config/old_configs/old_config_v5.rs @@ -25,6 +25,7 @@ use nym_sphinx_acknowledgements::AckKey; use persistence::*; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; +use tracing::instrument; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] @@ -208,7 +209,7 @@ pub struct MixnetV5 { /// If applicable, custom port announced in the self-described API that other clients and nodes /// will use. /// Useful when the node is behind a proxy. - #[serde(deserialize_with = "de_maybe_port")] + #[serde(deserialize_with = "de_maybe_port", default)] pub announce_port: Option, /// Addresses to nym APIs from which the node gets the view of the network. @@ -390,7 +391,7 @@ pub struct VerlocV5 { /// default: `0.0.0.0:1790` pub bind_address: SocketAddr, - #[serde(deserialize_with = "de_maybe_port")] + #[serde(deserialize_with = "de_maybe_port", default)] pub announce_port: Option, #[serde(default)] @@ -1069,15 +1070,16 @@ pub async fn initialise( Ok(()) } +#[instrument(skip_all)] pub async fn try_upgrade_config_v5>( path: P, prev_config: Option, ) -> Result { - tracing::debug!("Updating from 1.1.6"); + debug!("attempting to load v5 config..."); let old_cfg = if let Some(prev_config) = prev_config { prev_config } else { - ConfigV5::read_from_path(&path)? + ConfigV5::read_from_path(&path).inspect_err(|err| debug!("failed: {err}"))? }; let (private_ipv4, private_ipv6) = match old_cfg.wireguard.private_ip { diff --git a/nym-node/src/config/upgrade_helpers.rs b/nym-node/src/config/upgrade_helpers.rs index bae75192ec..c7596b69a6 100644 --- a/nym-node/src/config/upgrade_helpers.rs +++ b/nym-node/src/config/upgrade_helpers.rs @@ -5,6 +5,7 @@ use crate::config::old_configs::*; use crate::config::Config; use crate::error::NymNodeError; use std::path::Path; +use tracing::debug; // currently there are no upgrades async fn try_upgrade_config(path: &Path) -> Result<(), NymNodeError> { @@ -24,7 +25,10 @@ async fn try_upgrade_config(path: &Path) -> Result<(), NymNodeError> { pub async fn try_load_current_config>( config_path: P, ) -> Result { - if let Ok(cfg) = Config::read_from_toml_file(config_path.as_ref()) { + if let Ok(cfg) = Config::read_from_toml_file(config_path.as_ref()) + .inspect_err(|err| debug!("didn't manage to load the current config: {err}")) + { + debug!("managed to load the current version of the config"); return Ok(cfg); } From 35aa7e338da5f32d05ca5a479428a751463fbf5a Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Tue, 26 Nov 2024 15:01:06 +0100 Subject: [PATCH 05/11] bump binary versions --- Cargo.lock | 16 ++++++++-------- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-node/Cargo.toml | 2 +- service-providers/network-requester/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- tools/nymvisor/Cargo.toml | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d004324f62..b2eae3a227 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2428,7 +2428,7 @@ dependencies = [ [[package]] name = "explorer-api" -version = "1.1.42" +version = "1.1.43" dependencies = [ "chrono", "clap 4.5.20", @@ -4451,7 +4451,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nym-api" -version = "1.1.46" +version = "1.1.47" dependencies = [ "anyhow", "async-trait", @@ -4701,7 +4701,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.44" +version = "1.1.45" dependencies = [ "anyhow", "base64 0.22.1", @@ -4782,7 +4782,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.44" +version = "1.1.45" dependencies = [ "bs58", "clap 4.5.20", @@ -5899,7 +5899,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.45" +version = "1.1.46" dependencies = [ "addr", "anyhow", @@ -5950,7 +5950,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.1.11" +version = "1.1.12" dependencies = [ "anyhow", "bip39", @@ -6306,7 +6306,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.44" +version = "1.1.45" dependencies = [ "bs58", "clap 4.5.20", @@ -6908,7 +6908,7 @@ dependencies = [ [[package]] name = "nymvisor" -version = "0.1.9" +version = "0.1.10" dependencies = [ "anyhow", "bytes", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index c5679d02de..03eb55186e 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.44" +version = "1.1.45" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index f5d3cd8967..4363c56387 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.44" +version = "1.1.45" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 11f8672f98..6fe9830dae 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.42" +version = "1.1.43" edition = "2021" license.workspace = true diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index ea2e3ed212..27814af1db 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-api" license = "GPL-3.0" -version = "1.1.46" +version = "1.1.47" authors.workspace = true edition = "2021" rust-version.workspace = true diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 16f66a6fee..92dec65fea 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node" -version = "1.1.11" +version = "1.1.12" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index a419abd4f6..1508c7d775 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-network-requester" license = "GPL-3.0" -version = "1.1.45" +version = "1.1.46" authors.workspace = true edition.workspace = true rust-version = "1.70" diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index 2a4bdf0186..c156e28679 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.44" +version = "1.1.45" authors.workspace = true edition = "2021" license.workspace = true diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index a1f0590c8d..d44e9fc12b 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nymvisor" -version = "0.1.9" +version = "0.1.10" authors.workspace = true repository.workspace = true homepage.workspace = true From 8e713d43e1bf3d9de86f0986af2677ffc3b7882d Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Wed, 27 Nov 2024 11:07:39 +0100 Subject: [PATCH 06/11] Add monitor_run and testing_route indexes (#5182) --- .../migrations/20241127110000_add_monitor_run_indexes.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 nym-api/migrations/20241127110000_add_monitor_run_indexes.sql diff --git a/nym-api/migrations/20241127110000_add_monitor_run_indexes.sql b/nym-api/migrations/20241127110000_add_monitor_run_indexes.sql new file mode 100644 index 0000000000..f639bbba7a --- /dev/null +++ b/nym-api/migrations/20241127110000_add_monitor_run_indexes.sql @@ -0,0 +1,8 @@ +/* + * Copyright 2024 - Nym Technologies SA + * SPDX-License-Identifier: Apache-2.0 + */ + +CREATE INDEX IF NOT EXISTS monitor_run_id on monitor_run(id); +CREATE INDEX IF NOT EXISTS monitor_run_timestamp on monitor_run(timestamp); +CREATE INDEX IF NOT EXISTS testing_route_monitor_run_id on testing_route(monitor_run_id); \ No newline at end of file From 56206433e649395e9000de3516ac81a7ea7877c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 29 Nov 2024 09:20:45 +0000 Subject: [PATCH 07/11] chore: apply 1.84 linter suggestions (#5192) --- .../src/client/topology_control/accessor.rs | 2 +- .../client-libs/validator-client/src/nyxd/coin.rs | 2 +- .../validator-client/src/nyxd/fee/gas_price.rs | 2 +- .../mixnet-contract/src/interval.rs | 2 +- common/dkg/src/bte/proof_chunking.rs | 3 +-- common/dkg/src/interpolation/polynomial.rs | 6 +++--- .../src/registration/handshake/mod.rs | 2 +- .../src/scheme/coin_indices_signatures.rs | 12 ------------ .../nym_offline_compact_ecash/src/scheme/keygen.rs | 2 +- common/nym_offline_compact_ecash/src/scheme/mod.rs | 2 +- common/nymcoconut/src/elgamal.rs | 4 ++-- common/nymcoconut/src/scheme/keygen.rs | 2 +- common/nymsphinx/addressing/src/clients.rs | 2 +- common/nymsphinx/addressing/src/nodes.rs | 13 ++++++------- .../nymsphinx/anonymous-replies/src/reply_surb.rs | 2 +- common/socks5/requests/src/request.rs | 10 ---------- explorer-api/src/geo_ip/location.rs | 2 +- explorer-api/src/guards/location.rs | 2 +- nym-api/nym-api-requests/src/helpers.rs | 2 +- nym-api/src/ecash/tests/helpers.rs | 2 +- .../monitor/gateway_clients_cache.rs | 2 +- .../nym-credential-proxy/src/http/state/mod.rs | 2 +- sdk/ffi/go/src/lib.rs | 3 +++ .../dkg-bypass-contract/src/contract.rs | 4 ++-- .../testnet-manager/src/manager/dkg_skip.rs | 6 +++--- .../testnet-manager/src/manager/local_apis.rs | 2 +- .../testnet-manager/src/manager/local_client.rs | 2 +- .../testnet-manager/src/manager/local_nodes.rs | 2 +- 28 files changed, 39 insertions(+), 60 deletions(-) diff --git a/common/client-core/src/client/topology_control/accessor.rs b/common/client-core/src/client/topology_control/accessor.rs index fcb272c934..6b12d64562 100644 --- a/common/client-core/src/client/topology_control/accessor.rs +++ b/common/client-core/src/client/topology_control/accessor.rs @@ -38,7 +38,7 @@ pub struct TopologyReadPermit<'a> { permit: RwLockReadGuard<'a, Option>, } -impl<'a> Deref for TopologyReadPermit<'a> { +impl Deref for TopologyReadPermit<'_> { type Target = Option; fn deref(&self) -> &Self::Target { diff --git a/common/client-libs/validator-client/src/nyxd/coin.rs b/common/client-libs/validator-client/src/nyxd/coin.rs index 0fa175a243..8050273a51 100644 --- a/common/client-libs/validator-client/src/nyxd/coin.rs +++ b/common/client-libs/validator-client/src/nyxd/coin.rs @@ -32,7 +32,7 @@ impl Div for Coin { } } -impl<'a> Div for &'a Coin { +impl Div for &Coin { type Output = Gas; fn div(self, rhs: GasPrice) -> Self::Output { diff --git a/common/client-libs/validator-client/src/nyxd/fee/gas_price.rs b/common/client-libs/validator-client/src/nyxd/fee/gas_price.rs index 4f0f2fd0a8..3679cc7500 100644 --- a/common/client-libs/validator-client/src/nyxd/fee/gas_price.rs +++ b/common/client-libs/validator-client/src/nyxd/fee/gas_price.rs @@ -22,7 +22,7 @@ pub struct GasPrice { pub denom: String, } -impl<'a> Mul for &'a GasPrice { +impl Mul for &GasPrice { type Output = Coin; fn mul(self, gas_limit: Gas) -> Self::Output { diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs index e36935d66c..2259af4c7a 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs @@ -32,7 +32,7 @@ pub(crate) mod string_rfc3339_offset_date_time { struct Rfc3339OffsetDateTimeVisitor; - impl<'de> Visitor<'de> for Rfc3339OffsetDateTimeVisitor { + impl Visitor<'_> for Rfc3339OffsetDateTimeVisitor { type Value = OffsetDateTime; fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { diff --git a/common/dkg/src/bte/proof_chunking.rs b/common/dkg/src/bte/proof_chunking.rs index 6829a53660..1365aecbd7 100644 --- a/common/dkg/src/bte/proof_chunking.rs +++ b/common/dkg/src/bte/proof_chunking.rs @@ -26,9 +26,8 @@ const PARALLEL_RUNS: usize = 32; /// `lambda` ($\lambda$) in the DKG paper const SECURITY_PARAMETER: usize = 256; -// note: ceiling in integer division can be achieved via q = (x + y - 1) / y; /// ceil(SECURITY_PARAMETER / PARALLEL_RUNS) in the paper -const NUM_CHALLENGE_BITS: usize = (SECURITY_PARAMETER + PARALLEL_RUNS - 1) / PARALLEL_RUNS; +const NUM_CHALLENGE_BITS: usize = SECURITY_PARAMETER.div_ceil(PARALLEL_RUNS); // type alias for ease of use type FirstChallenge = Vec>>; diff --git a/common/dkg/src/interpolation/polynomial.rs b/common/dkg/src/interpolation/polynomial.rs index 33c7486a99..671b8e6832 100644 --- a/common/dkg/src/interpolation/polynomial.rs +++ b/common/dkg/src/interpolation/polynomial.rs @@ -196,7 +196,7 @@ impl<'b> Add<&'b Polynomial> for Polynomial { } } -impl<'a> Add for &'a Polynomial { +impl Add for &Polynomial { type Output = Polynomial; fn add(self, rhs: Polynomial) -> Polynomial { @@ -212,10 +212,10 @@ impl Add for Polynomial { } } -impl<'a, 'b> Add<&'b Polynomial> for &'a Polynomial { +impl<'a> Add<&'a Polynomial> for &Polynomial { type Output = Polynomial; - fn add(self, rhs: &'b Polynomial) -> Self::Output { + fn add(self, rhs: &'a Polynomial) -> Self::Output { let len = self.coefficients.len(); let rhs_len = rhs.coefficients.len(); diff --git a/common/gateway-requests/src/registration/handshake/mod.rs b/common/gateway-requests/src/registration/handshake/mod.rs index e5dc1dc59f..4a6f44b7d7 100644 --- a/common/gateway-requests/src/registration/handshake/mod.rs +++ b/common/gateway-requests/src/registration/handshake/mod.rs @@ -37,7 +37,7 @@ pub struct GatewayHandshake<'a> { handshake_future: BoxFuture<'a, Result>, } -impl<'a> Future for GatewayHandshake<'a> { +impl Future for GatewayHandshake<'_> { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { diff --git a/common/nym_offline_compact_ecash/src/scheme/coin_indices_signatures.rs b/common/nym_offline_compact_ecash/src/scheme/coin_indices_signatures.rs index b08ab368dc..30c7fe5523 100644 --- a/common/nym_offline_compact_ecash/src/scheme/coin_indices_signatures.rs +++ b/common/nym_offline_compact_ecash/src/scheme/coin_indices_signatures.rs @@ -324,18 +324,6 @@ pub fn unchecked_aggregate_indices_signatures( _aggregate_indices_signatures(params, vk, signatures_shares, false) } -/// Generates parameters for the scheme setup. -/// -/// # Arguments -/// -/// * `total_coins` - it is the number of coins in a freshly generated wallet. It is the public parameter of the scheme. -/// -/// # Returns -/// -/// A `Parameters` struct containing group parameters, public key, the number of signatures (`total_coins`), -/// and a map of signatures for each index `l`. -/// - #[cfg(test)] mod tests { use super::*; diff --git a/common/nym_offline_compact_ecash/src/scheme/keygen.rs b/common/nym_offline_compact_ecash/src/scheme/keygen.rs index f5926d9cb6..406b368be0 100644 --- a/common/nym_offline_compact_ecash/src/scheme/keygen.rs +++ b/common/nym_offline_compact_ecash/src/scheme/keygen.rs @@ -264,7 +264,7 @@ impl<'b> Add<&'b VerificationKeyAuth> for VerificationKeyAuth { } } -impl<'a> Mul for &'a VerificationKeyAuth { +impl Mul for &VerificationKeyAuth { type Output = VerificationKeyAuth; #[inline] diff --git a/common/nym_offline_compact_ecash/src/scheme/mod.rs b/common/nym_offline_compact_ecash/src/scheme/mod.rs index 8912bf91eb..7f9687a380 100644 --- a/common/nym_offline_compact_ecash/src/scheme/mod.rs +++ b/common/nym_offline_compact_ecash/src/scheme/mod.rs @@ -984,7 +984,7 @@ pub struct SerialNumberRef<'a> { pub(crate) inner: &'a [G1Projective], } -impl<'a> SerialNumberRef<'a> { +impl SerialNumberRef<'_> { pub fn to_bytes(&self) -> Vec { let ss_len = self.inner.len(); let mut bytes: Vec = Vec::with_capacity(ss_len * 48); diff --git a/common/nymcoconut/src/elgamal.rs b/common/nymcoconut/src/elgamal.rs index 55db7dcdd2..1b814f0bc5 100644 --- a/common/nymcoconut/src/elgamal.rs +++ b/common/nymcoconut/src/elgamal.rs @@ -206,10 +206,10 @@ impl Deref for PublicKey { } } -impl<'a, 'b> Mul<&'b Scalar> for &'a PublicKey { +impl<'a> Mul<&'a Scalar> for &PublicKey { type Output = G1Projective; - fn mul(self, rhs: &'b Scalar) -> Self::Output { + fn mul(self, rhs: &'a Scalar) -> Self::Output { self.0 * rhs } } diff --git a/common/nymcoconut/src/scheme/keygen.rs b/common/nymcoconut/src/scheme/keygen.rs index 85e057793d..f80c131143 100644 --- a/common/nymcoconut/src/scheme/keygen.rs +++ b/common/nymcoconut/src/scheme/keygen.rs @@ -305,7 +305,7 @@ impl<'b> Add<&'b VerificationKey> for VerificationKey { } } -impl<'a> Mul for &'a VerificationKey { +impl Mul for &VerificationKey { type Output = VerificationKey; #[inline] diff --git a/common/nymsphinx/addressing/src/clients.rs b/common/nymsphinx/addressing/src/clients.rs index a739e7369e..743302edbe 100644 --- a/common/nymsphinx/addressing/src/clients.rs +++ b/common/nymsphinx/addressing/src/clients.rs @@ -64,7 +64,7 @@ impl<'de> Deserialize<'de> for Recipient { { struct RecipientVisitor; - impl<'de> Visitor<'de> for RecipientVisitor { + impl Visitor<'_> for RecipientVisitor { type Value = Recipient; fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { diff --git a/common/nymsphinx/addressing/src/nodes.rs b/common/nymsphinx/addressing/src/nodes.rs index e0cd745ae9..0c1558c19c 100644 --- a/common/nymsphinx/addressing/src/nodes.rs +++ b/common/nymsphinx/addressing/src/nodes.rs @@ -1,6 +1,12 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +//! Encodoing and decoding node routing information. +//! +//! This module is responsible for encoding and decoding node routing information, so that +//! they could be later put into an appropriate field in a sphinx header. +//! Currently, that routing information is an IP address, but in principle it can be anything +//! for as long as it's going to fit in the field. use nym_crypto::asymmetric::identity; use nym_sphinx_types::{NodeAddressBytes, NODE_ADDRESS_LENGTH}; @@ -12,13 +18,6 @@ use thiserror::Error; pub type NodeIdentity = identity::PublicKey; pub const NODE_IDENTITY_SIZE: usize = identity::PUBLIC_KEY_LENGTH; -/// Encodoing and decoding node routing information. -/// -/// This module is responsible for encoding and decoding node routing information, so that -/// they could be later put into an appropriate field in a sphinx header. -/// Currently, that routing information is an IP address, but in principle it can be anything -/// for as long as it's going to fit in the field. - /// MAX_UNPADDED_LEN represents maximum length an unpadded address could have. /// In this case it's an ipv6 socket address (with version prefix) pub const MAX_NODE_ADDRESS_UNPADDED_LEN: usize = 19; diff --git a/common/nymsphinx/anonymous-replies/src/reply_surb.rs b/common/nymsphinx/anonymous-replies/src/reply_surb.rs index deac5f532d..f25871ba0b 100644 --- a/common/nymsphinx/anonymous-replies/src/reply_surb.rs +++ b/common/nymsphinx/anonymous-replies/src/reply_surb.rs @@ -56,7 +56,7 @@ impl<'de> Deserialize<'de> for ReplySurb { { struct ReplySurbVisitor; - impl<'de> Visitor<'de> for ReplySurbVisitor { + impl Visitor<'_> for ReplySurbVisitor { type Value = ReplySurb; fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { diff --git a/common/socks5/requests/src/request.rs b/common/socks5/requests/src/request.rs index 23e844db87..28a5182d00 100644 --- a/common/socks5/requests/src/request.rs +++ b/common/socks5/requests/src/request.rs @@ -253,25 +253,15 @@ impl Socks5RequestContent { /// Deserialize the request type, connection id, destination address and port, /// and the request body from bytes. /// - // TODO: this was already inaccurate - // /// Serialized bytes looks like this: - // /// - // /// -------------------------------------------------------------------------------------- - // /// request_flag | connection_id | address_length | remote_address_bytes | request_data | - // /// 1 | 8 | 2 | address_length | ... | - // /// -------------------------------------------------------------------------------------- - /// /// The request_flag tells us whether this is a new connection request (`new_connect`), /// an already-established connection we should send up (`new_send`), or /// a request to close an established connection (`new_close`). - // connect: // RequestFlag::Connect || CONN_ID || ADDR_LEN || ADDR || // // send: // RequestFlag::Send || CONN_ID || LOCAL_CLOSED || DATA // where DATA: SEQ || TRUE_DATA - pub fn try_from_bytes(b: &[u8]) -> Result { // each request needs to at least contain flag and ConnectionId if b.is_empty() { diff --git a/explorer-api/src/geo_ip/location.rs b/explorer-api/src/geo_ip/location.rs index 59bbb33ad7..263764943e 100644 --- a/explorer-api/src/geo_ip/location.rs +++ b/explorer-api/src/geo_ip/location.rs @@ -166,7 +166,7 @@ impl GeoIp { } } -impl<'a> TryFrom<&City<'a>> for Location { +impl TryFrom<&City<'_>> for Location { type Error = String; fn try_from(city: &City) -> Result { diff --git a/explorer-api/src/guards/location.rs b/explorer-api/src/guards/location.rs index 045b03f5b4..f5ce0b7ee2 100644 --- a/explorer-api/src/guards/location.rs +++ b/explorer-api/src/guards/location.rs @@ -65,7 +65,7 @@ impl<'r> FromRequest<'r> for Location { } } -impl<'a> OpenApiFromRequest<'a> for Location { +impl OpenApiFromRequest<'_> for Location { fn from_request_input( _gen: &mut OpenApiGenerator, _name: String, diff --git a/nym-api/nym-api-requests/src/helpers.rs b/nym-api/nym-api-requests/src/helpers.rs index 651030fc74..292ffb69f4 100644 --- a/nym-api/nym-api-requests/src/helpers.rs +++ b/nym-api/nym-api-requests/src/helpers.rs @@ -64,7 +64,7 @@ pub(crate) mod overengineered_offset_date_time_serde { ])), ]; - impl<'de> Visitor<'de> for OffsetDateTimeVisitor { + impl Visitor<'_> for OffsetDateTimeVisitor { type Value = OffsetDateTime; fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { diff --git a/nym-api/src/ecash/tests/helpers.rs b/nym-api/src/ecash/tests/helpers.rs index 7f7e4aaf54..458b57946e 100644 --- a/nym-api/src/ecash/tests/helpers.rs +++ b/nym-api/src/ecash/tests/helpers.rs @@ -76,7 +76,7 @@ pub(crate) async fn submit_public_keys(controllers: &mut [TestingDkgController], .unwrap(); } - let threshold = (2 * controllers.len() as u64 + 3 - 1) / 3; + let threshold = (2 * controllers.len() as u64).div_ceil(3); let mut guard = controllers[0].chain_state.lock().unwrap(); guard.dkg_contract.epoch.state = EpochState::DealingExchange { resharing }; diff --git a/nym-api/src/network_monitor/monitor/gateway_clients_cache.rs b/nym-api/src/network_monitor/monitor/gateway_clients_cache.rs index 4a321d57cd..c791f9a6af 100644 --- a/nym-api/src/network_monitor/monitor/gateway_clients_cache.rs +++ b/nym-api/src/network_monitor/monitor/gateway_clients_cache.rs @@ -59,7 +59,7 @@ impl GatewayClientHandle { } } -impl<'a> UnlockedGatewayClientHandle<'a> { +impl UnlockedGatewayClientHandle<'_> { pub(crate) fn get_mut_unchecked( &mut self, ) -> &mut GatewayClient { diff --git a/nym-credential-proxy/nym-credential-proxy/src/http/state/mod.rs b/nym-credential-proxy/nym-credential-proxy/src/http/state/mod.rs index c4c4a8ebe3..bcc62f9c7e 100644 --- a/nym-credential-proxy/nym-credential-proxy/src/http/state/mod.rs +++ b/nym-credential-proxy/nym-credential-proxy/src/http/state/mod.rs @@ -674,7 +674,7 @@ pub(crate) struct ChainWritePermit<'a> { inner: RwLockWriteGuard<'a, DirectSigningHttpRpcNyxdClient>, } -impl<'a> Deref for ChainWritePermit<'a> { +impl Deref for ChainWritePermit<'_> { type Target = DirectSigningHttpRpcNyxdClient; fn deref(&self) -> &Self::Target { diff --git a/sdk/ffi/go/src/lib.rs b/sdk/ffi/go/src/lib.rs index a5c930a2ec..a0a690c691 100644 --- a/sdk/ffi/go/src/lib.rs +++ b/sdk/ffi/go/src/lib.rs @@ -1,6 +1,9 @@ // Copyright 2023-2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +// due to autogenerated code +#![allow(clippy::empty_line_after_doc_comments)] + use nym_sdk::mixnet::Recipient; use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag; uniffi::include_scaffolding!("bindings"); diff --git a/tools/internal/testnet-manager/dkg-bypass-contract/src/contract.rs b/tools/internal/testnet-manager/dkg-bypass-contract/src/contract.rs index c04fae8ef2..df70e604f4 100644 --- a/tools/internal/testnet-manager/dkg-bypass-contract/src/contract.rs +++ b/tools/internal/testnet-manager/dkg-bypass-contract/src/contract.rs @@ -33,7 +33,7 @@ pub(crate) struct VkShareIndex<'a> { pub(crate) epoch_id: MultiIndex<'a, EpochId, ContractVKShare, VKShareKey<'a>>, } -impl<'a> IndexList for VkShareIndex<'a> { +impl IndexList for VkShareIndex<'_> { fn get_indexes(&'_ self) -> Box> + '_> { let v: Vec<&dyn Index> = vec![&self.epoch_id]; Box::new(v.into_iter()) @@ -87,7 +87,7 @@ pub fn query(_: Deps<'_>, _: Env, _: EmptyMessage) -> Result, env: Env, msg: MigrateMsg) -> Result { // on migration immediately attempt to rewrite the storage - let threshold = (2 * msg.dealers.len() as u64 + 3 - 1) / 3; + let threshold = (2 * msg.dealers.len() as u64).div_ceil(3); let epoch = CURRENT_EPOCH.load(deps.storage)?; assert_eq!(0, epoch.epoch_id); diff --git a/tools/internal/testnet-manager/src/manager/dkg_skip.rs b/tools/internal/testnet-manager/src/manager/dkg_skip.rs index a132ea6950..7720202665 100644 --- a/tools/internal/testnet-manager/src/manager/dkg_skip.rs +++ b/tools/internal/testnet-manager/src/manager/dkg_skip.rs @@ -58,7 +58,7 @@ impl<'a> FakeDkgKey<'a> { } } -impl<'a> PemStorableKey for FakeDkgKey<'a> { +impl PemStorableKey for FakeDkgKey<'_> { type Error = NetworkManagerError; fn pem_type() -> &'static str { @@ -84,7 +84,7 @@ struct DkgSkipCtx<'a> { ecash_signers: Vec, } -impl<'a> ProgressCtx for DkgSkipCtx<'a> { +impl ProgressCtx for DkgSkipCtx<'_> { fn progress_tracker(&self) -> &ProgressTracker { &self.progress } @@ -138,7 +138,7 @@ impl NetworkManager { // generate required materials let n = api_endpoints.len(); - let threshold = (2 * n + 3 - 1) / 3; + let threshold = (2 * n).div_ceil(3); let ecash_keys = ttp_keygen(threshold as u64, n as u64)?; diff --git a/tools/internal/testnet-manager/src/manager/local_apis.rs b/tools/internal/testnet-manager/src/manager/local_apis.rs index 631f6117f2..124b2a324f 100644 --- a/tools/internal/testnet-manager/src/manager/local_apis.rs +++ b/tools/internal/testnet-manager/src/manager/local_apis.rs @@ -24,7 +24,7 @@ struct LocalApisCtx<'a> { signers: Vec, } -impl<'a> ProgressCtx for LocalApisCtx<'a> { +impl ProgressCtx for LocalApisCtx<'_> { fn progress_tracker(&self) -> &ProgressTracker { &self.progress } diff --git a/tools/internal/testnet-manager/src/manager/local_client.rs b/tools/internal/testnet-manager/src/manager/local_client.rs index c037f53719..fac5e6828a 100644 --- a/tools/internal/testnet-manager/src/manager/local_client.rs +++ b/tools/internal/testnet-manager/src/manager/local_client.rs @@ -30,7 +30,7 @@ struct LocalClientCtx<'a> { network: &'a LoadedNetwork, } -impl<'a> ProgressCtx for LocalClientCtx<'a> { +impl ProgressCtx for LocalClientCtx<'_> { fn progress_tracker(&self) -> &ProgressTracker { &self.progress } diff --git a/tools/internal/testnet-manager/src/manager/local_nodes.rs b/tools/internal/testnet-manager/src/manager/local_nodes.rs index dc19d44436..75edc76b7d 100644 --- a/tools/internal/testnet-manager/src/manager/local_nodes.rs +++ b/tools/internal/testnet-manager/src/manager/local_nodes.rs @@ -30,7 +30,7 @@ struct LocalNodesCtx<'a> { gateways: Vec, } -impl<'a> ProgressCtx for LocalNodesCtx<'a> { +impl ProgressCtx for LocalNodesCtx<'_> { fn progress_tracker(&self) -> &ProgressTracker { &self.progress } From 889d464e9837d60e84bcc95de85e51eefa8c03fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 29 Nov 2024 09:45:12 +0000 Subject: [PATCH 08/11] improvement: make internal gateway clients use the same topology cache (#5191) --- gateway/src/node/helpers.rs | 58 +++++++++++++++++++++++++++++-------- gateway/src/node/mod.rs | 4 +++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index d0862f1688..d87b02afed 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -5,6 +5,8 @@ use async_trait::async_trait; use nym_sdk::{NymApiTopologyProvider, NymApiTopologyProviderConfig, UserAgent}; use nym_topology::{gateway, NymTopology, TopologyProvider}; use std::sync::Arc; +use std::time::Duration; +use time::OffsetDateTime; use tokio::sync::Mutex; use tracing::debug; use url::Url; @@ -17,6 +19,7 @@ pub struct GatewayTopologyProvider { impl GatewayTopologyProvider { pub fn new( gateway_node: gateway::LegacyNode, + cache_ttl: Duration, user_agent: UserAgent, nym_api_url: Vec, ) -> GatewayTopologyProvider { @@ -31,6 +34,9 @@ impl GatewayTopologyProvider { env!("CARGO_PKG_VERSION").to_string(), Some(user_agent), ), + cache_ttl, + cached_at: OffsetDateTime::UNIX_EPOCH, + cached: None, gateway_node, })), } @@ -39,25 +45,53 @@ impl GatewayTopologyProvider { struct GatewayTopologyProviderInner { inner: NymApiTopologyProvider, + cache_ttl: Duration, + cached_at: OffsetDateTime, + cached: Option, gateway_node: gateway::LegacyNode, } +impl GatewayTopologyProviderInner { + fn cached_topology(&self) -> Option { + if let Some(cached_topology) = &self.cached { + if self.cached_at + self.cache_ttl > OffsetDateTime::now_utc() { + return Some(cached_topology.clone()); + } + } + + None + } + + async fn update_cache(&mut self) -> Option { + let updated_cache = match self.inner.get_new_topology().await { + None => None, + Some(mut base) => { + if !base.gateway_exists(&self.gateway_node.identity_key) { + debug!( + "{} didn't exist in topology. inserting it.", + self.gateway_node.identity_key + ); + base.insert_gateway(self.gateway_node.clone()); + } + Some(base) + } + }; + + self.cached_at = OffsetDateTime::now_utc(); + self.cached = updated_cache.clone(); + + updated_cache + } +} + #[async_trait] impl TopologyProvider for GatewayTopologyProvider { async fn get_new_topology(&mut self) -> Option { let mut guard = self.inner.lock().await; - match guard.inner.get_new_topology().await { - None => None, - Some(mut base) => { - if !base.gateway_exists(&guard.gateway_node.identity_key) { - debug!( - "{} didn't exist in topology. inserting it.", - guard.gateway_node.identity_key - ); - base.insert_gateway(guard.gateway_node.clone()); - } - Some(base) - } + // check the cache + if let Some(cached) = guard.cached_topology() { + return Some(cached); } + guard.update_cache().await } } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 48e7975018..90e60f5bfc 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -30,6 +30,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; use std::process; use std::sync::Arc; +use std::time::Duration; use tracing::*; pub(crate) mod client_handling; @@ -148,8 +149,11 @@ impl Gateway { } fn gateway_topology_provider(&self) -> GatewayTopologyProvider { + // TODO: make topology ttl configurable + // (to be done in reeses with the final smooshing) GatewayTopologyProvider::new( self.as_topology_node(), + Duration::from_secs(5 * 60), self.user_agent.clone(), self.config.gateway.nym_api_urls.clone(), ) From ab20260a2fd27eed7a8223937901e2d723ddfb4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 29 Nov 2024 14:56:39 +0200 Subject: [PATCH 09/11] Guard storage access with cache (#5193) * Guard storage access with cache * Do the sync way less freq * Change sync behaviour for bandwidth too * Use bigger delta --- Cargo.lock | 1 + .../src/bandwidth_storage_manager.rs | 2 +- .../src/client_bandwidth.rs | 4 +- common/wireguard/Cargo.toml | 1 + common/wireguard/src/lib.rs | 3 +- common/wireguard/src/peer_controller.rs | 24 ++- common/wireguard/src/peer_handle.rs | 30 ++-- common/wireguard/src/peer_storage_manager.rs | 138 ++++++++++++++++++ 8 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 common/wireguard/src/peer_storage_manager.rs diff --git a/Cargo.lock b/Cargo.lock index 3be4b4751b..6557b2c99f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6749,6 +6749,7 @@ dependencies = [ "nym-task", "nym-wireguard-types", "thiserror", + "time", "tokio", "tokio-stream", "x25519-dalek", diff --git a/common/credential-verification/src/bandwidth_storage_manager.rs b/common/credential-verification/src/bandwidth_storage_manager.rs index 3e35fd9eb2..7c3136e91c 100644 --- a/common/credential-verification/src/bandwidth_storage_manager.rs +++ b/common/credential-verification/src/bandwidth_storage_manager.rs @@ -111,7 +111,7 @@ impl BandwidthStorageManager { } #[instrument(level = "trace", skip_all)] - async fn sync_storage_bandwidth(&mut self) -> Result<()> { + pub async fn sync_storage_bandwidth(&mut self) -> Result<()> { trace!("syncing client bandwidth with the underlying storage"); let updated = self .storage diff --git a/common/credential-verification/src/client_bandwidth.rs b/common/credential-verification/src/client_bandwidth.rs index 9b764714e8..d98f89b511 100644 --- a/common/credential-verification/src/client_bandwidth.rs +++ b/common/credential-verification/src/client_bandwidth.rs @@ -8,8 +8,8 @@ use std::time::Duration; use time::OffsetDateTime; use tokio::sync::RwLock; -const DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE: Duration = Duration::from_millis(5); -const DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT: i64 = 512 * 1024; // 512kB +const DEFAULT_CLIENT_BANDWIDTH_MAX_FLUSHING_RATE: Duration = Duration::from_secs(5 * 60); // 5 minutes +const DEFAULT_CLIENT_BANDWIDTH_MAX_DELTA_FLUSHING_AMOUNT: i64 = 5 * 1024 * 1024; // 5MB #[derive(Debug, Clone, Copy)] pub struct BandwidthFlushingBehaviourConfig { diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index f20651acbd..c594e6b891 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -26,6 +26,7 @@ log.workspace = true thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } tokio-stream = { workspace = true } +time = { workspace = true } nym-authenticator-requests = { path = "../authenticator-requests" } nym-credential-verification = { path = "../credential-verification" } diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index ecd1576926..938c44e650 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -20,6 +20,7 @@ const WG_TUN_NAME: &str = "nymwg"; pub(crate) mod error; pub mod peer_controller; pub mod peer_handle; +pub mod peer_storage_manager; pub struct WgApiWrapper { inner: WGApi, @@ -118,7 +119,7 @@ pub async fn start_wireguard storage .insert_wireguard_peer(peer, bandwidth_manager.is_some()) .await?; - peer_bandwidth_managers.insert(peer.public_key.clone(), bandwidth_manager); + peer_bandwidth_managers.insert(peer.public_key.clone(), (bandwidth_manager, peer.clone())); } wg_api.create_interface()?; let interface_config = InterfaceConfiguration { diff --git a/common/wireguard/src/peer_controller.rs b/common/wireguard/src/peer_controller.rs index 8c7d94784a..321b15462f 100644 --- a/common/wireguard/src/peer_controller.rs +++ b/common/wireguard/src/peer_controller.rs @@ -20,9 +20,9 @@ use std::{collections::HashMap, sync::Arc}; use tokio::sync::{mpsc, RwLock}; use tokio_stream::{wrappers::IntervalStream, StreamExt}; -use crate::peer_handle::PeerHandle; use crate::WgApiWrapper; use crate::{error::Error, peer_handle::SharedBandwidthStorageManager}; +use crate::{peer_handle::PeerHandle, peer_storage_manager::PeerStorageManager}; pub enum PeerControlRequest { AddPeer { @@ -79,7 +79,7 @@ impl PeerController { storage: St, wg_api: Arc, initial_host_information: Host, - bw_storage_managers: HashMap>>, + bw_storage_managers: HashMap>, Peer)>, request_tx: mpsc::Sender, request_rx: mpsc::Receiver, task_client: nym_task::TaskClient, @@ -88,11 +88,16 @@ impl PeerController { tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK), ); let host_information = Arc::new(RwLock::new(initial_host_information)); - for (public_key, bandwidth_storage_manager) in bw_storage_managers.iter() { - let mut handle = PeerHandle::new( + for (public_key, (bandwidth_storage_manager, peer)) in bw_storage_managers.iter() { + let peer_storage_manager = PeerStorageManager::new( storage.clone(), + peer.clone(), + bandwidth_storage_manager.is_some(), + ); + let mut handle = PeerHandle::new( public_key.clone(), host_information.clone(), + peer_storage_manager, bandwidth_storage_manager.clone(), request_tx.clone(), &task_client, @@ -103,6 +108,10 @@ impl PeerController { } }); } + let bw_storage_managers = bw_storage_managers + .into_iter() + .map(|(k, (m, _))| (k, m)) + .collect(); PeerController { storage, @@ -184,10 +193,15 @@ impl PeerController { Self::generate_bandwidth_manager(self.storage.clone(), &peer.public_key) .await? .map(|bw_m| Arc::new(RwLock::new(bw_m))); - let mut handle = PeerHandle::new( + let peer_storage_manager = PeerStorageManager::new( self.storage.clone(), + peer.clone(), + bandwidth_storage_manager.is_some(), + ); + let mut handle = PeerHandle::new( peer.public_key.clone(), self.host_information.clone(), + peer_storage_manager, bandwidth_storage_manager.clone(), self.request_tx.clone(), &self.task_client, diff --git a/common/wireguard/src/peer_handle.rs b/common/wireguard/src/peer_handle.rs index 71fa06f847..a6e5f9e502 100644 --- a/common/wireguard/src/peer_handle.rs +++ b/common/wireguard/src/peer_handle.rs @@ -3,6 +3,7 @@ use crate::error::Error; use crate::peer_controller::PeerControlRequest; +use crate::peer_storage_manager::PeerStorageManager; use defguard_wireguard_rs::host::Peer; use defguard_wireguard_rs::{host::Host, key::Key}; use futures::channel::oneshot; @@ -21,9 +22,9 @@ pub(crate) type SharedBandwidthStorageManager = Arc { - storage: St, public_key: Key, host_information: Arc>, + peer_storage_manager: PeerStorageManager, bandwidth_storage_manager: Option>, request_tx: mpsc::Sender, timeout_check_interval: IntervalStream, @@ -33,9 +34,9 @@ pub struct PeerHandle { impl PeerHandle { pub fn new( - storage: St, public_key: Key, host_information: Arc>, + peer_storage_manager: PeerStorageManager, bandwidth_storage_manager: Option>, request_tx: mpsc::Sender, task_client: &TaskClient, @@ -46,9 +47,9 @@ impl PeerHandle { let mut task_client = task_client.fork(format!("peer-{public_key}")); task_client.disarm(); PeerHandle { - storage, public_key, host_information, + peer_storage_manager, bandwidth_storage_manager, request_tx, timeout_check_interval, @@ -84,16 +85,19 @@ impl PeerHandle { .ok_or(Error::InconsistentConsumedBytes)? .try_into() .map_err(|_| Error::InconsistentConsumedBytes)?; - if spent_bandwidth > 0 - && bandwidth_manager + if spent_bandwidth > 0 { + self.peer_storage_manager.update_trx(kernel_peer); + if bandwidth_manager .write() .await .try_use_bandwidth(spent_bandwidth) .await .is_err() - { - let success = self.remove_peer().await?; - return Ok(!success); + { + let success = self.remove_peer().await?; + self.peer_storage_manager.remove_peer(); + return Ok(!success); + } } } else { if SystemTime::now().duration_since(self.startup_timestamp)? >= AUTO_REMOVE_AFTER { @@ -132,7 +136,7 @@ impl PeerHandle { // the host information hasn't beed updated yet continue; }; - let Some(storage_peer) = self.storage.get_wireguard_peer(&self.public_key.to_string()).await? else { + let Some(storage_peer) = self.peer_storage_manager.get_peer() else { log::debug!("Peer {:?} not in storage anymore, shutting down handle", self.public_key); return Ok(()); }; @@ -141,12 +145,18 @@ impl PeerHandle { return Ok(()); } else { // Update storage values - self.storage.insert_wireguard_peer(&kernel_peer, self.bandwidth_storage_manager.is_some()).await?; + self.peer_storage_manager.sync_storage_peer().await?; } } _ = self.task_client.recv() => { log::trace!("PeerHandle: Received shutdown"); + if let Some(bandwidth_manager) = &self.bandwidth_storage_manager { + if let Err(e) = bandwidth_manager.write().await.sync_storage_bandwidth().await { + log::error!("Storage sync failed - {e}, unaccounted bandwidth might have been consumed"); + } + } + log::trace!("PeerHandle: Finished shutdown"); } } } diff --git a/common/wireguard/src/peer_storage_manager.rs b/common/wireguard/src/peer_storage_manager.rs new file mode 100644 index 0000000000..f7992b8bb0 --- /dev/null +++ b/common/wireguard/src/peer_storage_manager.rs @@ -0,0 +1,138 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::Error; +use defguard_wireguard_rs::host::Peer; +use nym_gateway_storage::models::WireguardPeer; +use nym_gateway_storage::Storage; +use std::time::Duration; +use time::OffsetDateTime; + +const DEFAULT_PEER_MAX_FLUSHING_RATE: Duration = Duration::from_secs(60 * 60 * 24); // 24h +const DEFAULT_PEER_MAX_DELTA_FLUSHING_AMOUNT: u64 = 512 * 1024 * 1024; // 512MB + +#[derive(Debug, Clone, Copy)] +pub struct PeerFlushingBehaviourConfig { + /// Defines maximum delay between peer information being flushed to the persistent storage. + pub peer_max_flushing_rate: Duration, + + /// Defines a maximum change in peer before it gets flushed to the persistent storage. + pub peer_max_delta_flushing_amount: u64, +} + +impl Default for PeerFlushingBehaviourConfig { + fn default() -> Self { + Self { + peer_max_flushing_rate: DEFAULT_PEER_MAX_FLUSHING_RATE, + peer_max_delta_flushing_amount: DEFAULT_PEER_MAX_DELTA_FLUSHING_AMOUNT, + } + } +} + +pub struct PeerStorageManager { + pub(crate) storage: S, + pub(crate) peer_information: Option, + pub(crate) cfg: PeerFlushingBehaviourConfig, + pub(crate) with_client_id: bool, +} + +impl PeerStorageManager { + pub(crate) fn new(storage: S, peer: Peer, with_client_id: bool) -> Self { + let peer_information = Some(PeerInformation::new(peer)); + Self { + storage, + peer_information, + cfg: PeerFlushingBehaviourConfig::default(), + with_client_id, + } + } + + pub(crate) fn get_peer(&self) -> Option { + self.peer_information + .as_ref() + .map(|p| p.peer.clone().into()) + } + + pub(crate) fn remove_peer(&mut self) { + self.peer_information = None; + } + + pub(crate) fn update_trx(&mut self, kernel_peer: &Peer) { + if let Some(peer_information) = self.peer_information.as_mut() { + peer_information.update_trx_bytes(kernel_peer.tx_bytes, kernel_peer.rx_bytes); + } + } + + pub(crate) async fn sync_storage_peer(&mut self) -> Result<(), Error> { + let Some(peer_information) = self.peer_information.as_mut() else { + return Ok(()); + }; + if !peer_information.should_sync(self.cfg) { + return Ok(()); + } + if self + .storage + .get_wireguard_peer(&peer_information.peer().public_key.to_string()) + .await? + .is_none() + { + self.peer_information = None; + return Ok(()); + } + self.storage + .insert_wireguard_peer(peer_information.peer(), self.with_client_id) + .await?; + + peer_information.resync_peer_with_storage(); + + Ok(()) + } +} + +#[derive(Clone, Debug)] +pub(crate) struct PeerInformation { + pub(crate) peer: Peer, + pub(crate) last_synced: OffsetDateTime, + + pub(crate) bytes_delta_since_sync: u64, +} + +impl PeerInformation { + pub fn new(peer: Peer) -> PeerInformation { + PeerInformation { + peer, + last_synced: OffsetDateTime::now_utc(), + bytes_delta_since_sync: 0, + } + } + + pub(crate) fn should_sync(&self, cfg: PeerFlushingBehaviourConfig) -> bool { + if self.bytes_delta_since_sync >= cfg.peer_max_delta_flushing_amount { + return true; + } + + if self.last_synced + cfg.peer_max_flushing_rate < OffsetDateTime::now_utc() + && self.bytes_delta_since_sync != 0 + { + return true; + } + + false + } + + pub(crate) fn peer(&self) -> &Peer { + &self.peer + } + + pub(crate) fn update_trx_bytes(&mut self, tx_bytes: u64, rx_bytes: u64) { + self.bytes_delta_since_sync += tx_bytes.saturating_sub(self.peer.tx_bytes) + + rx_bytes.saturating_sub(self.peer.rx_bytes); + self.peer.tx_bytes = tx_bytes; + self.peer.rx_bytes = rx_bytes; + } + + pub(crate) fn resync_peer_with_storage(&mut self) { + self.bytes_delta_since_sync = 0; + self.last_synced = OffsetDateTime::now_utc(); + } +} From 96180275f8602defe50251202bae02cda8bd9c15 Mon Sep 17 00:00:00 2001 From: benedetta davico <46782255+benedettadavico@users.noreply.github.com> Date: Fri, 29 Nov 2024 13:57:57 +0100 Subject: [PATCH 10/11] Update Cargo.toml --- nym-node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index 07c8b33476..d687b7825b 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node" -version = "1.1.11" +version = "1.1.12" authors.workspace = true repository.workspace = true homepage.workspace = true From 4a9a5579c40ad956163ea02e01d7b53aef2ac8ef Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 29 Nov 2024 14:06:32 +0100 Subject: [PATCH 11/11] update changelog --- CHANGELOG.md | 4 ++++ Cargo.lock | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46cb35531e..bda75be82a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [2024.13-magura-drift] (2024-11-29) + +- Optimised syncing bandwidth information to storage + ## [2024.13-magura-patched] (2024-11-22) - [experimental] allow clients to change between deterministic route selection based on packet headers and a pseudorandom distribution diff --git a/Cargo.lock b/Cargo.lock index 6557b2c99f..8c183a73f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5880,7 +5880,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.1.11" +version = "1.1.12" dependencies = [ "anyhow", "bip39",