Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a75e99d59f | |||
| f6f7d3b175 | |||
| 3d2914b3e5 | |||
| 9b02de3e75 | |||
| f3d8aba82c | |||
| 72a4a26c40 | |||
| 5d9b5a0d70 | |||
| c070e4bfee | |||
| 8d5a41a790 | |||
| 039b05cf7e | |||
| 37b10b59aa | |||
| a9ede22bbd | |||
| b656003306 |
@@ -9,15 +9,16 @@ on:
|
||||
- 'gateway/**'
|
||||
- 'integrations/**'
|
||||
- 'mixnode/**'
|
||||
- 'sdk/rust/**'
|
||||
- 'sdk/lib/**'
|
||||
- 'service-providers/**'
|
||||
- 'nym-network-monitor/**'
|
||||
- 'nym-api/**'
|
||||
- 'nym-node/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'nym-data-observatory/**'
|
||||
- 'nym-network-monitor/**'
|
||||
- 'nym-node/**'
|
||||
- 'nym-node-status-api/**'
|
||||
- 'nym-outfox/**'
|
||||
- 'nym-validator-rewarder/**'
|
||||
- 'sdk/lib/**'
|
||||
- 'sdk/rust/**'
|
||||
- 'service-providers/**'
|
||||
- 'tools/**'
|
||||
- 'wasm/**'
|
||||
- 'Cargo.toml'
|
||||
|
||||
@@ -4,6 +4,11 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2024.14-crunch-patched] (2024-12-17)
|
||||
|
||||
- Fixes an issue to allow previously registred clients to connect to latest nym-nodes
|
||||
- Fixes compatibility issues between nym-nodes and older clients
|
||||
|
||||
## [2024.14-crunch] (2024-12-11)
|
||||
|
||||
- Merge/release/2024.14-crunch ([#5242])
|
||||
|
||||
Generated
+601
-257
File diff suppressed because it is too large
Load Diff
+25
-25
@@ -193,9 +193,9 @@ aes = "0.8.1"
|
||||
aes-gcm = "0.10.1"
|
||||
aes-gcm-siv = "0.11.1"
|
||||
aead = "0.5.2"
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
argon2 = "0.5.0"
|
||||
async-trait = "0.1.83"
|
||||
async-trait = "0.1.84"
|
||||
axum-client-ip = "0.6.1"
|
||||
axum = "0.7.5"
|
||||
axum-extra = "0.9.4"
|
||||
@@ -204,7 +204,7 @@ bincode = "1.3.3"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
bit-vec = "0.7.0" # can we unify those?
|
||||
bitvec = "1.0.0"
|
||||
blake3 = "1.5.4"
|
||||
blake3 = "1.5.5"
|
||||
bloomfilter = "1.0.14"
|
||||
bs58 = "0.5.1"
|
||||
bytecodec = "0.4.15"
|
||||
@@ -214,20 +214,20 @@ celes = "2.4.0"
|
||||
cfg-if = "1.0.0"
|
||||
chacha20 = "0.9.0"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
chrono = "0.4.31"
|
||||
chrono = "0.4.39"
|
||||
cipher = "0.4.3"
|
||||
clap = "4.5.20"
|
||||
clap = "4.5.23"
|
||||
clap_complete = "4.5"
|
||||
clap_complete_fig = "4.5"
|
||||
colored = "2.0"
|
||||
comfy-table = "7.1.1"
|
||||
console = "0.15.8"
|
||||
comfy-table = "7.1.3"
|
||||
console = "0.15.10"
|
||||
console-subscriber = "0.1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
const-str = "0.5.6"
|
||||
const_format = "0.2.33"
|
||||
const_format = "0.2.34"
|
||||
criterion = "0.4"
|
||||
csv = "1.3.0"
|
||||
csv = "1.3.1"
|
||||
ctr = "0.9.1"
|
||||
cupid = "0.6.1"
|
||||
curve25519-dalek = "4.1"
|
||||
@@ -244,7 +244,7 @@ etherparse = "0.13.0"
|
||||
envy = "0.4"
|
||||
eyre = "0.6.9"
|
||||
fastrand = "2.1.1"
|
||||
flate2 = "1.0.34"
|
||||
flate2 = "1.0.35"
|
||||
futures = "0.3.28"
|
||||
futures-util = "0.3"
|
||||
generic-array = "0.14.7"
|
||||
@@ -264,7 +264,7 @@ humantime-serde = "1.1.1"
|
||||
human-repr = "1.1.0"
|
||||
hyper = "1.4.1"
|
||||
hyper-util = "0.1"
|
||||
indicatif = "0.17.8"
|
||||
indicatif = "0.17.9"
|
||||
inquire = "0.6.2"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.20"
|
||||
@@ -289,7 +289,7 @@ parking_lot = "0.12.3"
|
||||
pem = "0.8"
|
||||
petgraph = "0.6.5"
|
||||
pin-project = "1.1"
|
||||
pin-project-lite = "0.2.14"
|
||||
pin-project-lite = "0.2.15"
|
||||
pretty_env_logger = "0.4.0"
|
||||
publicsuffix = "2.2.3"
|
||||
quote = "1"
|
||||
@@ -307,11 +307,11 @@ rocket_cors = "0.6.0"
|
||||
rocket_okapi = "0.8.0"
|
||||
safer-ffi = "0.1.13"
|
||||
schemars = "0.8.21"
|
||||
semver = "1.0.23"
|
||||
serde = "1.0.211"
|
||||
semver = "1.0.24"
|
||||
serde = "1.0.217"
|
||||
serde_bytes = "0.11.15"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.132"
|
||||
serde_json = "1.0.134"
|
||||
serde_json_path = "0.7.1"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.9.0"
|
||||
@@ -326,22 +326,22 @@ subtle-encoding = "0.5"
|
||||
syn = "1"
|
||||
sysinfo = "0.30.13"
|
||||
tap = "1.0.1"
|
||||
tar = "0.4.42"
|
||||
tar = "0.4.43"
|
||||
tempfile = "3.14"
|
||||
thiserror = "1.0.64"
|
||||
time = "0.3.30"
|
||||
time = "0.3.37"
|
||||
tokio = "1.39"
|
||||
tokio-stream = "0.1.16"
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-test = "0.4.4"
|
||||
tokio-tun = "0.11.5"
|
||||
tokio-tungstenite = { version = "0.20.1" }
|
||||
tokio-util = "0.7.12"
|
||||
toml = "0.8.14"
|
||||
tokio-util = "0.7.13"
|
||||
toml = "0.8.19"
|
||||
tower = "0.4.13"
|
||||
tower-http = "0.5.2"
|
||||
tracing = "0.1.37"
|
||||
tracing = "0.1.41"
|
||||
tracing-opentelemetry = "0.19.0"
|
||||
tracing-subscriber = "0.3.16"
|
||||
tracing-subscriber = "0.3.19"
|
||||
tracing-tree = "0.2.2"
|
||||
tracing-log = "0.2"
|
||||
ts-rs = "10.0.0"
|
||||
@@ -353,7 +353,7 @@ utoipauto = "0.2"
|
||||
uuid = "*"
|
||||
vergen = { version = "=8.3.1", default-features = false }
|
||||
walkdir = "2"
|
||||
wasm-bindgen-test = "0.3.43"
|
||||
wasm-bindgen-test = "0.3.45"
|
||||
x25519-dalek = "2.0.0"
|
||||
zeroize = "1.6.0"
|
||||
|
||||
@@ -402,11 +402,11 @@ gloo-net = "0.5.0"
|
||||
# this is blocked until the upstream removes outdates `wasm_bindgen` feature usage
|
||||
# indexed_db_futures = "0.4.1"
|
||||
indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" }
|
||||
js-sys = "0.3.70"
|
||||
js-sys = "0.3.76"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
tsify = "0.4.5"
|
||||
wasm-bindgen = "0.2.99"
|
||||
wasm-bindgen-futures = "0.4.45"
|
||||
wasm-bindgen-futures = "0.4.49"
|
||||
wasmtimer = "0.2.0"
|
||||
web-sys = "0.3.72"
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ pub mod error;
|
||||
mod manager;
|
||||
mod models;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OnDiskGatewaysDetails {
|
||||
manager: StorageManager,
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ pub enum InMemStorageError {
|
||||
MalformedGateway(#[from] BadGateway),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct InMemGatewaysDetails {
|
||||
inner: Arc<RwLock<InMemStorageInner>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct InMemStorageInner {
|
||||
active_gateway: Option<String>,
|
||||
gateways: HashMap<String, GatewayRegistration>,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// TODO: combine those more closely. Perhaps into a single underlying store.
|
||||
// Like for persistent, on-disk, storage, what's the point of having 3 different databases?
|
||||
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use crate::client::key_manager::persistence::{InMemEphemeralKeys, KeyStore};
|
||||
use crate::client::replies::reply_storage;
|
||||
use crate::client::replies::reply_storage::ReplyStorageBackend;
|
||||
@@ -63,7 +65,7 @@ pub trait MixnetClientStorage {
|
||||
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Clone)]
|
||||
pub struct Ephemeral {
|
||||
key_store: InMemEphemeralKeys,
|
||||
reply_store: reply_storage::Empty,
|
||||
@@ -71,9 +73,14 @@ pub struct Ephemeral {
|
||||
gateway_details_store: InMemGatewaysDetails,
|
||||
}
|
||||
|
||||
impl Ephemeral {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
impl Default for Ephemeral {
|
||||
fn default() -> Self {
|
||||
Ephemeral {
|
||||
key_store: InMemEphemeralKeys::new(&mut OsRng),
|
||||
reply_store: Default::default(),
|
||||
credential_store: Default::default(),
|
||||
gateway_details_store: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +121,7 @@ impl MixnetClientStorage for Ephemeral {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "fs-surb-storage",
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
use crate::client::key_manager::ClientKeys;
|
||||
use async_trait::async_trait;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@@ -64,6 +66,7 @@ pub enum OnDiskKeysError {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub struct OnDiskKeys {
|
||||
paths: ClientKeysPaths,
|
||||
@@ -193,9 +196,20 @@ impl KeyStore for OnDiskKeys {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Clone)]
|
||||
pub struct InMemEphemeralKeys {
|
||||
keys: Mutex<Option<ClientKeys>>,
|
||||
keys: Arc<Mutex<ClientKeys>>,
|
||||
}
|
||||
|
||||
impl InMemEphemeralKeys {
|
||||
pub fn new<R>(rng: &mut R) -> Self
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
InMemEphemeralKeys {
|
||||
keys: Arc::new(Mutex::new(ClientKeys::generate_new(rng))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
@@ -208,11 +222,11 @@ impl KeyStore for InMemEphemeralKeys {
|
||||
type StorageError = EphemeralKeysError;
|
||||
|
||||
async fn load_keys(&self) -> Result<ClientKeys, Self::StorageError> {
|
||||
self.keys.lock().await.clone().ok_or(EphemeralKeysError)
|
||||
Ok(self.keys.lock().await.clone())
|
||||
}
|
||||
|
||||
async fn store_keys(&self, keys: &ClientKeys) -> Result<(), Self::StorageError> {
|
||||
*self.keys.lock().await = Some(keys.clone());
|
||||
*self.keys.lock().await = keys.clone();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ mod error;
|
||||
mod manager;
|
||||
mod models;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Backend {
|
||||
temporary_old_path: Option<PathBuf>,
|
||||
database_path: PathBuf,
|
||||
|
||||
@@ -19,7 +19,7 @@ pub mod fs_backend;
|
||||
#[error("no information provided")]
|
||||
pub struct UndefinedError;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Empty {
|
||||
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
|
||||
pub min_surb_threshold: usize,
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::error::Error;
|
||||
// `SELECT total_tickets, used_tickets FROM ecash_ticketbook WHERE expiration_date >= ?`, today_date
|
||||
// then for each calculate the diff total_tickets - used_tickets and multiply the result by the size of the ticket
|
||||
#[async_trait]
|
||||
pub trait Storage: Send + Sync {
|
||||
pub trait Storage: Clone + Send + Sync {
|
||||
type StorageError: Error;
|
||||
|
||||
async fn close(&self);
|
||||
|
||||
@@ -9,5 +9,5 @@ edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.11.3"
|
||||
env_logger = "0.11.6"
|
||||
log.workspace = true
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { MyTab } from 'components/generic-tabs.tsx';
|
||||
import { Tabs } from 'nextra/components';
|
||||
|
||||
### VPS Hardware Specs
|
||||
|
||||
You will need to rent a VPS to run your node on. One key reason for this is that your node **must be able to send TCP data using both IPv4 and IPv6** (as other nodes you talk to may use either protocol). Therefore you will need a server with static IPv4 and IPv6!
|
||||
|
||||
Tor community created a very helpful table called [*Good Bad ISPs*](https://community.torproject.org/relay/community-resources/good-bad-isps/), you can use that one as a guideline for your choice of ISP for your VPS.
|
||||
|
||||
**Update:** Nym community started an ISP table called [*Where to host your nym node?*](../../community-counsel/isp-list.mdx), check it out and add your findings!
|
||||
|
||||
<div>
|
||||
<Tabs items={[
|
||||
<code>nym-node</code>,
|
||||
<code>validator</code>,
|
||||
]} defaultIndex="0">
|
||||
<MyTab>
|
||||
#### `nym-node`
|
||||
Before we conclude the testing with exact results, these are the rough specs:
|
||||
|
||||
| **Hardware** | **Minimum Specification** |
|
||||
| :--- | ---: |
|
||||
| CPU Cores | 4 |
|
||||
| Memory | 8 GB RAM |
|
||||
| Storage | 80 GB |
|
||||
| Connectivity | IPv4, IPv6, TCP/IP, UDP |
|
||||
| Bandwidth | > 1Tb |
|
||||
| Port speed | 1Gbps |
|
||||
|
||||
</MyTab>
|
||||
<MyTab>
|
||||
#### Nyx validator
|
||||
|
||||
The specification mentioned below is for running a full node alongside the nym-api. It is recommended to run `nym-api` and a full Nyx node on the same machine for optimum performance.
|
||||
|
||||
Bear in mind that credential signing is primarily CPU-bound, so choose the fastest CPU available to you.
|
||||
|
||||
##### Minimum Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|--------------------------------------------|
|
||||
| CPU | 8-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 16GB DDR4+ |
|
||||
| Disk | 500 GiB+ NVMe SSD |
|
||||
|
||||
##### Recommended Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|---------------------------------------------|
|
||||
| CPU | 16-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 32GB DDR4+ |
|
||||
| Disk | 1 TiB+ NVMe SSD |
|
||||
|
||||
</MyTab>
|
||||
</Tabs>
|
||||
</div>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
804_560_131
|
||||
805_903_308
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1_020_023
|
||||
1_022_821
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
402_280_065
|
||||
402_951_654
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
| **Item** | **Description** | **Amount in NYM** |
|
||||
|:-------------------|:------------------------------------------------------|--------------------:|
|
||||
| Total Supply | Maximum amount of NYM token in existence | 1_000_000_000 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 195_439_368 |
|
||||
| Mixmining Reserve | Tokens releasing for operators rewards | 194_096_191 |
|
||||
| Vesting Tokens | Tokens locked outside of cicrulation for future claim | 500 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 804_560_131 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 1_020_023 |
|
||||
| Circulating Supply | Amount of unlocked tokens | 805_903_308 |
|
||||
| Stake Saturation | Optimal size of node self-bond + delegation | 1_022_821 |
|
||||
|
||||
@@ -1 +1 @@
|
||||
Monday, December 23rd 2024, 11:36:26 UTC
|
||||
Monday, January 6th 2025, 11:03:09 UTC
|
||||
|
||||
@@ -45,7 +45,7 @@ make
|
||||
```
|
||||
|
||||
## Mnemonic Generation
|
||||
Create an account at [nymvpn.com](nymvpn.com) to obtain your mnemonic.
|
||||
Create an account at [nymvpn.com](https://nymvpn.com) to obtain your mnemonic.
|
||||
|
||||
## Start the daemon
|
||||
```sh
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This is **Nym's Operators guide**, containing information and setup guides for the various components of Nym network and Nyx blockchain validators.
|
||||
|
||||
Nym network (also known as mixnet) routes and mixes packets through Gateways and Mixnodes, all run from the same binary called `nym-node`.
|
||||
Nym network (also known as Nym mixnet) routes and mixes packets through Gateways and Mixnodes, all run from the same binary called `nym-node`.
|
||||
|
||||
```ascii
|
||||
┌─►mix──┐ mix mix
|
||||
@@ -14,10 +14,13 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───►
|
||||
mix └─►mix──┘ mix
|
||||
```
|
||||
|
||||
If you are new to Nym and want to learn about the Mixnet, explore kickstart options and demos, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/docs/developers/).
|
||||
If you want to dive deeper into Nym Network architecture, clients and nodes visit the [Network docs](https://nymtech.net/docs/network).
|
||||
|
||||
If you want to dive deeper into Nym's architecture, clients, nodes, and SDK examples visit the [technical docs](https://nymtech.net/docs/network).
|
||||
If you want to explore kickstart options and examples, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/docs/developers/).
|
||||
|
||||
## Minimum Requirements
|
||||
|
||||
**If you are an operator and want to join the journey of starting and mantaining a Nym Node, begin with visiting [Minimum requirements page](nodes.mdx).**
|
||||
|
||||
## Popular pages
|
||||
|
||||
@@ -52,4 +55,4 @@ If you want to dive deeper into Nym's architecture, clients, nodes, and SDK exam
|
||||
|
||||
**Archive**
|
||||
|
||||
*[FAQ: Project Smoosh](archive/faq/smoosh-faq.mdx)
|
||||
* [FAQ: Project Smoosh](archive/faq/smoosh-faq.mdx)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Callout } from 'nextra/components';
|
||||
import { Steps } from 'nextra/components';
|
||||
import { Tabs } from 'nextra/components';
|
||||
import NymNodeSpecs from 'components/operators/snippets/nym-node-specs.mdx';
|
||||
|
||||
# Nym Nodes Operator Guides
|
||||
|
||||
Welcome to the section containing setup guides for operators of Nym Nodes and Nym Validators. To setup, configure, run, bond and maintain a `nym-node` is not a difficult process, but it takes dedication. Before you start, please check out [minimum requirements](#minimum-requirements) and then follow the [Steps for Nym Node Operators](#steps-for-nym-node-operators) below.
|
||||
|
||||
## Minimum Requirements
|
||||
|
||||
Operating a `nym-node` is not a set-and-forget endeavor. To prevent operators committing their time and money into a sub-optimal server, resulting in frustration of never seeing their node active, we composed this list of prerequisites. Please read below about expectations regarding operators [skill set](#knowledge-base), [time dedication](#time) and [minimum hardware specs](#vps-hardware-specs).
|
||||
|
||||
### Knowledge base
|
||||
|
||||
**All nodes are run remotely from operators shell, using [SSH](https://www.ssh.com/academy/ssh) and [Bash](https://www.gnu.org/software/bash/) commands. Node operators need to be experienced super users or sys-admins.** If you never used terminal before, maybe start with some tutorial of [basic Linux administration](https://www.linode.com/docs/guides/linux-system-administration-basics/) before committing to run a node.
|
||||
|
||||
<NymNodeSpecs />
|
||||
|
||||
### Time
|
||||
|
||||
Last but not least, managing a Nym Node is work. More skilled an operator is, less time it takes to run and maintain a node (and search extra details), but just like any other work, it takes effort.
|
||||
|
||||
Reserve 45-120 minutes for the initial setup and configuration (depends on your skills). Then count on a few minutes once in 2-4 weeks to upgrade node version binaries. Patches don't always come out [regularly](release-cycle.mdx), operators need to keep their eyes on [Matrix announcement channel](https://matrix.to/#/#node-ops-announcements:nymtech.chat).
|
||||
|
||||
Outdated nodes are never selected for routing/mixing packets, resulting in not receiving any rewards. You can read more on our [Tokenomics page](tokenomics/mixnet-rewards.mdx) to understand the selection and rewards logic.
|
||||
|
||||
## Steps for Nym Node Operators
|
||||
|
||||
This is a summary of all needed steps for node operators to setup and configure a `nym-node` and register it to Nym Network:
|
||||
|
||||
|
||||
1. **Start with [Preliminary Steps](preliminary-steps.mdx), preparing:**
|
||||
- [VPS](preliminary-steps/vps-setup.mdx)
|
||||
- [Nym wallet](preliminary-steps/wallet-preparation/mdx)
|
||||
|
||||
2. **[Setup](nym-node/setup.mdx) the node**
|
||||
|
||||
3. **[Configure](nym-node/configuration.mdx) the node and (optionally) automation, Wireguard, WSS, reverse proxy ...**
|
||||
|
||||
4. **[Run](nym-node/setup.mdx#initialise--run) the node or [the service](nym-node/configuration.md#systemd)**
|
||||
|
||||
5. **[Bond](nym-node/bonding.mdx) the node to the Nym API, using Nym wallet**
|
||||
|
||||
Make sure to follow the steps thoroughly, in case you find any point difficult don't hesitate to ask in our [Operators channel](https://matrix.to/#/#operators:nymtech.chat).
|
||||
@@ -7,18 +7,4 @@ NYM NODE is a tool for running a node within the Nym network. Nym Nodes containi
|
||||
|
||||
To setup any type of Nym Node, start with either building [Nym's platform](../binaries/building-nym.mdx) from source or download [pre-compiled binaries](../binaries/pre-built-binaries.mdx) on the [configured server (VPS)](preliminary-steps/vps-setup.mdx) where you want to run the node. Your Nym Node will need to be bonded before it can be run. We recommend most users use the [Nym desktop wallet](preliminary-steps/wallet-preparation.mdx) for this.
|
||||
|
||||
**Follow [preliminary steps](preliminary-steps.mdx) page before you configure and run a `nym-node`!**
|
||||
|
||||
## Steps for Nym Node Operators
|
||||
|
||||
Once [VPS and Nym wallet are configured](preliminary-steps.mdx), binaries ready, the operators of `nym-node` need to:
|
||||
|
||||
1. **[Setup](nym-node/setup.mdx) the node**
|
||||
|
||||
2. **[Configure](nym-node/configuration.mdx) the node and optionally automation, Wireguard, WSS, reversed proxy ...**
|
||||
|
||||
3. **[Run](nym-node/setup.mdx#initialise--run) the node or [the service](nym-node/configuration.md#systemd)**
|
||||
|
||||
4. **[Bond](nym-node/bonding.mdx) the node to the Nym API, using Nym wallet**
|
||||
|
||||
Make sure to follow the steps thoroughly, in case you find any point difficult don't hesitate to ask in our [Operators channel](https://matrix.to/#/#operators:nymtech.chat).
|
||||
**Read thoroughly [Minimum Requirement page](../nodes.mdx) before you configure and run a `nym-node`!**
|
||||
|
||||
@@ -17,10 +17,10 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](.
|
||||
```sh
|
||||
nym-node
|
||||
Binary Name: nym-node
|
||||
Build Timestamp: 2024-12-11T13:49:11.974104790Z
|
||||
Build Version: 1.2.0
|
||||
Commit SHA: a491e6a71a8cf862d77defd740a4ee8d65d8292a
|
||||
Commit Date: 2024-12-11T10:28:47.000000000+01:00
|
||||
Build Timestamp: 2024-12-18T10:18:42.978852430Z
|
||||
Build Version: 1.2.1
|
||||
Commit SHA: 8d5a41a790e96ae5e821964865affaa7d3343eab
|
||||
Commit Date: 2024-12-18T11:07:49.000000000+01:00
|
||||
Commit Branch: HEAD
|
||||
rustc Version: 1.83.0
|
||||
rustc Channel: stable
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Steps } from 'nextra/components';import { Tabs } from 'nextra/component
|
||||
import { MyTab } from 'components/generic-tabs.tsx';
|
||||
import PortsNymNode from 'components/operators/snippets/ports-nym-node.mdx';
|
||||
import PortsValidator from 'components/operators/snippets/ports-validator.mdx'
|
||||
import NymNodeSpecs from 'components/operators/snippets/nym-node-specs.mdx'
|
||||
|
||||
# VPS Setup & Configuration
|
||||
|
||||
@@ -13,51 +14,9 @@ We aim for Nym Network to be reliable and quality base layer of privacy accross
|
||||
A sub-optimally configured VPS often results in a non-functional node. To follow these steps carefully will save you time and money later on.
|
||||
</Callout>
|
||||
|
||||
## VPS Hardware Specs
|
||||
<NymNodeSpecs />
|
||||
|
||||
You will need to rent a VPS to run your node on. One key reason for this is that your node **must be able to send TCP data using both IPv4 and IPv6** (as other nodes you talk to may use either protocol).
|
||||
|
||||
Tor community created a very helpful table called [*Good Bad ISPs*](https://community.torproject.org/relay/community-resources/good-bad-isps/), you can use that one as a guideline for your choice of ISP for your VPS.
|
||||
|
||||
**Update:** Nym community started an ISP table called [*Where to host your nym node?*](../../community-counsel/isp-list.mdx), check it out and add your findings!
|
||||
|
||||
### `nym-node`
|
||||
|
||||
Before we conclude the testing with exact results, these are the rough specs:
|
||||
|
||||
| **Hardware** | **Minimum Specification** w
|
||||
| :--- | ---: |
|
||||
| CPU Cores | 4 |
|
||||
| Memory | 4 GB RAM |
|
||||
| Storage | 40 GB |
|
||||
| Connectivity | IPv4, IPv6, TCP/IP, UDP |
|
||||
| Bandwidth | 1Tb |
|
||||
| Port speed | 1Gbps |
|
||||
|
||||
### Nyx validator
|
||||
|
||||
The specification mentioned below is for running a full node alongside the nym-api. It is recommended to run `nym-api` and a full Nyx node on the same machine for optimum performance.
|
||||
|
||||
Bear in mind that credential signing is primarily CPU-bound, so choose the fastest CPU available to you.
|
||||
|
||||
#### Minimum Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|--------------------------------------------|
|
||||
| CPU | 8-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 16GB DDR4+ |
|
||||
| Disk | 500 GiB+ NVMe SSD |
|
||||
|
||||
#### Recommended Requirements
|
||||
|
||||
| Hardware | **Minimum Specification** |
|
||||
|----------|---------------------------------------------|
|
||||
| CPU | 16-cores, 2.8GHz base clock speed or higher |
|
||||
| RAM | 32GB DDR4+ |
|
||||
| Disk | 1 TiB+ NVMe SSD |
|
||||
|
||||
|
||||
#### Full node configuration (validator)
|
||||
## Full node configuration (validator)
|
||||
|
||||
To install a full node from scratch, refer to the [validator setup guide](../validator-setup.mdx) and follow the steps outlined there.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ zeroize = { workspace = true }
|
||||
# wasm-specific deps
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
wasm-bindgen = { workspace = true }
|
||||
js-sys = "0.3.70"
|
||||
js-sys = "0.3.76"
|
||||
tsify = { workspace = true, features = ["js"] }
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
|
||||
|
||||
@@ -174,10 +174,10 @@ mod api_regression {
|
||||
let location_result = client.locate_ip(my_ip).await;
|
||||
assert!(location_result.is_ok(), "Did ipinfo response change?");
|
||||
|
||||
assert!(
|
||||
client.check_remaining_bandwidth().await.is_ok(),
|
||||
"Failed to check remaining bandwidth?"
|
||||
);
|
||||
client
|
||||
.check_remaining_bandwidth()
|
||||
.await
|
||||
.expect("Failed to check remaining bandwidth?");
|
||||
|
||||
// when serialized, these fields should be present because they're exposed over API
|
||||
let location_result = location_result.unwrap();
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "nym-node"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -35,7 +35,7 @@ serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "time"] }
|
||||
thiserror = { workspace = true }
|
||||
time = {version = "0.3.36"}
|
||||
time = {version = "0.3.37"}
|
||||
tokio = { workspace = true, features = ["process", "rt-multi-thread"] }
|
||||
tokio-util = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
@@ -18,6 +18,6 @@ nym-sphinx-anonymous-replies = { path = "../../../common/nymsphinx/anonymous-rep
|
||||
nym-ffi-shared = { path = "../shared" }
|
||||
lazy_static = "1.5.0"
|
||||
# error handling
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
# base58 en/decoding
|
||||
bs58 = "0.5.0"
|
||||
|
||||
@@ -20,7 +20,7 @@ nym-ffi-shared = { path = "../shared" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
lazy_static = "1.5.0"
|
||||
# error handling
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
thiserror = "1.0.64"
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -14,7 +14,7 @@ nym-sphinx-anonymous-replies = { path = "../../../common/nymsphinx/anonymous-rep
|
||||
# static var macro
|
||||
lazy_static = "1.5.0"
|
||||
# error handling
|
||||
anyhow = "1.0.90"
|
||||
anyhow = "1.0.95"
|
||||
# base58 en/decoding
|
||||
bs58 = "0.5.0"
|
||||
# UDL test
|
||||
|
||||
@@ -40,6 +40,7 @@ async fn main() {
|
||||
client.disconnect().await;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(unused)]
|
||||
struct MockClientStorage {
|
||||
pub key_store: MockKeyStore,
|
||||
@@ -96,6 +97,7 @@ impl MixnetClientStorage for MockClientStorage {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MockKeyStore;
|
||||
|
||||
#[async_trait]
|
||||
@@ -115,6 +117,7 @@ impl KeyStore for MockKeyStore {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MockGatewayDetailsStore;
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -17,22 +17,22 @@ use zeroize::Zeroizing;
|
||||
/// The way to create this client is by calling
|
||||
/// [`crate::mixnet::DisconnectedMixnetClient::create_bandwidth_client`] on the associated mixnet
|
||||
/// client.
|
||||
pub struct BandwidthAcquireClient<'a, St: Storage> {
|
||||
pub struct BandwidthAcquireClient<St: Storage + Clone> {
|
||||
client: DirectSigningHttpRpcNyxdClient,
|
||||
storage: &'a St,
|
||||
storage: St,
|
||||
client_id: Zeroizing<Vec<u8>>,
|
||||
ticketbook_type: TicketType,
|
||||
}
|
||||
|
||||
impl<'a, St> BandwidthAcquireClient<'a, St>
|
||||
impl<St> BandwidthAcquireClient<St>
|
||||
where
|
||||
St: Storage,
|
||||
St: Storage + Clone,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
{
|
||||
pub(crate) fn new(
|
||||
network_details: NymNetworkDetails,
|
||||
mnemonic: String,
|
||||
storage: &'a St,
|
||||
storage: St,
|
||||
client_id: Vec<u8>,
|
||||
ticketbook_type: TicketType,
|
||||
) -> Result<Self> {
|
||||
@@ -55,7 +55,7 @@ where
|
||||
pub async fn acquire(&self) -> Result<()> {
|
||||
issue_credential(
|
||||
&self.client,
|
||||
self.storage,
|
||||
&self.storage,
|
||||
self.client_id.deref(),
|
||||
self.ticketbook_type,
|
||||
)
|
||||
|
||||
@@ -108,7 +108,7 @@ impl MixnetClientBuilder<OnDiskPersistent> {
|
||||
|
||||
impl<S> MixnetClientBuilder<S>
|
||||
where
|
||||
S: MixnetClientStorage + 'static,
|
||||
S: MixnetClientStorage + Clone + 'static,
|
||||
S::ReplyStore: Send + Sync,
|
||||
S::GatewaysDetailsStore: Sync,
|
||||
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
@@ -326,7 +326,7 @@ where
|
||||
/// client.
|
||||
pub struct DisconnectedMixnetClient<S>
|
||||
where
|
||||
S: MixnetClientStorage,
|
||||
S: MixnetClientStorage + Clone,
|
||||
{
|
||||
/// Client configuration
|
||||
config: Config,
|
||||
@@ -371,7 +371,7 @@ where
|
||||
|
||||
impl<S> DisconnectedMixnetClient<S>
|
||||
where
|
||||
S: MixnetClientStorage + 'static,
|
||||
S: MixnetClientStorage + Clone + 'static,
|
||||
S::ReplyStore: Send + Sync,
|
||||
S::GatewaysDetailsStore: Sync,
|
||||
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||
@@ -622,7 +622,7 @@ where
|
||||
BandwidthAcquireClient::new(
|
||||
self.config.network_details.clone(),
|
||||
mnemonic,
|
||||
self.storage.credential_store(),
|
||||
self.storage.credential_store().clone(),
|
||||
client_id,
|
||||
ticketbook_type,
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::{
|
||||
net::IpAddr,
|
||||
sync::Arc,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
@@ -11,7 +12,9 @@ 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 nym_authenticator_requests::latest::registration::RegistrationData;
|
||||
use nym_authenticator_requests::{
|
||||
latest::registration::RegistrationData, v4::registration::IpPair,
|
||||
};
|
||||
use nym_authenticator_requests::{
|
||||
latest::registration::{GatewayClient, PendingRegistrations, PrivateIPs},
|
||||
traits::{
|
||||
@@ -242,25 +245,24 @@ impl MixnetListener {
|
||||
|
||||
let peer = self.peer_manager.query_peer(remote_public).await?;
|
||||
if let Some(peer) = peer {
|
||||
let private_ipv4 = peer
|
||||
let allowed_ipv4 = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find_map(|ip_mask| match ip_mask.ip {
|
||||
std::net::IpAddr::V4(ipv4_addr) => Some(ipv4_addr),
|
||||
_ => None,
|
||||
});
|
||||
let private_ipv6 = peer
|
||||
})
|
||||
.ok_or(AuthenticatorError::InternalError(
|
||||
"there should be one private IPv4 in the list".to_string(),
|
||||
))?;
|
||||
let allowed_ipv6 = peer
|
||||
.allowed_ips
|
||||
.iter()
|
||||
.find_map(|ip_mask| match ip_mask.ip {
|
||||
std::net::IpAddr::V6(ipv6_addr) => Some(ipv6_addr),
|
||||
_ => None,
|
||||
});
|
||||
let (Some(allowed_ipv4), Some(allowed_ipv6)) = (private_ipv4, private_ipv6) else {
|
||||
return Err(AuthenticatorError::InternalError(
|
||||
"there should be one private IP pair in the list".to_string(),
|
||||
));
|
||||
};
|
||||
})
|
||||
.unwrap_or(IpPair::from(IpAddr::from(allowed_ipv4)).ipv6);
|
||||
let bytes = match AuthenticatorVersion::from(protocol) {
|
||||
AuthenticatorVersion::V1 => v1::response::AuthenticatorResponse::new_registered(
|
||||
v1::registration::RegistredData {
|
||||
|
||||
Reference in New Issue
Block a user