Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cd29132a45 | |||
| 38e66f6ddf | |||
| b9fbe0b8f3 | |||
| daafb5cae4 | |||
| 0ec2514edf | |||
| d6435a8270 | |||
| 9efc50e067 | |||
| 1532547e2b | |||
| 0cb11632e6 | |||
| f71ea52d5d | |||
| 338835698c | |||
| e65e261cd3 | |||
| 2d78f6939e | |||
| 9a45de5874 | |||
| 2f894b9be3 | |||
| d36ea20366 | |||
| 7b1200f338 | |||
| d291582128 | |||
| 9800411990 | |||
| 18c6fd3e3e | |||
| d75c7eaaaf | |||
| 99cf7d1eec | |||
| f786dbeaa7 | |||
| eae76cce10 | |||
| 9341db5d08 | |||
| 75a5192c6d | |||
| 25ad0920cf | |||
| a1e75e1dff | |||
| e59a9a59b6 | |||
| 4c51a8975c | |||
| a4c6f51fe0 |
@@ -29,12 +29,17 @@ jobs:
|
||||
uses: mikefarah/yq@v4.44.3
|
||||
id: get_version
|
||||
with:
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
|
||||
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
|
||||
|
||||
- name: Check if tag exists
|
||||
run: |
|
||||
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
|
||||
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
|
||||
fi
|
||||
|
||||
- name: Remove existing tag if exists
|
||||
run: |
|
||||
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
|
||||
echo "Tag ${{ steps.get_version.outputs.result }} already exists, deleting"
|
||||
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
||||
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
|
||||
fi
|
||||
@@ -46,5 +51,5 @@ jobs:
|
||||
|
||||
- name: BuildAndPushImageOnHarbor
|
||||
run: |
|
||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||
docker build -f ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
|
||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
||||
|
||||
@@ -4,6 +4,80 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.12-aero] (2024-10-17)
|
||||
|
||||
- nym-node: don't use bloomfilters for double spending checks ([#4960])
|
||||
- bugfix: replace unreachable macro with an error return ([#4958])
|
||||
- [DOCs:/operators]: Update FAQ sphinx size ([#4946])
|
||||
- [DOCs/operators]: Release notes v2024.11-wedel ([#4939])
|
||||
- Fix handle drop ([#4934])
|
||||
- Assume offline mode ([#4926])
|
||||
- Make ip-packet-request VERSION pub ([#4925])
|
||||
- Expose error type ([#4924])
|
||||
- Fix argument to cargo-deny action ([#4922])
|
||||
- Fix nymvpn.com url in mainnet defaults ([#4920])
|
||||
- Check both version and type in message header ([#4918])
|
||||
- Bump http-api-client default timeout to 30 sec ([#4917])
|
||||
- Max/proxy ffi ([#4906])
|
||||
- Data Observatory stub ([#4905])
|
||||
- Fix missing duplication of modified tables ([#4904])
|
||||
- Update cargo deny ([#4901])
|
||||
- docs: add hostname instructions for wss ([#4900])
|
||||
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#4898])
|
||||
- Fix clippy for beta toolchain ([#4897])
|
||||
- Remove clippy github PR annotations ([#4896])
|
||||
- Fix apt install in ci-build-upload-binaries.yml ([#4894])
|
||||
- Update network monitor entrypoint ([#4893])
|
||||
- Update nym-vpn metapackage and replace nymvpn-x with nym-vpn-app ([#4889])
|
||||
- Entry wireguard tickets ([#4888])
|
||||
- Build and Push CI ([#4887])
|
||||
- Feature/updated gateway registration ([#4885])
|
||||
- Few fixes to NNM pre deploy ([#4883])
|
||||
- Fix sql serde with enum ([#4875])
|
||||
- allow clients to send stateless gateway requests without prior registration ([#4873])
|
||||
- chore: remove queued migration for adding explicit admin ([#4871])
|
||||
- Gateway database modifications for different modes ([#4868])
|
||||
- build(deps): bump strum from 0.25.0 to 0.26.3 ([#4848])
|
||||
- Use serde from workspace ([#4833])
|
||||
- build(deps): bump toml from 0.5.11 to 0.8.14 ([#4805])
|
||||
- Max/rust sdk stream abstraction ([#4743])
|
||||
|
||||
[#4960]: https://github.com/nymtech/nym/pull/4960
|
||||
[#4958]: https://github.com/nymtech/nym/pull/4958
|
||||
[#4946]: https://github.com/nymtech/nym/pull/4946
|
||||
[#4939]: https://github.com/nymtech/nym/pull/4939
|
||||
[#4934]: https://github.com/nymtech/nym/pull/4934
|
||||
[#4926]: https://github.com/nymtech/nym/pull/4926
|
||||
[#4925]: https://github.com/nymtech/nym/pull/4925
|
||||
[#4924]: https://github.com/nymtech/nym/pull/4924
|
||||
[#4922]: https://github.com/nymtech/nym/pull/4922
|
||||
[#4920]: https://github.com/nymtech/nym/pull/4920
|
||||
[#4918]: https://github.com/nymtech/nym/pull/4918
|
||||
[#4917]: https://github.com/nymtech/nym/pull/4917
|
||||
[#4906]: https://github.com/nymtech/nym/pull/4906
|
||||
[#4905]: https://github.com/nymtech/nym/pull/4905
|
||||
[#4904]: https://github.com/nymtech/nym/pull/4904
|
||||
[#4901]: https://github.com/nymtech/nym/pull/4901
|
||||
[#4900]: https://github.com/nymtech/nym/pull/4900
|
||||
[#4898]: https://github.com/nymtech/nym/pull/4898
|
||||
[#4897]: https://github.com/nymtech/nym/pull/4897
|
||||
[#4896]: https://github.com/nymtech/nym/pull/4896
|
||||
[#4894]: https://github.com/nymtech/nym/pull/4894
|
||||
[#4893]: https://github.com/nymtech/nym/pull/4893
|
||||
[#4889]: https://github.com/nymtech/nym/pull/4889
|
||||
[#4888]: https://github.com/nymtech/nym/pull/4888
|
||||
[#4887]: https://github.com/nymtech/nym/pull/4887
|
||||
[#4885]: https://github.com/nymtech/nym/pull/4885
|
||||
[#4883]: https://github.com/nymtech/nym/pull/4883
|
||||
[#4875]: https://github.com/nymtech/nym/pull/4875
|
||||
[#4873]: https://github.com/nymtech/nym/pull/4873
|
||||
[#4871]: https://github.com/nymtech/nym/pull/4871
|
||||
[#4868]: https://github.com/nymtech/nym/pull/4868
|
||||
[#4848]: https://github.com/nymtech/nym/pull/4848
|
||||
[#4833]: https://github.com/nymtech/nym/pull/4833
|
||||
[#4805]: https://github.com/nymtech/nym/pull/4805
|
||||
[#4743]: https://github.com/nymtech/nym/pull/4743
|
||||
|
||||
## [2024.11-wedel] (2024-09-23)
|
||||
|
||||
- Backport #4894 to fix ci ([#4899])
|
||||
|
||||
Generated
+8
-8
@@ -2364,7 +2364,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "explorer-api"
|
||||
version = "1.1.40"
|
||||
version = "1.1.41"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.5.18",
|
||||
@@ -4347,7 +4347,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.44"
|
||||
version = "1.1.45"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -4588,7 +4588,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli"
|
||||
version = "1.1.42"
|
||||
version = "1.1.43"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
@@ -4669,7 +4669,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-client"
|
||||
version = "1.1.41"
|
||||
version = "1.1.42"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap 4.5.18",
|
||||
@@ -5714,7 +5714,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.42"
|
||||
version = "1.1.43"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
@@ -5765,7 +5765,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
@@ -6055,7 +6055,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.41"
|
||||
version = "1.1.42"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"clap 4.5.18",
|
||||
@@ -6600,7 +6600,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nymvisor"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-client"
|
||||
version = "1.1.41"
|
||||
version = "1.1.42"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-socks5-client"
|
||||
version = "1.1.41"
|
||||
version = "1.1.42"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
|
||||
@@ -19,7 +19,7 @@ use nym_api_requests::ecash::{
|
||||
};
|
||||
use nym_api_requests::models::{
|
||||
GatewayCoreStatusResponse, MixnodeCoreStatusResponse, MixnodeStatusResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
NymNodeDescription, RewardEstimationResponse, StakeSaturationResponse,
|
||||
};
|
||||
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
|
||||
use nym_api_requests::nym_nodes::SkimmedNode;
|
||||
@@ -320,7 +320,7 @@ impl NymApiClient {
|
||||
loop {
|
||||
let mut res = self
|
||||
.nym_api
|
||||
.get_all_basic_entry_assigned_nodes(
|
||||
.get_basic_entry_assigned_nodes(
|
||||
semver_compatibility.clone(),
|
||||
false,
|
||||
Some(page),
|
||||
@@ -397,6 +397,27 @@ impl NymApiClient {
|
||||
Ok(self.nym_api.get_gateways_described().await?)
|
||||
}
|
||||
|
||||
pub async fn get_all_described_nodes(
|
||||
&self,
|
||||
) -> Result<Vec<NymNodeDescription>, ValidatorClientError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
let mut descriptions = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut res = self.nym_api.get_nodes_described(Some(page), None).await?;
|
||||
|
||||
descriptions.append(&mut res.data);
|
||||
if descriptions.len() < res.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
pub async fn get_gateway_core_status_count(
|
||||
&self,
|
||||
identity: IdentityKeyRef<'_>,
|
||||
|
||||
@@ -11,9 +11,10 @@ use nym_api_requests::ecash::models::{
|
||||
};
|
||||
use nym_api_requests::ecash::VerificationKeyResponse;
|
||||
use nym_api_requests::models::{
|
||||
AnnotationResponse, LegacyDescribedMixNode, NodePerformanceResponse,
|
||||
AnnotationResponse, LegacyDescribedMixNode, NodePerformanceResponse, NymNodeDescription,
|
||||
};
|
||||
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
|
||||
use nym_api_requests::pagination::PaginatedResponse;
|
||||
pub use nym_api_requests::{
|
||||
ecash::{
|
||||
models::{
|
||||
@@ -119,6 +120,25 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_nodes_described(
|
||||
&self,
|
||||
page: Option<u32>,
|
||||
per_page: Option<u32>,
|
||||
) -> Result<PaginatedResponse<NymNodeDescription>, NymAPIError> {
|
||||
let mut params = Vec::new();
|
||||
|
||||
if let Some(page) = page {
|
||||
params.push(("page", page.to_string()))
|
||||
}
|
||||
|
||||
if let Some(per_page) = per_page {
|
||||
params.push(("per_page", per_page.to_string()))
|
||||
}
|
||||
|
||||
self.get_json(&[routes::API_VERSION, "nym-nodes", "described"], ¶ms)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_basic_mixnodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
@@ -167,7 +187,7 @@ pub trait NymApiClientExt: ApiClient {
|
||||
|
||||
/// retrieve basic information for nodes are capable of operating as an entry gateway
|
||||
/// this includes legacy gateways and nym-nodes
|
||||
async fn get_all_basic_entry_assigned_nodes(
|
||||
async fn get_basic_entry_assigned_nodes(
|
||||
&self,
|
||||
semver_compatibility: Option<String>,
|
||||
no_legacy: bool,
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::ecash::error::EcashTicketError;
|
||||
use crate::ecash::state::SharedState;
|
||||
use nym_ecash_double_spending::DoubleSpendingFilter;
|
||||
use nym_gateway_storage::Storage;
|
||||
use nym_task::TaskClient;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::EcashApiClient;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use tokio::time::{interval, Duration};
|
||||
use tracing::{info, trace, warn};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct DoubleSpendingDetector<S> {
|
||||
spent_serial_numbers: Arc<RwLock<DoubleSpendingFilter>>,
|
||||
shared_state: SharedState<S>,
|
||||
}
|
||||
|
||||
impl<S> DoubleSpendingDetector<S>
|
||||
where
|
||||
S: Storage + Clone + Send + Sync + 'static,
|
||||
{
|
||||
pub(crate) fn new(shared_state: SharedState<S>) -> Self {
|
||||
DoubleSpendingDetector {
|
||||
spent_serial_numbers: Arc::new(RwLock::new(DoubleSpendingFilter::new_empty_ecash())),
|
||||
shared_state,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn check(&self, serial_number: &Vec<u8>) -> bool {
|
||||
self.spent_serial_numbers.read().await.check(serial_number)
|
||||
}
|
||||
|
||||
async fn latest_api_endpoints(
|
||||
&self,
|
||||
) -> Result<RwLockReadGuard<Vec<EcashApiClient>>, EcashTicketError> {
|
||||
let epoch_id = self.shared_state.current_epoch_id().await?;
|
||||
self.shared_state.api_clients(epoch_id).await
|
||||
}
|
||||
|
||||
async fn refresh_bloomfilter(&self) {
|
||||
let mut filter_builder = self.spent_serial_numbers.read().await.rebuild();
|
||||
|
||||
let api_clients = match self.latest_api_endpoints().await {
|
||||
Ok(clients) => clients,
|
||||
Err(err) => {
|
||||
warn!("failed to obtain current api clients: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut clients = api_clients
|
||||
.iter()
|
||||
.map(|c| c.api_client.clone())
|
||||
.collect::<Vec<_>>();
|
||||
clients.shuffle(&mut thread_rng());
|
||||
|
||||
for client in clients {
|
||||
match client.nym_api.double_spending_filter_v1().await {
|
||||
Ok(response) => {
|
||||
// due to relative big size of the filter, query only one api since all of them should contain
|
||||
// roughly the same data anyway.
|
||||
filter_builder.add_bytes(&response.bitmap);
|
||||
*self.spent_serial_numbers.write().await = filter_builder.build();
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Validator @ {} could not be reached. There might be a problem with the ecash endpoint: {err}", client.api_url());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
warn!("none of the validators could be reached. the bloomfilter will remain unchanged.");
|
||||
}
|
||||
|
||||
async fn run(&self, mut shutdown: TaskClient) {
|
||||
info!("Starting Ecash DoubleSpendingDetector");
|
||||
let mut interval = interval(Duration::from_secs(600));
|
||||
|
||||
while !shutdown.is_shutdown() {
|
||||
tokio::select! {
|
||||
biased;
|
||||
_ = shutdown.recv() => {
|
||||
trace!("ecash_verifier::DoubleSpendingDetector : received shutdown");
|
||||
},
|
||||
_ = interval.tick() => self.refresh_bloomfilter().await,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start(self, shutdown: nym_task::TaskClient) {
|
||||
tokio::spawn(async move { self.run(shutdown).await });
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
use crate::Error;
|
||||
use credential_sender::CredentialHandler;
|
||||
use credential_sender::CredentialHandlerConfig;
|
||||
use double_spending::DoubleSpendingDetector;
|
||||
use error::EcashTicketError;
|
||||
use futures::channel::mpsc::{self, UnboundedSender};
|
||||
use nym_credentials::CredentialSpendingData;
|
||||
@@ -18,7 +17,6 @@ use tokio::sync::{Mutex, RwLockReadGuard};
|
||||
use tracing::error;
|
||||
|
||||
pub mod credential_sender;
|
||||
pub(crate) mod double_spending;
|
||||
pub mod error;
|
||||
mod helpers;
|
||||
mod state;
|
||||
@@ -31,7 +29,6 @@ pub struct EcashManager<S> {
|
||||
pk_bytes: [u8; 32], // bytes representation of a pub key representing the verifier
|
||||
pay_infos: Mutex<Vec<NymPayInfo>>,
|
||||
cred_sender: UnboundedSender<ClientTicket>,
|
||||
double_spend_detector: DoubleSpendingDetector<S>,
|
||||
}
|
||||
|
||||
impl<S> EcashManager<S>
|
||||
@@ -47,9 +44,6 @@ where
|
||||
) -> Result<Self, Error> {
|
||||
let shared_state = SharedState::new(nyxd_client, storage).await?;
|
||||
|
||||
let double_spend_detector = DoubleSpendingDetector::new(shared_state.clone());
|
||||
double_spend_detector.clone().start(shutdown.clone());
|
||||
|
||||
let (cred_sender, cred_receiver) = mpsc::unbounded();
|
||||
|
||||
let cs =
|
||||
@@ -62,7 +56,6 @@ where
|
||||
pk_bytes,
|
||||
pay_infos: Default::default(),
|
||||
cred_sender,
|
||||
double_spend_detector,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -163,10 +156,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn check_double_spend(&self, serial_number: &Vec<u8>) -> bool {
|
||||
self.double_spend_detector.check(serial_number).await
|
||||
}
|
||||
|
||||
pub fn async_verify(&self, ticket: ClientTicket) {
|
||||
// TODO: I guess do something for shutdowns
|
||||
let _ = self
|
||||
|
||||
@@ -53,18 +53,6 @@ impl<S: Storage + Clone + 'static> CredentialVerifier<S> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn check_bloomfilter(&self, serial_number: &Vec<u8>) -> Result<()> {
|
||||
trace!("checking the bloomfilter...");
|
||||
|
||||
let spent = self.ecash_verifier.check_double_spend(serial_number).await;
|
||||
|
||||
if spent {
|
||||
trace!("the credential has already been spent before at some gateway before (bloomfilter failure)");
|
||||
return Err(Error::BandwidthCredentialAlreadySpent);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn check_local_db_for_double_spending(&self, serial_number: &[u8]) -> Result<()> {
|
||||
trace!("checking local db for double spending...");
|
||||
|
||||
@@ -128,7 +116,6 @@ impl<S: Storage + Clone + 'static> CredentialVerifier<S> {
|
||||
}
|
||||
|
||||
self.check_credential_spending_date(spend_date.ecash_date())?;
|
||||
self.check_bloomfilter(&serial_number).await?;
|
||||
self.check_local_db_for_double_spending(&serial_number)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ pub enum TicketTypeRepr {
|
||||
}
|
||||
|
||||
impl TicketTypeRepr {
|
||||
pub const WIREGUARD_ENTRY_TICKET_SIZE: u64 = 512 * 1024 * 1024; // 512 MB
|
||||
pub const WIREGUARD_EXIT_TICKET_SIZE: u64 = 512 * 1024 * 1024; // 512 MB
|
||||
pub const MIXNET_ENTRY_TICKET_SIZE: u64 = 128 * 1024 * 1024; // 128 MB
|
||||
pub const MIXNET_EXIT_TICKET_SIZE: u64 = 128 * 1024 * 1024; // 128 MB
|
||||
pub const WIREGUARD_ENTRY_TICKET_SIZE: u64 = 500 * 1000 * 1000; // 500 MB
|
||||
pub const WIREGUARD_EXIT_TICKET_SIZE: u64 = 500 * 1000 * 1000; // 500 MB
|
||||
pub const MIXNET_ENTRY_TICKET_SIZE: u64 = 200 * 1000 * 1000; // 200 MB
|
||||
pub const MIXNET_EXIT_TICKET_SIZE: u64 = 100 * 1000 * 1000; // 100 MB
|
||||
|
||||
/// How much bandwidth (in bytes) one ticket can grant
|
||||
pub const fn bandwidth_value(&self) -> u64 {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::fragment::{linked_fragment_payload_max_len, unlinked_fragment_payload_max_len};
|
||||
use dashmap::DashMap;
|
||||
use fragment::{Fragment, FragmentHeader};
|
||||
use fragment::FragmentHeader;
|
||||
use nym_crypto::asymmetric::ed25519::PublicKey;
|
||||
use serde::Serialize;
|
||||
pub use set::split_into_sets;
|
||||
@@ -29,6 +26,59 @@ pub mod fragment;
|
||||
pub mod reconstruction;
|
||||
pub mod set;
|
||||
|
||||
pub mod monitoring {
|
||||
use crate::fragment::Fragment;
|
||||
use crate::{ReceivedFragment, SentFragment};
|
||||
use dashmap::DashMap;
|
||||
use nym_crypto::asymmetric::ed25519::PublicKey;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub static ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub static FRAGMENTS_RECEIVED: LazyLock<DashMap<i32, Vec<ReceivedFragment>>> =
|
||||
LazyLock::new(DashMap::new);
|
||||
|
||||
pub static FRAGMENTS_SENT: LazyLock<DashMap<i32, Vec<SentFragment>>> =
|
||||
LazyLock::new(DashMap::new);
|
||||
|
||||
pub fn enable() {
|
||||
ENABLED.store(true, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn enabled() -> bool {
|
||||
ENABLED.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! now {
|
||||
() => {
|
||||
match std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) {
|
||||
Ok(n) => n.as_secs(),
|
||||
Err(_) => 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fragment_received(fragment: &Fragment) {
|
||||
if enabled() {
|
||||
let id = fragment.fragment_identifier().set_id();
|
||||
let mut entry = FRAGMENTS_RECEIVED.entry(id).or_default();
|
||||
let r = ReceivedFragment::new(fragment.header(), now!());
|
||||
entry.push(r);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fragment_sent(fragment: &Fragment, client_nonce: i32, destination: PublicKey, hops: u8) {
|
||||
if enabled() {
|
||||
let id = fragment.fragment_identifier().set_id();
|
||||
let mut entry = FRAGMENTS_SENT.entry(id).or_default();
|
||||
let s = SentFragment::new(fragment.header(), now!(), client_nonce, destination, hops);
|
||||
entry.push(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FragmentMixParams {
|
||||
destination: PublicKey,
|
||||
@@ -112,35 +162,6 @@ impl ReceivedFragment {
|
||||
}
|
||||
}
|
||||
|
||||
pub static FRAGMENTS_RECEIVED: LazyLock<DashMap<i32, Vec<ReceivedFragment>>> =
|
||||
LazyLock::new(DashMap::new);
|
||||
|
||||
pub static FRAGMENTS_SENT: LazyLock<DashMap<i32, Vec<SentFragment>>> = LazyLock::new(DashMap::new);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! now {
|
||||
() => {
|
||||
match std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) {
|
||||
Ok(n) => n.as_secs(),
|
||||
Err(_) => 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fragment_received(fragment: &Fragment) {
|
||||
let id = fragment.fragment_identifier().set_id();
|
||||
let mut entry = FRAGMENTS_RECEIVED.entry(id).or_default();
|
||||
let r = ReceivedFragment::new(fragment.header(), now!());
|
||||
entry.push(r);
|
||||
}
|
||||
|
||||
pub fn fragment_sent(fragment: &Fragment, client_nonce: i32, destination: PublicKey, hops: u8) {
|
||||
let id = fragment.fragment_identifier().set_id();
|
||||
let mut entry = FRAGMENTS_SENT.entry(id).or_default();
|
||||
let s = SentFragment::new(fragment.header(), now!(), client_nonce, destination, hops);
|
||||
entry.push(s);
|
||||
}
|
||||
|
||||
/// The idea behind the process of chunking is to incur as little data overhead as possible due
|
||||
/// to very computationally costly sphinx encapsulation procedure.
|
||||
///
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
use crate::fragment::Fragment;
|
||||
use crate::{fragment_received, ChunkingError};
|
||||
use crate::{monitoring, ChunkingError};
|
||||
use log::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -110,7 +110,7 @@ impl ReconstructionBuffer {
|
||||
}
|
||||
});
|
||||
|
||||
fragment_received(&fragment);
|
||||
monitoring::fragment_received(&fragment);
|
||||
|
||||
let fragment_index = fragment.current_fragment() as usize - 1;
|
||||
if self.fragments[fragment_index].is_some() {
|
||||
|
||||
@@ -12,7 +12,6 @@ use nym_sphinx_addressing::clients::Recipient;
|
||||
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
use nym_sphinx_anonymous_replies::reply_surb::ReplySurb;
|
||||
use nym_sphinx_chunking::fragment::{Fragment, FragmentIdentifier};
|
||||
use nym_sphinx_chunking::fragment_sent;
|
||||
use nym_sphinx_forwarding::packet::MixPacket;
|
||||
use nym_sphinx_params::packet_sizes::PacketSize;
|
||||
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
@@ -21,6 +20,7 @@ use nym_topology::{NymTopology, NymTopologyError};
|
||||
use rand::{CryptoRng, Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
|
||||
use nym_sphinx_chunking::monitoring;
|
||||
use std::time::Duration;
|
||||
|
||||
pub(crate) mod payload;
|
||||
@@ -206,7 +206,7 @@ pub trait FragmentPreparer {
|
||||
|
||||
let destination = packet_recipient.gateway();
|
||||
let hops = mix_hops.unwrap_or(self.num_mix_hops());
|
||||
fragment_sent(&fragment, self.nonce(), *destination, hops);
|
||||
monitoring::fragment_sent(&fragment, self.nonce(), *destination, hops);
|
||||
|
||||
let non_reply_overhead = encryption::PUBLIC_KEY_SIZE;
|
||||
let expected_plaintext = match packet_type {
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("peers in wireguard don't match with in-memory ")]
|
||||
PeerMismatch,
|
||||
|
||||
#[error("traffic byte data needs to be increasing")]
|
||||
InconsistentConsumedBytes,
|
||||
|
||||
@@ -20,4 +17,7 @@ pub enum Error {
|
||||
|
||||
#[error("{0}")]
|
||||
GatewayStorage(#[from] nym_gateway_storage::error::StorageError),
|
||||
|
||||
#[error("{0}")]
|
||||
SystemTime(#[from] std::time::SystemTimeError),
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::{error::Error, peer_handle::SharedBandwidthStorageManager};
|
||||
pub enum PeerControlRequest {
|
||||
AddPeer {
|
||||
peer: Peer,
|
||||
ticket_validation: bool,
|
||||
client_id: Option<i64>,
|
||||
response_tx: oneshot::Sender<AddPeerControlResponse>,
|
||||
},
|
||||
RemovePeer {
|
||||
@@ -46,7 +46,6 @@ pub enum PeerControlRequest {
|
||||
|
||||
pub struct AddPeerControlResponse {
|
||||
pub success: bool,
|
||||
pub client_id: Option<i64>,
|
||||
}
|
||||
|
||||
pub struct RemovePeerControlResponse {
|
||||
@@ -118,13 +117,13 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
}
|
||||
|
||||
// Function that should be used for peer insertion, to handle both storage and kernel interaction
|
||||
pub async fn add_peer(&self, peer: &Peer, with_client_id: bool) -> Result<Option<i64>, Error> {
|
||||
let client_id = self
|
||||
.storage
|
||||
.insert_wireguard_peer(peer, with_client_id)
|
||||
.await?;
|
||||
let ret = self.wg_api.inner.configure_peer(peer);
|
||||
if ret.is_err() {
|
||||
pub async fn add_peer(&self, peer: &Peer, client_id: Option<i64>) -> Result<(), Error> {
|
||||
if client_id.is_none() {
|
||||
self.storage.insert_wireguard_peer(peer, false).await?;
|
||||
}
|
||||
let ret: Result<(), defguard_wireguard_rs::error::WireguardInterfaceError> =
|
||||
self.wg_api.inner.configure_peer(peer);
|
||||
if client_id.is_none() && ret.is_err() {
|
||||
// Try to revert the insertion in storage
|
||||
if self
|
||||
.storage
|
||||
@@ -135,8 +134,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
log::error!("The storage has been corrupted. Wireguard peer {} will persist in storage indefinitely.", peer.public_key);
|
||||
}
|
||||
}
|
||||
ret?;
|
||||
Ok(client_id)
|
||||
Ok(ret?)
|
||||
}
|
||||
|
||||
// Function that should be used for peer removal, to handle both storage and kernel interaction
|
||||
@@ -179,9 +177,9 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
async fn handle_add_request(
|
||||
&mut self,
|
||||
peer: &Peer,
|
||||
with_client_id: bool,
|
||||
) -> Result<Option<i64>, Error> {
|
||||
let client_id = self.add_peer(peer, with_client_id).await?;
|
||||
client_id: Option<i64>,
|
||||
) -> Result<(), Error> {
|
||||
self.add_peer(peer, client_id).await?;
|
||||
let bandwidth_storage_manager =
|
||||
Self::generate_bandwidth_manager(self.storage.clone(), &peer.public_key)
|
||||
.await?
|
||||
@@ -201,7 +199,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
log::error!("Peer handle shut down ungracefully - {e}");
|
||||
}
|
||||
});
|
||||
Ok(client_id)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_query_peer(&self, key: &Key) -> Result<Option<Peer>, Error> {
|
||||
@@ -228,14 +226,10 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
.available_bandwidth()
|
||||
.await
|
||||
} else {
|
||||
let peer = self
|
||||
.host_information
|
||||
.read()
|
||||
.await
|
||||
.peers
|
||||
.get(key)
|
||||
.ok_or(Error::PeerMismatch)?
|
||||
.clone();
|
||||
let Some(peer) = self.host_information.read().await.peers.get(key).cloned() else {
|
||||
// host information not updated yet
|
||||
return Ok(None);
|
||||
};
|
||||
BANDWIDTH_CAP_PER_DAY.saturating_sub((peer.rx_bytes + peer.tx_bytes) as i64)
|
||||
};
|
||||
|
||||
@@ -260,12 +254,12 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
|
||||
}
|
||||
msg = self.request_rx.recv() => {
|
||||
match msg {
|
||||
Some(PeerControlRequest::AddPeer { peer, ticket_validation, response_tx }) => {
|
||||
let ret = self.handle_add_request(&peer, ticket_validation).await;
|
||||
if let Ok(client_id) = ret {
|
||||
response_tx.send(AddPeerControlResponse { success: true, client_id }).ok();
|
||||
Some(PeerControlRequest::AddPeer { peer, client_id, response_tx }) => {
|
||||
let ret = self.handle_add_request(&peer, client_id).await;
|
||||
if ret.is_ok() {
|
||||
response_tx.send(AddPeerControlResponse { success: true }).ok();
|
||||
} else {
|
||||
response_tx.send(AddPeerControlResponse { success: false, client_id: None }).ok();
|
||||
response_tx.send(AddPeerControlResponse { success: false }).ok();
|
||||
}
|
||||
}
|
||||
Some(PeerControlRequest::RemovePeer { key, response_tx }) => {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::peer_controller::PeerControlRequest;
|
||||
use defguard_wireguard_rs::host::Peer;
|
||||
use defguard_wireguard_rs::{host::Host, key::Key};
|
||||
use futures::channel::oneshot;
|
||||
use nym_authenticator_requests::v2::registration::BANDWIDTH_CAP_PER_DAY;
|
||||
@@ -12,10 +13,12 @@ use nym_gateway_storage::Storage;
|
||||
use nym_task::TaskClient;
|
||||
use nym_wireguard_types::DEFAULT_PEER_TIMEOUT_CHECK;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use tokio::sync::{mpsc, RwLock};
|
||||
use tokio_stream::{wrappers::IntervalStream, StreamExt};
|
||||
|
||||
pub(crate) type SharedBandwidthStorageManager<St> = Arc<RwLock<BandwidthStorageManager<St>>>;
|
||||
const AUTO_REMOVE_AFTER: Duration = Duration::from_secs(60 * 60 * 24); // 24 hours
|
||||
|
||||
pub struct PeerHandle<St> {
|
||||
storage: St,
|
||||
@@ -25,6 +28,7 @@ pub struct PeerHandle<St> {
|
||||
request_tx: mpsc::Sender<PeerControlRequest>,
|
||||
timeout_check_interval: IntervalStream,
|
||||
task_client: TaskClient,
|
||||
startup_timestamp: SystemTime,
|
||||
}
|
||||
|
||||
impl<St: Storage + Clone + 'static> PeerHandle<St> {
|
||||
@@ -39,7 +43,8 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
|
||||
let timeout_check_interval = tokio_stream::wrappers::IntervalStream::new(
|
||||
tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK),
|
||||
);
|
||||
let task_client = task_client.fork(format!("peer{public_key}"));
|
||||
let mut task_client = task_client.fork(format!("peer-{public_key}"));
|
||||
task_client.disarm();
|
||||
PeerHandle {
|
||||
storage,
|
||||
public_key,
|
||||
@@ -48,14 +53,11 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
|
||||
request_tx,
|
||||
timeout_check_interval,
|
||||
task_client,
|
||||
startup_timestamp: SystemTime::now(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn remove_depleted_peer(&self) -> Result<bool, Error> {
|
||||
log::debug!(
|
||||
"Peer {} doesn't have bandwidth anymore, removing it",
|
||||
self.public_key.to_string()
|
||||
);
|
||||
async fn remove_peer(&self) -> Result<bool, Error> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.request_tx
|
||||
.send(PeerControlRequest::RemovePeer {
|
||||
@@ -71,35 +73,44 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
|
||||
Ok(success)
|
||||
}
|
||||
|
||||
async fn active_peer(&mut self, storage_peer: WireguardPeer) -> Result<bool, Error> {
|
||||
let kernel_peer = self
|
||||
.host_information
|
||||
.read()
|
||||
.await
|
||||
.peers
|
||||
.get(&self.public_key)
|
||||
.ok_or(Error::PeerMismatch)?
|
||||
.clone();
|
||||
async fn active_peer(
|
||||
&mut self,
|
||||
storage_peer: WireguardPeer,
|
||||
kernel_peer: Peer,
|
||||
) -> Result<bool, Error> {
|
||||
if let Some(bandwidth_manager) = &self.bandwidth_storage_manager {
|
||||
let spent_bandwidth = (kernel_peer.rx_bytes + kernel_peer.tx_bytes)
|
||||
.checked_sub(storage_peer.rx_bytes as u64 + storage_peer.tx_bytes as u64)
|
||||
.ok_or(Error::InconsistentConsumedBytes)?
|
||||
.try_into()
|
||||
.map_err(|_| Error::InconsistentConsumedBytes)?;
|
||||
if bandwidth_manager
|
||||
.write()
|
||||
.await
|
||||
.try_use_bandwidth(spent_bandwidth)
|
||||
.await
|
||||
.is_err()
|
||||
if spent_bandwidth > 0
|
||||
&& bandwidth_manager
|
||||
.write()
|
||||
.await
|
||||
.try_use_bandwidth(spent_bandwidth)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
let success = self.remove_depleted_peer().await?;
|
||||
let success = self.remove_peer().await?;
|
||||
return Ok(!success);
|
||||
}
|
||||
} else {
|
||||
if SystemTime::now().duration_since(self.startup_timestamp)? >= AUTO_REMOVE_AFTER {
|
||||
log::debug!(
|
||||
"Peer {} has been present for 24 hours, removing it",
|
||||
self.public_key.to_string()
|
||||
);
|
||||
let success = self.remove_peer().await?;
|
||||
return Ok(!success);
|
||||
}
|
||||
let spent_bandwidth = kernel_peer.rx_bytes + kernel_peer.tx_bytes;
|
||||
if spent_bandwidth >= BANDWIDTH_CAP_PER_DAY {
|
||||
let success = self.remove_depleted_peer().await?;
|
||||
log::debug!(
|
||||
"Peer {} doesn't have bandwidth anymore, removing it",
|
||||
self.public_key.to_string()
|
||||
);
|
||||
let success = self.remove_peer().await?;
|
||||
return Ok(!success);
|
||||
}
|
||||
}
|
||||
@@ -111,11 +122,21 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
|
||||
while !self.task_client.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = self.timeout_check_interval.next() => {
|
||||
let Some(peer) = self.storage.get_wireguard_peer(&self.public_key.to_string()).await? else {
|
||||
let Some(kernel_peer) = self
|
||||
.host_information
|
||||
.read()
|
||||
.await
|
||||
.peers
|
||||
.get(&self.public_key)
|
||||
.cloned() else {
|
||||
// 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 {
|
||||
log::debug!("Peer {:?} not in storage anymore, shutting down handle", self.public_key);
|
||||
return Ok(());
|
||||
};
|
||||
if !self.active_peer(peer).await? {
|
||||
if !self.active_peer(storage_peer, kernel_peer).await? {
|
||||
log::debug!("Peer {:?} doesn't have bandwidth anymore, shutting down handle", self.public_key);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "explorer-api"
|
||||
version = "1.1.40"
|
||||
version = "1.1.41"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
|
||||
@@ -73,6 +73,9 @@ pub(crate) enum InitialAuthenticationError {
|
||||
#[error("Only 'Register' or 'Authenticate' requests are allowed")]
|
||||
InvalidRequest,
|
||||
|
||||
#[error("received a Message of type {typ} which was not expected in this context")]
|
||||
UnexpectedMessageType { typ: String },
|
||||
|
||||
#[error("Experienced connection error: {0}")]
|
||||
ConnectionError(#[from] WsError),
|
||||
|
||||
@@ -861,9 +864,27 @@ where
|
||||
Message::Binary(_) => {
|
||||
return Err(InitialAuthenticationError::BinaryRequestWithoutAuthentication);
|
||||
}
|
||||
_ => unreachable!(
|
||||
"the underlying tunsgenite stream should be handling other message types"
|
||||
),
|
||||
other => {
|
||||
if other.is_ping() {
|
||||
debug!("unexpected ping message!");
|
||||
return Err(InitialAuthenticationError::UnexpectedMessageType {
|
||||
typ: "ping".to_string(),
|
||||
});
|
||||
} else if other.is_pong() {
|
||||
debug!("unexpected pong message!");
|
||||
return Err(InitialAuthenticationError::UnexpectedMessageType {
|
||||
typ: "pong".to_string(),
|
||||
});
|
||||
} else if other.is_close() {
|
||||
debug!("unexpected close message!");
|
||||
return Err(InitialAuthenticationError::UnexpectedMessageType {
|
||||
typ: "close".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
// at this point this is definitely unreachable, but just in case, let's not panic...
|
||||
return Err(InitialAuthenticationError::InvalidRequest);
|
||||
}
|
||||
};
|
||||
|
||||
text.parse()
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
FROM rust:latest AS builder
|
||||
|
||||
COPY ./ /usr/src/nym
|
||||
WORKDIR /usr/src/nym/nym-api
|
||||
RUN cargo build --release
|
||||
|
||||
ENTRYPOINT ["/usr/src/nym/nym-api/entrypoint.sh"]
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-api"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.44"
|
||||
version = "1.1.45"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
@@ -18,7 +18,7 @@ bip39 = { workspace = true }
|
||||
bincode.workspace = true
|
||||
bloomfilter = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
clap = { workspace = true, features = ["cargo", "derive", "env"] }
|
||||
console-subscriber = { workspace = true, optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable"
|
||||
dirs = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
/usr/src/nym/target/release/nym-api init && /usr/src/nym/target/release/nym-api run
|
||||
@@ -24,6 +24,9 @@ pub type Result<T, E = EcashError> = std::result::Result<T, E>;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EcashError {
|
||||
#[error("permanently restricted")]
|
||||
Restricted,
|
||||
|
||||
#[error(transparent)]
|
||||
IOError(#[from] std::io::Error),
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ pub enum NymApiStorageError {
|
||||
GatewayNotFound { identity: String },
|
||||
|
||||
// I don't think we want to expose errors to the user about what really happened
|
||||
#[error("experienced internal database error")]
|
||||
#[error("experienced internal database error: {0}")]
|
||||
InternalDatabaseError(#[from] sqlx::Error),
|
||||
|
||||
// the same is true here (also note that the message is subtly different so we would be able to distinguish them)
|
||||
|
||||
@@ -9,7 +9,7 @@ use axum::routing::get;
|
||||
use axum::{Json, Router};
|
||||
use nym_api_requests::models::{
|
||||
AnnotationResponse, NodeDatePerformanceResponse, NodePerformanceResponse, NoiseDetails,
|
||||
NymNodeData, PerformanceHistoryResponse, UptimeHistoryResponse,
|
||||
NymNodeDescription, PerformanceHistoryResponse, UptimeHistoryResponse,
|
||||
};
|
||||
use nym_api_requests::pagination::{PaginatedResponse, Pagination};
|
||||
use nym_contracts_common::NaiveFloat;
|
||||
@@ -125,32 +125,27 @@ async fn get_bonded_nodes(
|
||||
path = "/described",
|
||||
context_path = "/v1/nym-nodes",
|
||||
responses(
|
||||
(status = 200, body = PaginatedResponse<NymNodeData>)
|
||||
(status = 200, body = PaginatedResponse<NymNodeDescription>)
|
||||
),
|
||||
params(PaginationRequest)
|
||||
)]
|
||||
async fn get_described_nodes(
|
||||
State(state): State<AppState>,
|
||||
Query(pagination): Query<PaginationRequest>,
|
||||
) -> AxumResult<Json<PaginatedResponse<NymNodeData>>> {
|
||||
) -> AxumResult<Json<PaginatedResponse<NymNodeDescription>>> {
|
||||
// TODO: implement it
|
||||
let _ = pagination;
|
||||
|
||||
let cache = state.described_nodes_cache.get().await?;
|
||||
let descriptions = cache.all_nodes();
|
||||
|
||||
let data = descriptions
|
||||
.map(|n| &n.description)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
let descriptions = cache.all_nodes().cloned().collect::<Vec<_>>();
|
||||
|
||||
Ok(Json(PaginatedResponse {
|
||||
pagination: Pagination {
|
||||
total: data.len(),
|
||||
total: descriptions.len(),
|
||||
page: 0,
|
||||
size: data.len(),
|
||||
size: descriptions.len(),
|
||||
},
|
||||
data,
|
||||
data: descriptions,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -10,27 +10,33 @@ use std::net::SocketAddr;
|
||||
pub(crate) struct Args {
|
||||
/// Id of the nym-api we want to initialise. if unspecified, a default value will be used.
|
||||
/// default: "default"
|
||||
#[clap(long, default_value = "default")]
|
||||
#[clap(long, default_value = "default", env = "NYMAPI_ID_ARG")]
|
||||
pub(crate) id: String,
|
||||
|
||||
/// Specifies whether network monitoring is enabled on this API
|
||||
/// default: false
|
||||
#[clap(short = 'm', long)]
|
||||
#[clap(short = 'm', long, env = "NYMAPI_ENABLE_MONITOR_ARG")]
|
||||
pub(crate) enable_monitor: bool,
|
||||
|
||||
/// Specifies whether network rewarding is enabled on this API
|
||||
/// default: false
|
||||
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
|
||||
#[clap(
|
||||
short = 'r',
|
||||
long,
|
||||
requires = "enable_monitor",
|
||||
requires = "mnemonic",
|
||||
env = "NYMAPI_ENABLE_REWARDING_ARG"
|
||||
)]
|
||||
pub(crate) enable_rewarding: bool,
|
||||
|
||||
/// Endpoint to nyxd instance used for contract information.
|
||||
/// default: http://localhost:26657
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_NYXD_VALIDATOR_ARG")]
|
||||
pub(crate) nyxd_validator: Option<url::Url>,
|
||||
|
||||
/// Mnemonic of the network monitor used for sending rewarding and zk-nyms transactions
|
||||
/// default: None
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_MNEMONIC_ARG")]
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Flag to indicate whether credential signer authority is enabled on this API
|
||||
@@ -39,18 +45,23 @@ pub(crate) struct Args {
|
||||
long,
|
||||
requires = "mnemonic",
|
||||
requires = "announce_address",
|
||||
alias = "enable_coconut"
|
||||
alias = "enable_coconut",
|
||||
env = "NYMAPI_ENABLE_ZK_NYM_ARG"
|
||||
)]
|
||||
pub(crate) enable_zk_nym: bool,
|
||||
|
||||
/// Announced address that is going to be put in the DKG contract where zk-nym clients will connect
|
||||
/// to obtain their credentials
|
||||
/// default: None
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_ANNOUNCE_ADDRESS_NYM_ARG")]
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
#[clap(long, requires = "enable_monitor")]
|
||||
#[clap(
|
||||
long,
|
||||
requires = "enable_monitor",
|
||||
env = "NYMAPI_MONITOR_CREDENTIALS_MODE_ARG"
|
||||
)]
|
||||
pub(crate) monitor_credentials_mode: bool,
|
||||
|
||||
/// Socket address this api will use for binding its http API.
|
||||
|
||||
@@ -20,11 +20,11 @@ fn pretty_build_info_static() -> &'static str {
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the Nym API.
|
||||
#[clap(short, long)]
|
||||
#[clap(short, long, env = "NYMAPI_CONFIG_ENV_FILE_ARG")]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
/// A no-op flag included for consistency with other binaries (and compatibility with nymvisor, oops)
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_NO_BANNER_ARG")]
|
||||
pub(crate) no_banner: bool,
|
||||
|
||||
#[clap(subcommand)]
|
||||
|
||||
@@ -44,27 +44,33 @@ use tracing::{error, info};
|
||||
pub(crate) struct Args {
|
||||
/// Id of the nym-api we want to run.if unspecified, a default value will be used.
|
||||
/// default: "default"
|
||||
#[clap(long, default_value = "default")]
|
||||
#[clap(long, default_value = "default", env = "NYMAPI_ID_ARG")]
|
||||
pub(crate) id: String,
|
||||
|
||||
/// Specifies whether network monitoring is enabled on this API
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(short = 'm', long)]
|
||||
#[clap(short = 'm', long, env = "NYMAPI_ENABLE_MONITOR_ARG")]
|
||||
pub(crate) enable_monitor: Option<bool>,
|
||||
|
||||
/// Specifies whether network rewarding is enabled on this API
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(short = 'r', long, requires = "enable_monitor", requires = "mnemonic")]
|
||||
#[clap(
|
||||
short = 'r',
|
||||
long,
|
||||
requires = "enable_monitor",
|
||||
requires = "mnemonic",
|
||||
env = "NYMAPI_ENABLE_REWARDING_ARG"
|
||||
)]
|
||||
pub(crate) enable_rewarding: Option<bool>,
|
||||
|
||||
/// Endpoint to nyxd instance used for contract information.
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_NYXD_VALIDATOR_ARG")]
|
||||
pub(crate) nyxd_validator: Option<url::Url>,
|
||||
|
||||
/// Mnemonic of the network monitor used for sending rewarding and zk-nyms transactions
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_MNEMONIC_ARG")]
|
||||
pub(crate) mnemonic: Option<bip39::Mnemonic>,
|
||||
|
||||
/// Flag to indicate whether coconut signer authority is enabled on this API
|
||||
@@ -73,19 +79,20 @@ pub(crate) struct Args {
|
||||
long,
|
||||
requires = "mnemonic",
|
||||
requires = "announce_address",
|
||||
alias = "enable_coconut"
|
||||
alias = "enable_coconut",
|
||||
env = "NYMAPI_ENABLE_ZK_NYM_ARG"
|
||||
)]
|
||||
pub(crate) enable_zk_nym: Option<bool>,
|
||||
|
||||
/// Announced address that is going to be put in the DKG contract where zk-nym clients will connect
|
||||
/// to obtain their credentials
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_ANNOUNCE_ADDRESS_ARG")]
|
||||
pub(crate) announce_address: Option<url::Url>,
|
||||
|
||||
/// Set this nym api to work in a enabled credentials that would attempt to use gateway with the bandwidth credential requirement
|
||||
/// default: None - config value will be used instead
|
||||
#[clap(long)]
|
||||
#[clap(long, env = "NYMAPI_MONITOR_CREDENTIALS_MODE_ARG")]
|
||||
pub(crate) monitor_credentials_mode: Option<bool>,
|
||||
|
||||
/// Socket address this api will use for binding its http API.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-credential-proxy"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -26,6 +26,8 @@ RUN cargo build --release
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -yy curl ca-certificates
|
||||
|
||||
WORKDIR /nym
|
||||
|
||||
COPY --from=builder /usr/src/nym/nym-credential-proxy/target/release/nym-credential-proxy ./
|
||||
|
||||
@@ -7,11 +7,7 @@ RUN cargo build --release
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \
|
||||
echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \
|
||||
echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom
|
||||
|
||||
RUN apt update && apt install -yy curl
|
||||
RUN apt update && apt install -yy curl ca-certificates
|
||||
|
||||
WORKDIR /nym
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
|
||||
use anyhow::Result;
|
||||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use log::{debug, info};
|
||||
use nym_sphinx::chunking::{SentFragment, FRAGMENTS_RECEIVED, FRAGMENTS_SENT};
|
||||
use nym_sphinx::chunking::{monitoring, SentFragment};
|
||||
use nym_topology::{gateway, mix, NymTopology};
|
||||
use nym_types::monitoring::{MonitorMessage, NodeResult};
|
||||
use nym_validator_client::nym_api::routes::{API_VERSION, STATUS, SUBMIT_GATEWAY, SUBMIT_NODE};
|
||||
@@ -115,8 +115,8 @@ impl NetworkAccount {
|
||||
}
|
||||
|
||||
pub fn empty_buffers() {
|
||||
FRAGMENTS_SENT.clear();
|
||||
FRAGMENTS_RECEIVED.clear();
|
||||
monitoring::FRAGMENTS_SENT.clear();
|
||||
monitoring::FRAGMENTS_RECEIVED.clear();
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
@@ -125,7 +125,7 @@ impl NetworkAccount {
|
||||
topology,
|
||||
..Default::default()
|
||||
};
|
||||
for fragment_set in FRAGMENTS_SENT.iter() {
|
||||
for fragment_set in monitoring::FRAGMENTS_SENT.iter() {
|
||||
let sent_fragments = fragment_set
|
||||
.value()
|
||||
.first()
|
||||
@@ -138,7 +138,7 @@ impl NetworkAccount {
|
||||
sent_fragments
|
||||
);
|
||||
|
||||
let recv = FRAGMENTS_RECEIVED.get(fragment_set.key());
|
||||
let recv = monitoring::FRAGMENTS_RECEIVED.get(fragment_set.key());
|
||||
let recv_fragments = recv.as_ref().map(|r| r.value().len()).unwrap_or(0);
|
||||
debug!(
|
||||
"RECV Fragment set {} has {} fragments",
|
||||
@@ -170,7 +170,7 @@ impl NetworkAccount {
|
||||
}
|
||||
|
||||
fn hydrate_all_fragments(&mut self) -> Result<()> {
|
||||
for fragment_set in FRAGMENTS_SENT.iter() {
|
||||
for fragment_set in monitoring::FRAGMENTS_SENT.iter() {
|
||||
let fragment_set_id = fragment_set.key();
|
||||
for fragment in fragment_set.value() {
|
||||
let route = self.hydrate_route(fragment.clone())?;
|
||||
@@ -205,7 +205,7 @@ impl NetworkAccount {
|
||||
fn find_missing_fragments(&mut self) {
|
||||
let mut missing_fragments_map = HashMap::new();
|
||||
for fragment_set_id in &self.incomplete_fragment_sets {
|
||||
if let Some(fragment_ref) = FRAGMENTS_RECEIVED.get(fragment_set_id) {
|
||||
if let Some(fragment_ref) = monitoring::FRAGMENTS_RECEIVED.get(fragment_set_id) {
|
||||
if let Some(ref_fragment) = fragment_ref.value().first() {
|
||||
let ref_header = ref_fragment.header();
|
||||
let ref_id_set = (0..ref_header.total_fragments()).collect::<HashSet<u8>>();
|
||||
|
||||
@@ -6,7 +6,7 @@ use axum::{
|
||||
use futures::StreamExt;
|
||||
use log::{debug, error, warn};
|
||||
use nym_sdk::mixnet::MixnetMessageSender;
|
||||
use nym_sphinx::chunking::{ReceivedFragment, SentFragment, FRAGMENTS_RECEIVED, FRAGMENTS_SENT};
|
||||
use nym_sphinx::chunking::{monitoring, ReceivedFragment, SentFragment};
|
||||
use petgraph::{dot::Dot, Graph};
|
||||
use rand::{distributions::Alphanumeric, seq::SliceRandom, Rng};
|
||||
use serde::Serialize;
|
||||
@@ -113,7 +113,7 @@ pub async fn graph_handler() -> Result<String, StatusCode> {
|
||||
)]
|
||||
pub async fn sent_handler() -> Json<FragmentsSent> {
|
||||
Json(FragmentsSent(
|
||||
(*FRAGMENTS_SENT)
|
||||
(*monitoring::FRAGMENTS_SENT)
|
||||
.clone()
|
||||
.into_iter()
|
||||
.collect::<HashMap<_, _>>(),
|
||||
@@ -129,7 +129,7 @@ pub async fn sent_handler() -> Json<FragmentsSent> {
|
||||
)]
|
||||
pub async fn recv_handler() -> Json<FragmentsReceived> {
|
||||
Json(FragmentsReceived(
|
||||
(*FRAGMENTS_RECEIVED)
|
||||
(*monitoring::FRAGMENTS_RECEIVED)
|
||||
.clone()
|
||||
.into_iter()
|
||||
.collect::<HashMap<_, _>>(),
|
||||
|
||||
@@ -7,6 +7,7 @@ use nym_crypto::asymmetric::ed25519::PrivateKey;
|
||||
use nym_network_defaults::setup_env;
|
||||
use nym_network_defaults::var_names::NYM_API;
|
||||
use nym_sdk::mixnet::{self, MixnetClient};
|
||||
use nym_sphinx::chunking::monitoring;
|
||||
use nym_topology::{HardcodedTopologyProvider, NymTopology};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
@@ -154,6 +155,9 @@ async fn main() -> Result<()> {
|
||||
|
||||
setup_env(args.env); // Defaults to mainnet if empty
|
||||
|
||||
// enable monitoring client-side
|
||||
monitoring::enable();
|
||||
|
||||
let cancel_token = CancellationToken::new();
|
||||
let server_cancel_token = cancel_token.clone();
|
||||
let clients = Arc::new(RwLock::new(VecDeque::with_capacity(args.n_clients)));
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
FROM rust:latest AS builder
|
||||
|
||||
COPY ./ /usr/src/nym
|
||||
WORKDIR /usr/src/nym/nym-node
|
||||
|
||||
RUN cargo build --release
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
WORKDIR /nym
|
||||
|
||||
COPY --from=builder /usr/src/nym/target/release/nym-node ./
|
||||
ENTRYPOINT [ "/nym/nym-node" ]
|
||||
@@ -27,9 +27,9 @@ impl DummyHandler {
|
||||
msg = self.peer_rx.recv() => {
|
||||
if let Some(msg) = msg {
|
||||
match msg {
|
||||
PeerControlRequest::AddPeer { peer, ticket_validation, response_tx } => {
|
||||
log::info!("[DUMMY] Adding peer {:?} with ticket validation {}", peer, ticket_validation);
|
||||
response_tx.send(AddPeerControlResponse { success: true, client_id: None }).ok();
|
||||
PeerControlRequest::AddPeer { peer, client_id, response_tx } => {
|
||||
log::info!("[DUMMY] Adding peer {:?} with client id {:?}", peer, client_id);
|
||||
response_tx.send(AddPeerControlResponse { success: true }).ok();
|
||||
}
|
||||
PeerControlRequest::RemovePeer { key, response_tx } => {
|
||||
log::info!("[DUMMY] Removing peer {:?}", key);
|
||||
|
||||
@@ -7,8 +7,9 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{error::AuthenticatorError, peer_manager::PeerManager};
|
||||
use defguard_wireguard_rs::net::IpAddrMask;
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key};
|
||||
use futures::StreamExt;
|
||||
use log::warn;
|
||||
use nym_authenticator_requests::{
|
||||
v1, v2,
|
||||
v3::{
|
||||
@@ -121,10 +122,17 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
reg.gateway_data.private_ip
|
||||
)))?;
|
||||
|
||||
let timestamp = ip.ok_or(AuthenticatorError::InternalDataCorruption(
|
||||
"timestamp should be set".to_string(),
|
||||
))?;
|
||||
let duration = SystemTime::now().duration_since(timestamp).map_err(|_| {
|
||||
let Some(timestamp) = ip else {
|
||||
registred_and_free
|
||||
.registration_in_progres
|
||||
.remove(®.gateway_data.pub_key());
|
||||
log::debug!(
|
||||
"Removed stale registration of {}",
|
||||
reg.gateway_data.pub_key()
|
||||
);
|
||||
continue;
|
||||
};
|
||||
let duration = SystemTime::now().duration_since(*timestamp).map_err(|_| {
|
||||
AuthenticatorError::InternalDataCorruption(
|
||||
"set timestamp shouldn't have been set in the future".to_string(),
|
||||
)
|
||||
@@ -151,10 +159,8 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
) -> AuthenticatorHandleResult {
|
||||
let remote_public = init_message.pub_key;
|
||||
let nonce: u64 = fastrand::u64(..);
|
||||
if let Some(registration_data) = self
|
||||
.registred_and_free
|
||||
.read()
|
||||
.await
|
||||
let mut registred_and_free = self.registred_and_free.write().await;
|
||||
if let Some(registration_data) = registred_and_free
|
||||
.registration_in_progres
|
||||
.get(&remote_public)
|
||||
{
|
||||
@@ -183,7 +189,6 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
));
|
||||
}
|
||||
|
||||
let mut registred_and_free = self.registred_and_free.write().await;
|
||||
let private_ip_ref = registred_and_free
|
||||
.free_private_network_ips
|
||||
.iter_mut()
|
||||
@@ -235,38 +240,42 @@ impl<S: Storage + Clone + 'static> MixnetListener<S> {
|
||||
return Err(AuthenticatorError::MacVerificationFailure);
|
||||
}
|
||||
|
||||
let mut peer = Peer::new(Key::new(final_message.gateway_client.pub_key.to_bytes()));
|
||||
peer.allowed_ips
|
||||
.push(IpAddrMask::new(final_message.gateway_client.private_ip, 32));
|
||||
|
||||
// If gateway does ecash verification and client sends a credential, we do the additional
|
||||
// credential verification. Later this will become mandatory.
|
||||
if let (Some(ecash_verifier), Some(credential)) = (
|
||||
self.ecash_verifier.clone(),
|
||||
final_message.credential.clone(),
|
||||
) {
|
||||
let client_id = self
|
||||
.peer_manager
|
||||
.add_peer(&final_message.gateway_client, true)
|
||||
let client_id = ecash_verifier
|
||||
.storage()
|
||||
.insert_wireguard_peer(&peer, true)
|
||||
.await?
|
||||
.ok_or(AuthenticatorError::InternalError(
|
||||
"peer with ticket shouldn't have been used before without a ticket".to_string(),
|
||||
))?;
|
||||
|
||||
if let Err(e) =
|
||||
Self::credential_verification(ecash_verifier, credential, client_id).await
|
||||
Self::credential_verification(ecash_verifier.clone(), credential, client_id).await
|
||||
{
|
||||
self.peer_manager
|
||||
.remove_peer(&final_message.gateway_client)
|
||||
.await
|
||||
.inspect_err(|err| {
|
||||
warn!(
|
||||
"Could not revert adding peer {} on credential verification {err}",
|
||||
final_message.gateway_client.pub_key()
|
||||
)
|
||||
})?;
|
||||
ecash_verifier
|
||||
.storage()
|
||||
.remove_wireguard_peer(&peer.public_key.to_string())
|
||||
.await?;
|
||||
return Err(e);
|
||||
}
|
||||
let public_key = peer.public_key.to_string();
|
||||
if let Err(e) = self.peer_manager.add_peer(peer, Some(client_id)).await {
|
||||
ecash_verifier
|
||||
.storage()
|
||||
.remove_wireguard_peer(&public_key)
|
||||
.await?;
|
||||
return Err(e);
|
||||
}
|
||||
} else {
|
||||
self.peer_manager
|
||||
.add_peer(&final_message.gateway_client, false)
|
||||
.await?;
|
||||
self.peer_manager.add_peer(peer, None).await?;
|
||||
}
|
||||
registred_and_free
|
||||
.registration_in_progres
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::*;
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask};
|
||||
use defguard_wireguard_rs::{host::Peer, key::Key};
|
||||
use futures::channel::oneshot;
|
||||
use nym_authenticator_requests::latest::registration::{GatewayClient, RemainingBandwidthData};
|
||||
use nym_wireguard::{
|
||||
@@ -24,18 +24,11 @@ impl PeerManager {
|
||||
wireguard_gateway_data,
|
||||
}
|
||||
}
|
||||
pub async fn add_peer(
|
||||
&mut self,
|
||||
client: &GatewayClient,
|
||||
ticket_validation: bool,
|
||||
) -> Result<Option<i64>> {
|
||||
let mut peer = Peer::new(Key::new(client.pub_key.to_bytes()));
|
||||
pub async fn add_peer(&mut self, peer: Peer, client_id: Option<i64>) -> Result<()> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
peer.allowed_ips
|
||||
.push(IpAddrMask::new(client.private_ip, 32));
|
||||
let msg = PeerControlRequest::AddPeer {
|
||||
peer,
|
||||
ticket_validation,
|
||||
client_id,
|
||||
response_tx,
|
||||
};
|
||||
self.wireguard_gateway_data
|
||||
@@ -44,7 +37,7 @@ impl PeerManager {
|
||||
.await
|
||||
.map_err(|_| AuthenticatorError::PeerInteractionStopped)?;
|
||||
|
||||
let AddPeerControlResponse { success, client_id } = response_rx.await.map_err(|_| {
|
||||
let AddPeerControlResponse { success } = response_rx.await.map_err(|_| {
|
||||
AuthenticatorError::InternalError("no response for add peer".to_string())
|
||||
})?;
|
||||
if !success {
|
||||
@@ -52,10 +45,10 @@ impl PeerManager {
|
||||
"adding peer could not be performed".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(client_id)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_peer(&mut self, client: &GatewayClient) -> Result<()> {
|
||||
pub async fn _remove_peer(&mut self, client: &GatewayClient) -> Result<()> {
|
||||
let key = Key::new(client.pub_key().to_bytes());
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
let msg = PeerControlRequest::RemovePeer { key, response_tx };
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "nym-network-requester"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.42"
|
||||
version = "1.1.43"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version = "1.70"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-cli"
|
||||
version = "1.1.42"
|
||||
version = "1.1.43"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nymvisor"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user