Compare commits

...

83 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu fd1d437211 Add 1GB/day/user bandwidth cap (#4717)
* Add check for 1GB/day/user and remove stale check

* Use saturated_sub

* Remove from wg peers

* Use 10 seconds instead of 1

* Query bandwidth message

* Ad client query message too

* Keep stale check

* Make bandwidth cap value public

* Fix consumed vs available bug

* Don't overwrite existing registrations

* Use self pub key instead of peer's
2024-07-23 20:49:49 +02:00
Jędrzej Stuczyński 6478736654 Merge pull request #4706 from nymtech/chore/remove-old-migration-code
removed mixnode/gateway config migration code and disabled cli without explicit flag
2024-07-23 15:11:36 +01:00
Jon Häggblad f86050d916 Default construct NodeRole for backwards compatibility (#4722) 2024-07-22 16:04:29 +02:00
import this 4e51188d35 [DOCs/operators]: Guide to back up and restore nym-node (#4720)
* add node backup & node restore guides

* finished: ready to review

* finished: ready to review
2024-07-22 11:17:55 +00:00
John Smith 22eb199936 Update isp-sheet.csv (#4718)
* Update isp-sheet.csv

Added a few known VPS providers which (a) support crypto payment (b) allow TOR in some shape or form (c) more or less know for their stability. Will add more eventually.

* Update isp-sheet.csv

added a few more providers
2024-07-22 10:57:57 +00:00
Tommy Verrall a2fc1bbc96 Merge pull request #4719 from nymtech/serinko/bug-fix/wss-guide
[DOCs/operators]: BugFix - add ssl cert to WSS server block
2024-07-19 12:48:36 +02:00
import this 621599692f add ssl cert to WSS server block 2024-07-19 10:43:02 +00:00
import this 3ad3837c87 done: fix wrong URL and picture formatting (#4714) 2024-07-17 10:47:41 +00:00
import this 4d745e3b7e [DOCs/operators]: Correct ports for bonding (#4707)
* fix port issue for nym-node mixnode

* fix port issue for nym-node mixnode

* simplify language

* clarify moving node info

* syntax fix
2024-07-16 14:00:38 +00:00
Sachin Kamath 3a053b8dd6 fix links (#4712) 2024-07-15 18:06:56 +02:00
Bogdan-Ștefan Neacşu 1f144690da Add upgrades to nym-node for authenticator changes (#4703) (#4710)
* Add iterative upgrades to nym-node

* Authenticator correct configuration

* Add info log

* Enable auth opts on entry gw

* Move ephemeral config from exit_gateway

* Fix fmt

* Fix clippy

* Pass custom transceiver for authenticator

* Fix non-linux build

* Feature gate wg_api

* Change naming from semver to simple incremental

* Move opts unwrap inside the mutable function

* Remove unneeded authenticator_description
2024-07-12 14:45:59 +02:00
Tommy Verrall eec1895acc Merge pull request #4709 from nymtech/dependabot/npm_and_yarn/nym-wallet/webdriver/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /nym-wallet/webdriver
2024-07-12 12:14:04 +02:00
dependabot[bot] 99864cb7a9 Bump braces from 3.0.2 to 3.0.3 in /nym-wallet/webdriver
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-12 09:09:14 +00:00
Fouad 3155728119 fix explorer mui deps (#4708) 2024-07-12 10:08:29 +01:00
Jędrzej Stuczyński c253b22f69 fixed the positional argument 2024-07-11 16:20:20 +01:00
Jędrzej Stuczyński 66f3a3e9a8 removed mixnode/gateway config migration code and disabled commands without explicit flag 2024-07-11 15:53:10 +01:00
Sachin Kamath 65a1d6d91e switch to new vanity link (#4705) 2024-07-11 13:04:56 +01:00
mx 44cf9b054b Max/dev portal update (#4696)
* updated tutorials with archive + stub

* removed out of date faq pages

* added binary build instructions section

* removed clients from docs

* added clients to devportal

* moved nym-vs-others to docs from devportal

* removed ood quickstart stuff

* tweaked integration options page

* summary changes for new structure

* moved sdk to devportal

* removed sdk from docs

* changed summary file for new structure

* added intro client overview page

* added wallet gif

* fixed now broken links

* removed old comm pages

* added references to newer apps (oreowallet + zcash demo)

* updated darkfi irc socks5

* fixed broken link

---------

Co-authored-by: mfahampshire <mfahampshire@pm.me>
2024-07-10 13:54:13 +02:00
Tommy Verrall 39e2473ef3 Merge pull request #4702 from nymtech/release/2024.7-doubledecker
Release/2024.7 doubledecker
2024-07-10 13:25:11 +02:00
import this 93a108863c add node description and release changelog (#4701) 2024-07-10 10:59:47 +00:00
import this 0905593123 [DOCs/operators]: Test WSS for exit-gateway, write a tutorial & update reversed proxy page (#4694)
* initialise wss guide

* update reverse proxy guide to post smoosh

* finish draft - missing correct script and testing

* syntax edit

* syntax edit

* update WSS configs and script

* edit WSS configs and script

* dinish wss guide - ready to review

* dinish wss guide - ready to review
2024-07-10 10:59:22 +00:00
Tommy Verrall ed9223d5a3 Merge branch 'develop' into release/2024.7-doubledecker 2024-07-10 11:46:21 +02:00
Tommy Verrall 962684ff56 Merge pull request #4667 from nymtech/feature/authenticator
Add authenticator
2024-07-10 10:14:58 +02:00
Tommy Verrall 7b3804c078 Merge pull request #4697 from nymtech/event-parsing
add event parsing to support cosmos_sdk > 0.50
2024-07-10 09:55:43 +02:00
Sachin Kamath 170f1823e1 fix tests 2024-07-09 21:54:57 +05:30
Sachin Kamath dc2020559a parse attributes from events instead of raw logs 2024-07-09 21:24:58 +05:30
Tommy Verrall 2b9444cce3 add an early return in parse_raw_str_logs for empty raw log strings.
this accommodates for the v50 chain upgrade
2024-07-09 20:36:36 +05:30
Bogdan-Ștefan Neacşu 68c1c068ac Add old config upgrade flow 2024-07-09 09:16:00 +00:00
Drazen Urch 3d0b70a237 Add mixnodes to self describing api cache (#4684)
* Add mixnodes to self describing api cache

* Use NodeRole enum

* Add route for described mixnodes

* Cleanup contract_cache

* Remove nodestatuscache

* wait_until_ready impl
2024-07-09 10:54:48 +02:00
Bogdan-Ștefan Neacşu 65a6edc78c Add authenticator debug to entry gateway config 2024-07-08 11:00:53 +00:00
Sachin Kamath 2ec8349897 update social links (#4695)
* replace vanity link

* fix links
2024-07-05 14:19:09 +00:00
Bogdan-Ștefan Neacşu 38a2d94f80 Fix clippy 2024-07-05 11:36:15 +00:00
Bogdan-Ștefan Neacşu c7fa910516 Fix add of req id 2024-07-05 10:36:18 +00:00
Bogdan-Ștefan Neacşu 2fe08274dd Add another layer for request id field 2024-07-05 10:20:56 +00:00
mx be89d848dc Max/try fix doc search (#4692)
* minimised dropdown bar

* update ci scripts

* theme changes to dev portal

* theme changes to operators

* theme changes to docs

* theme -> themes

* fixed theme -> themes import in book

* removed bak files

* remove logging from post_process + remove search feature from mdbook

---------

Co-authored-by: mfahampshire <mfahampshire@pm.me>
2024-07-05 12:19:14 +02:00
Bogdan-Ștefan Neacşu a230a9b8b9 Merge remote-tracking branch 'origin/develop' into feature/authenticator 2024-07-05 09:57:48 +00:00
Bogdan-Ștefan Neacşu 72eae7cdf3 Remove stale mid-registrations 2024-07-05 09:38:17 +00:00
Bogdan-Ștefan Neacşu 7cae195370 Typo 2024-07-05 07:54:29 +00:00
Bogdan-Ștefan Neacşu dfb16e385c Rand from workspace 2024-07-05 07:53:33 +00:00
Bogdan-Ștefan Neacşu 660e1cad0a Reconstruction msg 2024-07-04 14:26:37 +00:00
Bogdan-Ștefan Neacşu 7c1aa57a7e Add curr version 2024-07-04 14:15:25 +00:00
Bogdan-Ștefan Neacşu a06e496f78 Add final req creation 2024-07-04 13:54:13 +00:00
Jon Häggblad 70599b97b9 Send bandwidth status messages when connecting (#4691)
* Send bandwidth status messages when connecting

* Rename to task_client

* Move status message type to bandwidth controller
2024-07-04 13:10:16 +02:00
Bogdan-Ștefan Neacşu 02b194bde0 Function to create AuthReq 2024-07-04 10:40:53 +00:00
Bogdan-Ștefan Neacşu 20ec049db5 Remove more unnecessary structures 2024-07-04 09:41:17 +00:00
Bogdan-Ștefan Neacşu fec3d46b33 Include auth in self description 2024-07-03 13:50:44 +00:00
Bogdan-Ștefan Neacşu a4eb3a7dbf Named fork for better logging 2024-07-03 13:03:32 +00:00
Bogdan-Ștefan Neacşu 28d15f2c4f Remove unused import 2024-07-03 11:28:09 +00:00
Jon Häggblad 6078787daa Remove constructor since it's weakly typed (#4689) 2024-07-03 12:26:47 +02:00
Jon Häggblad 6d93f36c82 Fix NR config compatibility (#4690)
* Make NR able to read config with old keys in

We removed stuff related to the old statistics service, so we ignore
unknown fields to be nice to our users

* Remove deleted config keys from NR template
2024-07-03 12:10:41 +02:00
Bogdan-Ștefan Neacşu c6f93e38f5 Remove unused post function 2024-07-03 09:34:03 +00:00
Bogdan-Ștefan Neacşu 2159f71888 Fix wg feature 2024-07-03 09:04:01 +00:00
Bogdan-Ștefan Neacşu a9abea3446 Fix macos build 2024-07-03 08:27:10 +00:00
Bogdan-Ștefan Neacşu 8e2713c9ba Remove unwrap 2024-07-03 08:21:58 +00:00
Bogdan-Ștefan Neacşu 2ba0ef0e35 Remove unused wg http endpoint 2024-07-02 14:09:34 +00:00
Bogdan-Ștefan Neacşu d3713cbc79 Fix user agent arg 2024-07-02 16:40:11 +03:00
Bogdan-Ștefan Neacşu 4d3fb2b585 Merge remote-tracking branch 'origin/develop' into feature/authenticator 2024-07-02 16:25:29 +03:00
import this e65e611859 remove roles selection on blacklisting node - PR done (#4687) 2024-07-02 13:37:23 +01:00
Bogdan-Ștefan Neacşu c465eb3efc Fix error type 2024-07-02 08:58:48 +00:00
Bogdan-Ștefan Neacşu b90136ac4e Uniformise non-linux wg function 2024-07-01 15:10:36 +00:00
Bogdan-Ștefan Neacşu ae5373168d Fmt 2024-07-01 14:42:10 +00:00
Bogdan-Ștefan Neacşu 6f3942f6b7 Move implementation for final request 2024-07-01 14:38:48 +00:00
import this 4a25725a11 README.md update (#4685)
* start README update

* test alpha on github preview

* test alpha on github preview

* comment out rewards

* finish README update
2024-07-01 16:27:59 +02:00
Bogdan-Ștefan Neacşu 13f38343aa Finalize cli build 2024-07-01 13:44:59 +00:00
Jon Häggblad d34c829174 Create UserAgent that can be passed from the binary to the nym api client (#4677)
* Create UserAgent that can be passed from the binary to the nym api client

* TryFrom for UserAgent to HeaderValue

* Add user agent for getting the list of gateways

* Fix wasm client

* Move clap behind feature flag in bin-common

* Implement conversion to UserAgent

* Set user_agent on base client in native and socks5 clients

* Set user agent in socks5-listener lib

* wip

* wip

* Deserialize cargo_triple to unknown by default

* Abbreviate git hash

* Remove unused import

* Add missing dep, and remove dbg statements

* Reorder string representation

* Remove commented out code

* Revert temporary log level change
2024-07-01 13:29:10 +02:00
Bogdan-Ștefan Neacşu f75b4843e8 Merge remote-tracking branch 'origin/develop' into feature/authenticator 2024-07-01 09:56:34 +00:00
Jędrzej Stuczyński 6963ead65a minor cleanup 2024-07-01 08:25:31 +01:00
Jon Häggblad 0425cdeaf0 Merge pull request #4680 from nymtech/jon/deps-to-workspace
Move and whole bump of crates to workspace and upgrade some
2024-06-27 13:25:21 +02:00
import this 789914b096 [DOCs/operators]: Updates v2024.6-chomp and T&Cs (#4674)
* initialise updates and ToC

* add toc flag

* changelog and node black-xit improvement

* add node-api-check option

* syntax fix

* syntax fix

* change CI/CD with git reset

* fix typo

* add T&C AMA explanation link - ready for review

* fix typo

* resolve review comments

* add ToC standalone page

* minor edit - ready to go
2024-06-27 09:59:57 +00:00
Jon Häggblad 8acd3a0975 Move a few more deps partially to workspace 2024-06-27 10:52:15 +02:00
Jon Häggblad fa1519ec6a Move itertools to workspace deps 2024-06-27 10:52:15 +02:00
Jon Häggblad da94b7e8df Sort list 2024-06-27 10:52:15 +02:00
Jon Häggblad 4aa8cb4647 Move dalek and rand_chacha crates to workspace 2024-06-27 10:52:15 +02:00
Jon Häggblad 5d13538508 Use workspace base64 dep 2024-06-27 10:52:15 +02:00
Jon Häggblad 4bbbcf629d Fix warning for default_features 2024-06-27 10:52:15 +02:00
Jon Häggblad 34ef970fd8 Move dirs 4.0 to workspace deps 2024-06-27 10:52:14 +02:00
Jon Häggblad fec570613c Remove code that refers to removed nym-network-statistics (#4679)
* Remove nym-network-statistics from workspace

* Remove nym-network-statistics

* Cargo.lock

* Update ci workflow

* Remove code that refers to removed nym-network-statistics

* Remove more

* Remove nym-statistics-common

* Delete commented out modules

* Remove commented out code

* Remove more commented out code

* Remove more commented out stuff

* Remove unused function
2024-06-27 10:32:32 +02:00
Jon Häggblad 14a904eff0 Remove nym-network-statistics (#4678)
* Remove nym-network-statistics from workspace

* Remove nym-network-statistics

* Cargo.lock

* Update ci workflow
2024-06-27 10:32:09 +02:00
Bogdan-Ștefan Neacşu b43844bd7a Embed into gateway 2024-06-21 15:51:02 +00:00
Bogdan-Ștefan Neacşu cd89feb57e Fix path 2024-06-20 15:15:05 +00:00
Bogdan-Ștefan Neacşu 17553d606e Requests and responses 2024-06-20 16:58:21 +03:00
Bogdan-Ștefan Neacşu b6d9ed960b Specify version 2024-06-19 11:37:09 +03:00
Bogdan-Ștefan Neacşu 1d89a887fb Add authenticator 2024-06-18 19:05:23 +03:00
344 changed files with 7262 additions and 8336 deletions
+2 -2
View File
@@ -41,8 +41,8 @@ jobs:
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
+2 -2
View File
@@ -46,8 +46,8 @@ jobs:
# This is a workaround replacement which builds on the last working commit b332a6b55668f60988e36961f3f62a794ba82ddb and then on current branch
- name: Save current branch to ~/current_branch
run: git rev-parse --abbrev-ref HEAD > ~/current_branch
- name: Git pull & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Git pull, reset & switch to b332a6b55668f60988e36961f3f62a794ba82ddb
run: git pull && git reset --hard && git checkout b332a6b55668f60988e36961f3f62a794ba82ddb
- name: Build all projects in documentation/ & move to ~/dist/docs/ from b332a6b55668f60988e36961f3f62a794ba82ddb
run: cd documentation && ./build_all_to_dist.sh
Generated
+70 -58
View File
@@ -2100,7 +2100,7 @@ dependencies = [
"dotenvy",
"humantime-serde",
"isocountry",
"itertools 0.10.5",
"itertools 0.12.1",
"log",
"maxminddb",
"nym-bin-common",
@@ -2221,7 +2221,7 @@ dependencies = [
"atomic 0.6.0",
"pear",
"serde",
"toml 0.8.12",
"toml 0.8.14",
"uncased",
"version_check",
]
@@ -3272,15 +3272,6 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.1"
@@ -3959,6 +3950,54 @@ dependencies = [
"tokio",
]
[[package]]
name = "nym-authenticator"
version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"bs58 0.5.1",
"bytes",
"clap 4.5.4",
"fastrand 2.1.0",
"futures",
"ipnetwork 0.16.0",
"log",
"nym-authenticator-requests",
"nym-bin-common",
"nym-client-core",
"nym-config",
"nym-crypto",
"nym-id",
"nym-network-defaults",
"nym-sdk",
"nym-service-providers-common",
"nym-sphinx",
"nym-task",
"nym-types",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio-stream",
"tokio-util",
"url",
]
[[package]]
name = "nym-authenticator-requests"
version = "0.1.0"
dependencies = [
"bincode",
"nym-sphinx",
"nym-wireguard-types",
"rand 0.8.5",
"serde",
]
[[package]]
name = "nym-bandwidth-controller"
version = "0.1.0"
@@ -4282,7 +4321,7 @@ dependencies = [
"ff",
"getrandom 0.2.15",
"group",
"itertools 0.10.5",
"itertools 0.12.1",
"nym-dkg",
"nym-pemstore",
"rand 0.8.5",
@@ -4523,6 +4562,7 @@ dependencies = [
"ipnetwork 0.16.0",
"log",
"nym-api-requests",
"nym-authenticator",
"nym-bin-common",
"nym-config",
"nym-credentials",
@@ -4537,7 +4577,6 @@ dependencies = [
"nym-node-http-api",
"nym-pemstore",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-types",
"nym-validator-client",
@@ -4633,6 +4672,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"http 1.1.0",
"nym-bin-common",
"reqwest 0.12.4",
"serde",
"serde_json",
@@ -4939,7 +4979,6 @@ dependencies = [
"nym-socks5-proxy-helpers",
"nym-socks5-requests",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-types",
"pretty_env_logger",
@@ -4960,23 +4999,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-network-statistics"
version = "1.1.34"
dependencies = [
"dirs 4.0.0",
"log",
"nym-bin-common",
"nym-statistics-common",
"nym-task",
"pretty_env_logger",
"rocket",
"serde",
"sqlx",
"thiserror",
"tokio",
]
[[package]]
name = "nym-node"
version = "1.1.4"
@@ -4991,6 +5013,7 @@ dependencies = [
"cupid",
"humantime-serde",
"ipnetwork 0.16.0",
"nym-authenticator",
"nym-bin-common",
"nym-client-core-config-types",
"nym-config",
@@ -5014,7 +5037,7 @@ dependencies = [
"sysinfo 0.30.12",
"thiserror",
"tokio",
"toml 0.8.12",
"toml 0.8.14",
"tracing",
"url",
"zeroize",
@@ -5160,7 +5183,7 @@ dependencies = [
"chacha20poly1305",
"criterion",
"curve25519-dalek 4.1.2",
"fastrand 1.9.0",
"fastrand 2.1.0",
"getrandom 0.2.15",
"log",
"rand 0.8.5",
@@ -5260,6 +5283,7 @@ dependencies = [
"nym-socks5-client-core",
"nym-sphinx",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"serde",
"serde_json",
@@ -5505,20 +5529,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "nym-statistics-common"
version = "1.0.1"
dependencies = [
"async-trait",
"log",
"reqwest 0.12.4",
"serde",
"serde_json",
"sqlx",
"thiserror",
"tokio",
]
[[package]]
name = "nym-store-cipher"
version = "0.1.0"
@@ -5593,7 +5603,7 @@ dependencies = [
"cosmwasm-std",
"eyre",
"hmac",
"itertools 0.11.0",
"itertools 0.12.1",
"log",
"nym-config",
"nym-crypto",
@@ -5632,7 +5642,7 @@ dependencies = [
"eyre",
"flate2",
"futures",
"itertools 0.10.5",
"itertools 0.12.1",
"log",
"nym-api-requests",
"nym-coconut",
@@ -5732,6 +5742,7 @@ name = "nym-wireguard"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"chrono",
"dashmap",
"defguard_wireguard_rs",
"ip_network",
@@ -5740,6 +5751,7 @@ dependencies = [
"nym-network-defaults",
"nym-task",
"nym-wireguard-types",
"thiserror",
"tokio",
"tokio-stream",
"x25519-dalek",
@@ -7594,9 +7606,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
dependencies = [
"serde",
]
@@ -8616,21 +8628,21 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.12"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.12",
"toml_edit 0.22.14",
]
[[package]]
name = "toml_datetime"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
dependencies = [
"serde",
]
@@ -8650,9 +8662,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.12"
version = "0.22.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
dependencies = [
"indexmap 2.2.6",
"serde",
+14 -4
View File
@@ -20,6 +20,7 @@ members = [
"clients/native",
"clients/native/websocket-requests",
"clients/socks5",
"common/authenticator-requests",
"common/async-file-watcher",
"common/bandwidth-controller",
"common/bin-common",
@@ -76,7 +77,6 @@ members = [
"common/socks5-client-core",
"common/socks5/proxy-helpers",
"common/socks5/requests",
"common/statistics",
"common/store-cipher",
"common/task",
"common/topology",
@@ -96,10 +96,10 @@ members = [
"mixnode",
"sdk/lib/socks5-listener",
"sdk/rust/nym-sdk",
"service-providers/authenticator",
"service-providers/common",
"service-providers/ip-packet-router",
"service-providers/network-requester",
"service-providers/network-statistics",
"nym-api",
"nym-browser-extension/storage",
"nym-api/nym-api-requests",
@@ -127,7 +127,6 @@ default-members = [
"clients/socks5",
"gateway",
"service-providers/network-requester",
"service-providers/network-statistics",
"mixnode",
"nym-api",
"tools/nymvisor",
@@ -192,12 +191,15 @@ cupid = "0.6.1"
curve25519-dalek = "4.1"
dashmap = "5.5.3"
defguard_wireguard_rs = "0.4.2"
digest = "0.10.7"
dirs = "4.0"
doc-comment = "0.3"
dotenvy = "0.15.6"
ecdsa = "0.16"
ed25519-dalek = "2.1"
etherparse = "0.13.0"
eyre = "0.6.9"
fastrand = "2.1.0"
flate2 = "1.0.28"
futures = "0.3.28"
generic-array = "0.14.7"
@@ -209,14 +211,15 @@ hex = "0.4.3"
hex-literal = "0.3.3"
hkdf = "0.12.3"
hmac = "0.12.1"
http = "1"
httpcodec = "0.2.3"
humantime = "2.1.0"
humantime-serde = "1.1.1"
http = "1"
hyper = "1.3.1"
indexed_db_futures = "0.3.0"
inquire = "0.6.2"
ip_network = "0.4.1"
ipnetwork = "0.16"
isocountry = "0.3.2"
k256 = "0.13"
lazy_static = "1.4.0"
@@ -239,6 +242,7 @@ publicsuffix = "2.2.3"
quote = "1"
rand = "0.8.5"
rand-07 = "0.7.3"
rand_chacha = "0.3"
rand_chacha_02 = "0.2"
rand_core = "0.6.3"
rand_distr = "0.4"
@@ -252,6 +256,7 @@ rocket_cors = "0.6.0"
rocket_okapi = "0.8.0"
safer-ffi = "0.1.4"
schemars = "0.8.1"
semver = "1.0.23"
serde = "1.0.152"
serde_bytes = "0.11.6"
serde_derive = "1.0"
@@ -259,12 +264,14 @@ serde_json = "1.0.91"
serde_repr = "0.1"
serde_with = "3.4.0"
serde_yaml = "0.9.25"
sha2 = "0.10.8"
si-scale = "0.2.2"
sphinx-packet = "0.1.1"
sqlx = "0.6.3"
strum = "0.25"
subtle-encoding = "0.5"
syn = "1"
sysinfo = "0.30.12"
tap = "1.0.1"
tar = "0.4.40"
tempfile = "3.5.0"
@@ -275,6 +282,7 @@ tokio-stream = "0.1.14"
tokio-test = "0.4.2"
tokio-tungstenite = { version = "0.20.1" }
tokio-util = "0.7.10"
toml = "0.8.14"
tower = "0.4.13"
tower-http = "0.5.2"
tracing = "0.1.37"
@@ -289,6 +297,7 @@ utoipa-swagger-ui = "6.0.0"
vergen = { version = "=8.3.1", default-features = false }
walkdir = "2"
wasm-bindgen-test = "0.3.36"
x25519-dalek = "2.0.0"
zeroize = "1.6.0"
prometheus = { version = "0.13.0" }
@@ -336,6 +345,7 @@ wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4.39"
wasmtimer = "0.2.0"
web-sys = "0.3.69"
itertools = "0.12.0"
# Profile settings for individual crates
+36 -56
View File
@@ -7,86 +7,66 @@ SPDX-License-Identifier: Apache-2.0
The platform is composed of multiple Rust crates. Top-level executable binary crates include:
* nym-mixnode - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
* nym-client - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* nym-socks5-client - a Socks5 proxy you can run on your machine and use with existing applications.
* nym-gateway - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices.
* nym-network-monitor - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
* nym-explorer - a (projected) block explorer and (existing) mixnet viewer.
* nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
* `nym-node` - a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. Read more about `nym-node` in [Operators Guide documentation](https://nymtech.net/operators/nodes/nym-node.html). Network functionality of `nym-node` (labeled with `--mode` flag) can be:
- `mixnode` - shuffles [Sphinx](https://github.com/nymtech/sphinx) packets together to provide privacy against network-level attackers.
- `gateway` - acts sort of like a mailbox for mixnet messages, which removes the need for direct delivery to potentially offline or firewalled devices. Gateways can be further categorized as `entry-gateway` and `exit-gateway`. The latter has an extra embedded IP packet router and Network requester to route data to the internet.
* `nym-client` - an executable which you can build into your own applications. Use it for interacting with Nym nodes.
* `nym-socks5-client` - a Socks5 proxy you can run on your machine and use with existing applications.
* `nym-explorer` - a (projected) block explorer and (existing) mixnet viewer.
* `nym-wallet` - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework.
<!-- coming soon
* `nym-network-monitor` - sends packets through the full system to check that they are working as expected, and stores node uptime histories as the basis of a rewards system ("mixmining" or "proof-of-mixing").
-->
```ascii
┌─►mix──┐ mix mix
│ │
Entry │ │ Exit
client ───► Gateway ──┘ mix │ mix ┌─►mix ───► Gateway ───► internet
│ │
│ │
mix └─►mix──┘ mix
```
[![Build Status](https://img.shields.io/github/actions/workflow/status/nymtech/nym/build.yml?branch=develop&style=for-the-badge&logo=github-actions)](https://github.com/nymtech/nym/actions?query=branch%3Adevelop)
### Building
Platform build instructions are available on [our docs site](https://nymtech.net/docs/binaries/pre-built-binaries.html).
Wallet build instructions are also available on [our docs site](https://nymtech.net/docs/wallet/desktop-wallet.html).
* Platform build instructions are available on Nym [Operators Guide documentation](https://nymtech.net/operators/binaries/building-nym.html).
* Wallet build instructions are available on Nym [Technical docs](https://nymtech.net/docs/wallet/desktop-wallet.html).
### Developing
There's a `.env.sample-dev` file provided which you can rename to `.env` if you want convenient logging, backtrace, or other environment variables pre-set. The `.env` file is ignored so you don't need to worry about checking it in.
There's a [`sandbox.env`](https://github.com/nymtech/nym/envs/sandbox.env) file provided which you can rename to `.env` if you want convenient testing environment. Read more about sandbox environment in our [Operators Guide page](https://nymtech.net/operators/sandbox.html).
For Typescript components, please see [ts-packages](./ts-packages).
References for developers:
* [Developers Portal](https://nymtech.net/developers)
* [Typescript SDKs](https://sdk.nymtech.net/)
* [Technical Documentation - Nym network overview](https://nymtech.net/docs/)
* [Release Cycle - git flow](https://nymtech.net/operators/release-cycle.html)
### Developer chat
> We used to use Keybase for developer chats, but we have since migrated to Matrix and Discord. We no longer check the old **nymtech.friends** Keybase team.
You can chat to us in two places:
* The #dev channel on [Matrix](https://matrix.to/#/#dev:nymtech.chat)
* The various developer channels on [Discord](https://discord.gg/nym)
* The various developer channels on [Discord](https://nymtech.net/go/discord)
### Rewards
### Tokenomics & Rewards
Node, node operator and delegator rewards are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf). Below is a TLDR of the variables and formulas involved in calculating the epoch rewards. Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
|Symbol|Definition|
|---|---|
|<img src="https://render.githubusercontent.com/render/math?math=R#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R#gh-dark-mode-only">|global share of rewards available, starts at 2% of the reward pool.
|<img src="https://render.githubusercontent.com/render/math?math=R_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}#gh-dark-mode-only">|node reward for mixnode `i`.
|<img src="https://render.githubusercontent.com/render/math?math=\sigma_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma_{i}#gh-dark-mode-only">|ratio of total node stake (node bond + all delegations) to the token circulating supply.
|<img src="https://render.githubusercontent.com/render/math?math=\lambda_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda_{i}#gh-dark-mode-only">|ratio of stake operator has pledged to their node to the token circulating supply.
|<img src="https://render.githubusercontent.com/render/math?math=\omega_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\omega_{i}#gh-dark-mode-only">|fraction of total effort undertaken by node `i`, set to `1/k`.
|<img src="https://render.githubusercontent.com/render/math?math=k#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}k#gh-dark-mode-only">|number of nodes stakeholders are incentivised to create, set by the validators, a matter of governance. Currently determined by the `reward set` size, and set to 720 in testnet Sandbox.
|<img src="https://render.githubusercontent.com/render/math?math=\alpha#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}\alpha#gh-dark-mode-only">|A Sybil attack resistance parameter - the higher this parameter is set, the stronger the reduction in competitiveness for a Sybil attacker.
|<img src="https://render.githubusercontent.com/render/math?math=PM_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PM_{i}#gh-dark-mode-only">|declared profit margin of operator `i`, defaults to 10%.
|<img src="https://render.githubusercontent.com/render/math?math=PF_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PF_{i}#gh-dark-mode-only">|uptime of node `i`, scaled to 0 - 1, for the rewarding epoch
|<img src="https://render.githubusercontent.com/render/math?math=PP_{i}#gh-light-mode-only"><img src="https://render.githubusercontent.com/render/math?math=\color{white}PP_{i}#gh-dark-mode-only">|cost of operating node `i` for the duration of the rewarding epoch, set to 40 NYMs.
Node reward for node `i` is determined as:
<img src="https://render.githubusercontent.com/render/math?math=R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}R_{i}=PF_{i} \cdot R \cdot (\sigma^'_{i} \cdot \omega_{i} \cdot k %2b \alpha \cdot \lambda^'_{i} \cdot \sigma^'_{i} \cdot k)/(1 %2b \alpha)#gh-dark-mode-only">
where:
<img src="https://render.githubusercontent.com/render/math?math=\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\sigma^'_{i} = min\{\sigma_{i}, 1/k\}#gh-dark-mode-only">
and
<img src="https://render.githubusercontent.com/render/math?math=\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}\lambda^'_{i} = min\{\lambda_{i}, 1/k\}#gh-dark-mode-only">
Operator of node `i` is credited with the following amount:
<img src="https://render.githubusercontent.com/render/math?math=min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}min\{PP_{i},R_{i})\} %2b max\{0, (PM_{i} %2b (1 - PM_{i}) \cdot \lambda_{i}/\delta_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
Delegate with stake `s` receives:
<img src="https://render.githubusercontent.com/render/math?math=max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-light-mode-only">
<img src="https://render.githubusercontent.com/render/math?math=\color{white}max\{0, (1-PM_{i}) \cdot (s^'/\sigma_{i}) \cdot (R_{i} - PP_{i})\}#gh-dark-mode-only">
where `s'` is stake `s` scaled over total token circulating supply.
Nym network economic incentives, operator and validator rewards, and scalability of the network are determined according to the principles laid out in the section 6 of [Nym Whitepaper](https://nymtech.net/nym-whitepaper.pdf).
Initial reward pool is set to 250 million Nym, making the circulating supply 750 million Nym.
### Licensing and copyright information
This is a monorepo and components that make up Nym as a system are licensed individually, so for accurate information, please check individual files.
As a general approach, licensing is as follows this pattern:
- applications and binaries are GPLv3
- libraries and components are Apache 2.0 or MIT
- documentation is Apache 2.0 or CC0-1.0
Again, for accurate information, please check individual files.
Nym Node Operators and Validators Temrs and Conditions can be found [here](https://nymtech.net/terms-and-conditions/operators/v1.0.0).
+2 -2
View File
@@ -23,7 +23,7 @@ url = { workspace = true }
bs58 = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] }
dirs = "4.0"
dirs = { workspace = true }
log = { workspace = true } # self explanatory
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
@@ -37,7 +37,7 @@ zeroize = { workspace = true }
## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
+3 -1
View File
@@ -106,8 +106,10 @@ impl SocketClient {
};
let storage = self.initialise_storage().await?;
let user_agent = nym_bin_common::bin_info!().into();
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client);
let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client)
.with_user_agent(user_agent);
if let Some(custom_mixnet) = &self.custom_mixnet {
base_client = base_client.with_stored_topology(custom_mixnet)?;
+2 -1
View File
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
}
pub(crate) async fn execute(args: Args) -> Result<(), ClientError> {
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = add_gateway::<CliNativeClient, _>(args).await?;
let res = add_gateway::<CliNativeClient, _>(args, Some(user_agent)).await?;
println!("{}", output.format(&res));
Ok(())
+2 -1
View File
@@ -114,8 +114,9 @@ impl Display for InitResults {
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
eprintln!("Initialising client...");
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = initialise_client::<CliNativeClient>(args).await?;
let res = initialise_client::<CliNativeClient>(args, Some(user_agent)).await?;
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
+5 -4
View File
@@ -25,17 +25,18 @@ zeroize = { workspace = true }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-id = { path = "../../common/nym-id" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
nym-pemstore = { path = "../../common/pemstore" }
nym-topology = { path = "../../common/topology" }
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
nym-id = { path = "../../common/nym-id" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
[features]
default = []
+2 -1
View File
@@ -22,8 +22,9 @@ impl AsRef<CommonClientAddGatewayArgs> for Args {
}
pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> {
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = add_gateway::<CliSocks5Client, _>(args).await?;
let res = add_gateway::<CliSocks5Client, _>(args, Some(user_agent)).await?;
println!("{}", output.format(&res));
Ok(())
+2 -1
View File
@@ -129,8 +129,9 @@ impl Display for InitResults {
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
eprintln!("Initialising client...");
let user_agent = nym_bin_common::bin_info!().into();
let output = args.output;
let res = initialise_client::<CliSocks5Client>(args).await?;
let res = initialise_client::<CliSocks5Client>(args, Some(user_agent)).await?;
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
+9 -3
View File
@@ -116,7 +116,13 @@ pub(crate) async fn execute(args: Run) -> Result<(), Box<dyn std::error::Error +
let storage =
OnDiskPersistent::from_paths(config.storage_paths.common_paths, &config.core.base.debug)
.await?;
NymClient::new(config.core, storage, args.common_args.custom_mixnet)
.run_forever()
.await
let user_agent = nym_bin_common::bin_info!().into();
NymClient::new(
config.core,
storage,
user_agent,
args.common_args.custom_mixnet,
)
.run_forever()
.await
}
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "nym-authenticator-requests"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
[dependencies]
bincode = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
nym-sphinx = { path = "../nymsphinx" }
nym-wireguard-types = { path = "../wireguard-types" }
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod v1;
pub const CURRENT_VERSION: u8 = 1;
fn make_bincode_serializer() -> impl bincode::Options {
use bincode::Options;
bincode::DefaultOptions::new()
.with_big_endian()
.with_varint_encoding()
}
@@ -0,0 +1,7 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod request;
pub mod response;
const VERSION: u8 = 1;
@@ -0,0 +1,84 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::{GatewayClient, InitMessage, PeerPublicKey};
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
fn generate_random() -> u64 {
use rand::RngCore;
let mut rng = rand::rngs::OsRng;
rng.next_u64()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorRequest {
pub version: u8,
pub data: AuthenticatorRequestData,
pub reply_to: Recipient,
pub request_id: u64,
}
impl AuthenticatorRequest {
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
version: VERSION,
data: AuthenticatorRequestData::Initial(init_message),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_final_request(gateway_client: GatewayClient, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
version: VERSION,
data: AuthenticatorRequestData::Final(gateway_client),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
version: VERSION,
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
reply_to,
request_id,
},
request_id,
)
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorRequestData {
Initial(InitMessage),
Final(GatewayClient),
QueryBandwidth(PeerPublicKey),
}
@@ -0,0 +1,119 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorResponse {
pub version: u8,
pub data: AuthenticatorResponseData,
pub reply_to: Recipient,
}
impl AuthenticatorResponse {
pub fn new_pending_registration_success(
registration_data: RegistrationData,
request_id: u64,
reply_to: Recipient,
) -> Self {
Self {
version: VERSION,
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
reply: registration_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_registered(
registred_data: RegistredData,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
version: VERSION,
data: AuthenticatorResponseData::Registered(RegisteredResponse {
reply: registred_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_remaining_bandwidth(
remaining_bandwidth_data: Option<RemainingBandwidthData>,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
version: VERSION,
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
reply: remaining_bandwidth_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn recipient(&self) -> Recipient {
self.reply_to
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn id(&self) -> Option<u64> {
match &self.data {
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorResponseData {
PendingRegistration(PendingRegistrationResponse),
Registered(RegisteredResponse),
RemainingBandwidth(RemainingBandwidthResponse),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PendingRegistrationResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistrationData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RegisteredResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistredData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RemainingBandwidthResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: Option<RemainingBandwidthData>,
}
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// See other comments for other TaskStatus message enumds about abusing the Error trait when we
// should have a new trait for TaskStatus messages
#[derive(Debug, thiserror::Error)]
pub enum BandwidthStatusMessage {
#[error("remaining bandwidth: {0}")]
RemainingBandwidth(i64),
#[error("no bandwidth left")]
NoBandwidth,
}
+3
View File
@@ -14,8 +14,11 @@ use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nym_api::EpochId;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
pub use event::BandwidthStatusMessage;
pub mod acquire;
pub mod error;
mod event;
mod utils;
#[derive(Debug)]
+5 -4
View File
@@ -9,9 +9,9 @@ repository = { workspace = true }
[dependencies]
const-str = { workspace = true }
clap = { workspace = true, features = ["derive"] }
clap_complete = { workspace = true }
clap_complete_fig = { workspace = true }
clap = { workspace = true, features = ["derive"], optional = true }
clap_complete = { workspace = true, optional = true }
clap_complete_fig = { workspace = true, optional = true }
log = { workspace = true }
pretty_env_logger = { workspace = true }
semver = "0.11"
@@ -34,7 +34,7 @@ vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "carg
[features]
default = []
openapi = ["utoipa"]
output_format = ["serde_json"]
output_format = ["serde_json", "dep:clap"]
bin_info_schema = ["schemars"]
basic_tracing = ["tracing-subscriber"]
tracing = [
@@ -44,3 +44,4 @@ tracing = [
"tracing-opentelemetry",
"opentelemetry",
]
clap = [ "dep:clap", "dep:clap_complete", "dep:clap_complete_fig" ]
@@ -44,6 +44,10 @@ pub struct BinaryBuildInformation {
/// Provides the cargo debug mode that was used for the build.
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
pub cargo_profile: &'static str,
// VERGEN_CARGO_TARGET_TRIPLE
/// Provides the cargo target triple that was used for the build.
pub cargo_triple: &'static str,
}
impl BinaryBuildInformation {
@@ -66,6 +70,7 @@ impl BinaryBuildInformation {
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile,
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
}
}
@@ -95,6 +100,7 @@ impl BinaryBuildInformation {
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile,
cargo_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"),
}
}
@@ -109,6 +115,7 @@ impl BinaryBuildInformation {
rustc_version: self.rustc_version.to_owned(),
rustc_channel: self.rustc_channel.to_owned(),
cargo_profile: self.cargo_profile.to_owned(),
cargo_triple: self.cargo_triple.to_owned(),
}
}
@@ -156,6 +163,15 @@ pub struct BinaryBuildInformationOwned {
/// Provides the cargo debug mode that was used for the build.
// NOTE: keep the old name cargo_profile instead of cargo_debug for backwards compatibility
pub cargo_profile: String,
// VERGEN_CARGO_TARGET_TRIPLE
/// Provides the cargo target triple that was used for the build.
#[serde(default = "unknown")]
pub cargo_triple: String,
}
fn unknown() -> String {
"unknown".to_string()
}
impl Display for BinaryBuildInformationOwned {
+3 -1
View File
@@ -2,9 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
pub mod build_information;
pub mod completions;
pub mod logging;
pub mod version_checker;
#[cfg(feature = "clap")]
pub mod completions;
#[cfg(feature = "output_format")]
pub mod output_format;
+2 -2
View File
@@ -10,7 +10,7 @@ license.workspace = true
[dependencies]
async-trait = { workspace = true }
base64 = "0.21.2"
base64 = { workspace = true }
bs58 = { workspace = true }
cfg-if = { workspace = true }
clap = { workspace = true, optional = true }
@@ -20,7 +20,7 @@ log = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
sha2 = { workspace = true }
si-scale = { workspace = true }
tap = { workspace = true }
thiserror = { workspace = true }
@@ -16,6 +16,7 @@ use log::info;
use nym_client_core_gateways_storage::GatewayDetails;
use nym_crypto::asymmetric::identity;
use nym_topology::NymTopology;
use nym_validator_client::UserAgent;
use std::path::PathBuf;
#[cfg_attr(feature = "cli", derive(clap::Args))]
@@ -60,7 +61,10 @@ pub struct CommonClientAddGatewayArgs {
pub custom_mixnet: Option<PathBuf>,
}
pub async fn add_gateway<C, A>(args: A) -> Result<GatewayInfo, C::Error>
pub async fn add_gateway<C, A>(
args: A,
user_agent: Option<UserAgent>,
) -> Result<GatewayInfo, C::Error>
where
A: AsRef<CommonClientAddGatewayArgs>,
C: CliClient,
@@ -111,7 +115,8 @@ where
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
.await?
};
// since we're registering with a brand new gateway,
@@ -16,6 +16,7 @@ use log::info;
use nym_client_core_gateways_storage::GatewayDetails;
use nym_crypto::asymmetric::identity;
use nym_topology::NymTopology;
use nym_validator_client::UserAgent;
use rand::rngs::OsRng;
use std::path::PathBuf;
@@ -96,6 +97,7 @@ pub struct InitResultsWithConfig<T> {
pub async fn initialise_client<C>(
init_args: C::InitArgs,
user_agent: Option<UserAgent>,
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
where
C: InitialisableClient,
@@ -163,7 +165,8 @@ where
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls, user_agent)
.await?
};
let gateway_setup = GatewaySetup::New {
@@ -53,7 +53,7 @@ use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender,
use nym_task::{TaskClient, TaskHandle};
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::HardcodedTopologyProvider;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
use rand::rngs::OsRng;
use std::fmt::Debug;
use std::os::raw::c_int as RawFd;
@@ -184,6 +184,7 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> {
custom_topology_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
shutdown: Option<TaskClient>,
user_agent: Option<UserAgent>,
setup_method: GatewaySetup,
}
@@ -207,6 +208,7 @@ where
custom_topology_provider: None,
custom_gateway_transceiver: None,
shutdown: None,
user_agent: None,
setup_method: GatewaySetup::MustLoad { gateway_id: None },
}
}
@@ -250,6 +252,12 @@ where
self
}
#[must_use]
pub fn with_user_agent(mut self, user_agent: UserAgent) -> Self {
self.user_agent = Some(user_agent);
self
}
pub fn with_stored_topology<P: AsRef<Path>>(
mut self,
file: P,
@@ -467,6 +475,7 @@ where
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
config_topology: config::Topology,
nym_api_urls: Vec<Url>,
user_agent: Option<UserAgent>,
) -> Box<dyn TopologyProvider + Send + Sync> {
// if no custom provider was ... provided ..., create one using nym-api
custom_provider.unwrap_or_else(|| match config_topology.topology_structure {
@@ -477,6 +486,7 @@ where
},
nym_api_urls,
env!("CARGO_PKG_VERSION").to_string(),
user_agent,
)),
config::TopologyStructure::GeoAware(group_by) => {
Box::new(GeoAwareTopologyProvider::new(
@@ -689,6 +699,7 @@ where
self.custom_topology_provider.take(),
self.config.debug.topology,
self.config.get_nym_api_endpoints(),
self.user_agent.clone(),
);
// needs to be started as the first thing to block if required waiting for the gateway
@@ -5,6 +5,7 @@ use async_trait::async_trait;
use log::{debug, error, warn};
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::{NymTopology, NymTopologyError};
use nym_validator_client::UserAgent;
use rand::prelude::SliceRandom;
use rand::thread_rng;
use url::Url;
@@ -39,14 +40,26 @@ pub(crate) struct NymApiTopologyProvider {
}
impl NymApiTopologyProvider {
pub(crate) fn new(config: Config, mut nym_api_urls: Vec<Url>, client_version: String) -> Self {
pub(crate) fn new(
config: Config,
mut nym_api_urls: Vec<Url>,
client_version: String,
user_agent: Option<UserAgent>,
) -> Self {
nym_api_urls.shuffle(&mut thread_rng());
let validator_client = if let Some(user_agent) = user_agent {
nym_validator_client::client::NymApiClient::new_with_user_agent(
nym_api_urls[0].clone(),
user_agent,
)
} else {
nym_validator_client::client::NymApiClient::new(nym_api_urls[0].clone())
};
NymApiTopologyProvider {
config,
validator_client: nym_validator_client::client::NymApiClient::new(
nym_api_urls[0].clone(),
),
validator_client,
nym_api_urls,
client_version,
currently_used_api: 0,
+7 -1
View File
@@ -9,6 +9,7 @@ use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_topology::{filter::VersionFilterable, gateway, mix};
use nym_validator_client::client::IdentityKeyRef;
use nym_validator_client::UserAgent;
use rand::{seq::SliceRandom, Rng};
use std::{sync::Arc, time::Duration};
use tungstenite::Message;
@@ -59,11 +60,16 @@ impl<'a> GatewayWithLatency<'a> {
pub async fn current_gateways<R: Rng>(
rng: &mut R,
nym_apis: &[Url],
user_agent: Option<UserAgent>,
) -> Result<Vec<gateway::Node>, ClientCoreError> {
let nym_api = nym_apis
.choose(rng)
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let client = nym_validator_client::client::NymApiClient::new(nym_api.clone());
let client = if let Some(user_agent) = user_agent {
nym_validator_client::client::NymApiClient::new_with_user_agent(nym_api.clone(), user_agent)
} else {
nym_validator_client::client::NymApiClient::new(nym_api.clone())
};
log::debug!("Fetching list of gateways from: {nym_api}");
+15 -12
View File
@@ -11,7 +11,7 @@ use crate::traits::GatewayPacketRouter;
use crate::{cleanup_socket_message, try_decrypt_binary_message};
use futures::{SinkExt, StreamExt};
use log::*;
use nym_bandwidth_controller::BandwidthController;
use nym_bandwidth_controller::{BandwidthController, BandwidthStatusMessage};
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
use nym_credential_storage::storage::Storage as CredentialStorage;
use nym_credentials::CredentialSpendingData;
@@ -105,8 +105,8 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
// currently unused (but populated)
negotiated_protocol: Option<u8>,
/// Listen to shutdown messages.
shutdown: TaskClient,
/// Listen to shutdown messages and send notifications back to the task manager
task_client: TaskClient,
}
impl<C, St> GatewayClient<C, St> {
@@ -117,7 +117,7 @@ impl<C, St> GatewayClient<C, St> {
shared_key: Option<Arc<SharedKeys>>,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
shutdown: TaskClient,
task_client: TaskClient,
) -> Self {
GatewayClient {
authenticated: false,
@@ -135,7 +135,7 @@ impl<C, St> GatewayClient<C, St> {
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
negotiated_protocol: None,
shutdown,
task_client,
}
}
@@ -299,7 +299,7 @@ impl<C, St> GatewayClient<C, St> {
loop {
tokio::select! {
_ = self.shutdown.recv() => {
_ = self.task_client.recv() => {
log::trace!("GatewayClient control response: Received shutdown");
log::debug!("GatewayClient control response: Exiting");
break Err(GatewayClientError::ConnectionClosedGatewayShutdown);
@@ -540,6 +540,9 @@ impl<C, St> GatewayClient<C, St> {
self.bandwidth_remaining = bandwidth_remaining;
self.negotiated_protocol = protocol_version;
log::debug!("authenticated: {status}, bandwidth remaining: {bandwidth_remaining}");
self.task_client.send_status_msg(Box::new(
BandwidthStatusMessage::RemainingBandwidth(bandwidth_remaining),
));
Ok(())
}
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
@@ -805,7 +808,7 @@ impl<C, St> GatewayClient<C, St> {
.as_ref()
.expect("no shared key present even though we're authenticated!"),
),
self.shutdown.clone(),
self.task_client.clone(),
)
}
_ => unreachable!(),
@@ -879,8 +882,8 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
// perfectly fine here, because it's not meant to be used
let (ack_tx, _) = mpsc::unbounded();
let (mix_tx, _) = mpsc::unbounded();
let shutdown = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone());
let task_client = TaskClient::dummy();
let packet_router = PacketRouter::new(ack_tx, mix_tx, task_client.clone());
GatewayClient {
authenticated: false,
@@ -898,7 +901,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS,
reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF,
negotiated_protocol: None,
shutdown,
task_client,
}
}
@@ -906,7 +909,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
self,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
shutdown: TaskClient,
task_client: TaskClient,
) -> GatewayClient<C, St> {
// invariants that can't be broken
// (unless somebody decided to expose some field that wasn't meant to be exposed)
@@ -930,7 +933,7 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
reconnection_attempts: self.reconnection_attempts,
reconnection_backoff: self.reconnection_backoff,
negotiated_protocol: self.negotiated_protocol,
shutdown,
task_client,
}
}
}
@@ -54,7 +54,7 @@ cw-controllers = { workspace = true }
prost = { workspace = true, default-features = false }
flate2 = { workspace = true }
sha2 = { version = "0.9.5" }
itertools = { version = "0.10" }
itertools = { workspace = true }
zeroize = { workspace = true, features = ["zeroize_derive"] }
cosmwasm-std = { workspace = true }
@@ -19,6 +19,7 @@ use nym_api_requests::models::{
RewardEstimationResponse, StakeSaturationResponse,
};
use nym_api_requests::nym_nodes::SkimmedNode;
use nym_http_api_client::UserAgent;
use nym_network_defaults::NymNetworkDetails;
use url::Url;
@@ -258,6 +259,16 @@ impl NymApiClient {
NymApiClient { nym_api }
}
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
.expect("invalid api url")
.with_user_agent(user_agent)
.build::<ValidatorClientError>()
.expect("failed to build nym api client");
NymApiClient { nym_api }
}
pub fn api_url(&self) -> &Url {
self.nym_api.current_url()
}
@@ -17,6 +17,7 @@ pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
pub use client::NymApiClient;
pub use client::{Client, CoconutApiClient, Config};
pub use nym_api_requests::*;
pub use nym_http_api_client::UserAgent;
#[cfg(feature = "http-client")]
pub use cosmrs::rpc::HttpClient as HttpRpcClient;
@@ -3,7 +3,7 @@
use crate::nyxd::cosmwasm_client::client_traits::CosmWasmClient;
use crate::nyxd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
use crate::nyxd::cosmwasm_client::logs::{self, parse_raw_logs};
use crate::nyxd::cosmwasm_client::logs::parse_raw_logs;
use crate::nyxd::cosmwasm_client::types::*;
use crate::nyxd::error::NyxdError;
use crate::nyxd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
@@ -19,6 +19,7 @@ use cosmrs::feegrant::{
};
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
use cosmrs::tendermint::abci::{Event, EventAttribute};
use cosmrs::tx::{self, Msg};
use cosmrs::{cosmwasm, AccountId, Any, Tx};
use log::debug;
@@ -51,6 +52,20 @@ fn single_unspecified_signer_auth(
}
.auth_info(empty_fee())
}
// Searches in events for an event of the given event type which contains an
// attribute for with the given key.
fn find_attribute<'a>(
events: &'a [Event],
event_type: &str,
attr_key: &str,
) -> Option<&'a EventAttribute> {
events
.iter()
.find(|attr| attr.kind == event_type)?
.attributes
.iter()
.find(|attr| attr.key == attr_key)
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
@@ -118,6 +133,7 @@ where
.check_response()?;
let logs = parse_raw_logs(tx_res.tx_result.log)?;
let events = tx_res.tx_result.events;
let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
@@ -127,7 +143,7 @@ where
// the reason I think unwrap here is fine is that if the transaction succeeded and those
// fields do not exist or code_id is not a number, there's no way we can recover, we're probably connected
// to wrong validator or something
let code_id = logs::find_attribute(&logs, "store_code", "code_id")
let code_id = find_attribute(&events, "store_code", "code_id")
.unwrap()
.value
.parse()
@@ -140,6 +156,7 @@ where
compressed_checksum,
code_id,
logs,
events,
transaction_hash: tx_res.hash,
gas_info,
})
@@ -182,6 +199,7 @@ where
.check_response()?;
let logs = parse_raw_logs(tx_res.tx_result.log)?;
let events = tx_res.tx_result.events;
let gas_info = GasInfo {
gas_wanted: tx_res.tx_result.gas_wanted.try_into().unwrap_or_default(),
gas_used: tx_res.tx_result.gas_used.try_into().unwrap_or_default(),
@@ -190,7 +208,7 @@ where
// the reason I think unwrap here is fine is that if the transaction succeeded and those
// fields do not exist or address is malformed, there's no way we can recover, we're probably connected
// to wrong validator or something
let contract_address = logs::find_attribute(&logs, "instantiate", "_contract_address")
let contract_address = find_attribute(&events, "instantiate", "_contract_address")
.unwrap()
.value
.parse()
@@ -199,6 +217,7 @@ where
Ok(InstantiateResult {
contract_address,
logs,
events,
transaction_hash: tx_res.hash,
gas_info,
})
@@ -231,6 +250,7 @@ where
};
Ok(ChangeAdminResult {
logs: parse_raw_logs(tx_res.tx_result.log)?,
events: tx_res.tx_result.events,
transaction_hash: tx_res.hash,
gas_info,
})
@@ -261,6 +281,7 @@ where
};
Ok(ChangeAdminResult {
logs: parse_raw_logs(tx_res.tx_result.log)?,
events: tx_res.tx_result.events,
transaction_hash: tx_res.hash,
gas_info,
})
@@ -298,6 +319,7 @@ where
};
Ok(MigrateResult {
logs: parse_raw_logs(tx_res.tx_result.log)?,
events: tx_res.tx_result.events,
transaction_hash: tx_res.hash,
gas_info,
})
@@ -335,6 +357,7 @@ where
};
Ok(ExecuteResult {
logs: parse_raw_logs(tx_res.tx_result.log)?,
events: tx_res.tx_result.events,
data: tx_res.tx_result.data.into(),
transaction_hash: tx_res.hash,
gas_info,
@@ -378,6 +401,7 @@ where
};
Ok(ExecuteResult {
logs: parse_raw_logs(tx_res.tx_result.log)?,
events: tx_res.tx_result.events,
data: tx_res.tx_result.data.into(),
transaction_hash: tx_res.hash,
gas_info,
@@ -35,6 +35,7 @@ pub fn find_attribute<'a>(
// these two functions were separated so that the internal logic could actually be tested
fn parse_raw_str_logs(raw: &str) -> Result<Vec<Log>, NyxdError> {
// From Cosmos SDK > 0.50 onwards, log field is not populated
if raw.is_empty() {
return Ok(Vec::new());
}
@@ -232,6 +232,8 @@ pub struct UploadResult {
pub logs: Vec<Log>,
pub events: Vec<abci::Event>,
/// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash,
@@ -269,6 +271,8 @@ pub struct InstantiateResult {
pub logs: Vec<Log>,
pub events: Vec<abci::Event>,
/// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash,
@@ -279,6 +283,8 @@ pub struct InstantiateResult {
pub struct ChangeAdminResult {
pub logs: Vec<Log>,
pub events: Vec<abci::Event>,
/// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash,
@@ -289,6 +295,8 @@ pub struct ChangeAdminResult {
pub struct MigrateResult {
pub logs: Vec<Log>,
pub events: Vec<abci::Event>,
/// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash,
@@ -301,6 +309,8 @@ pub struct ExecuteResult {
pub data: Vec<u8>,
pub events: Vec<abci::Event>,
/// Transaction hash (might be used as transaction ID)
pub transaction_hash: Hash,
@@ -29,7 +29,7 @@ time = { workspace = true, features = ["parsing", "formatting"] }
ts-rs = { workspace = true, optional = true }
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
time = { workspace = true, features = ["serde", "macros"] }
[features]
+5 -5
View File
@@ -12,16 +12,16 @@ aes = { workspace = true, optional = true }
bs58 = { workspace = true }
blake3 = { workspace = true, features = ["traits-preview"], optional = true }
ctr = { workspace = true, optional = true }
digest = { version = "0.10.3", optional = true }
digest = { workspace = true, optional = true }
generic-array = { workspace = true, optional = true }
hkdf = { workspace = true, optional = true }
hmac = { workspace = true, optional = true }
cipher = { workspace = true, optional = true }
x25519-dalek = { version = "2.0", optional = true, features = ["static_secrets"]}
ed25519-dalek = { version = "2.1", features = ["rand_core"], optional = true }
x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true }
ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true }
rand = { workspace = true, optional = true }
serde_bytes = { version = "0.11.6", optional = true }
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
subtle-encoding = { workspace = true, features = ["bech32-preview"] }
thiserror = { workspace = true }
zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] }
@@ -31,7 +31,7 @@ nym-sphinx-types = { path = "../nymsphinx/types", version = "0.2.0", default-fea
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
[features]
default = ["sphinx"]
+1 -1
View File
@@ -19,7 +19,7 @@ bs58 = { workspace = true }
lazy_static = { workspace = true }
rand = { version = "0.8.5", default-features = false}
rand_chacha = "0.3"
rand_chacha = { workspace = true }
rand_core = { workspace = true }
sha2 = "0.9"
serde = { workspace = true }
+2
View File
@@ -20,6 +20,8 @@ serde_json = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
nym-bin-common = { path = "../bin-common" }
# for request timeout until https://github.com/seanmonstar/reqwest/issues/1135 is fixed
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
+4
View File
@@ -14,6 +14,10 @@ use url::Url;
pub use reqwest::IntoUrl;
pub use user_agent::UserAgent;
mod user_agent;
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
pub type PathSegments<'a> = &'a [&'a str];
+56
View File
@@ -0,0 +1,56 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::fmt;
use http::HeaderValue;
use nym_bin_common::build_information::{BinaryBuildInformation, BinaryBuildInformationOwned};
#[derive(Clone, Debug)]
pub struct UserAgent {
pub application: String,
pub version: String,
pub platform: String,
pub git_commit: String,
}
impl fmt::Display for UserAgent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let abbreviated_commit = self.git_commit.chars().take(7).collect::<String>();
write!(
f,
"{}/{}/{}/{}",
self.application, self.version, self.platform, abbreviated_commit
)
}
}
impl TryFrom<UserAgent> for HeaderValue {
type Error = http::header::InvalidHeaderValue;
fn try_from(user_agent: UserAgent) -> Result<Self, Self::Error> {
HeaderValue::from_str(&user_agent.to_string())
}
}
impl From<BinaryBuildInformation> for UserAgent {
fn from(build_info: BinaryBuildInformation) -> Self {
UserAgent {
application: build_info.binary_name.to_string(),
version: build_info.build_version.to_string(),
platform: build_info.cargo_triple.to_string(),
git_commit: build_info.commit_sha.to_string(),
}
}
}
impl From<BinaryBuildInformationOwned> for UserAgent {
fn from(build_info: BinaryBuildInformationOwned) -> Self {
UserAgent {
application: build_info.binary_name,
version: build_info.build_version,
platform: build_info.cargo_triple,
git_commit: build_info.commit_sha,
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ bytes = { workspace = true }
nym-bin-common = { path = "../bin-common" }
nym-crypto = { path = "../crypto" }
nym-sphinx = { path = "../nymsphinx" }
rand = "0.8.5"
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
time = { workspace = true }
-9
View File
@@ -27,7 +27,6 @@ pub const COCONUT_DKG_CONTRACT_ADDRESS: &str =
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
@@ -110,10 +109,6 @@ pub fn export_to_env() {
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
);
set_var_to_default(
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
STATISTICS_SERVICE_DOMAIN_ADDRESS,
);
set_var_to_default(var_names::NYXD, NYXD_URL);
set_var_to_default(var_names::NYM_API, NYM_API);
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
@@ -155,10 +150,6 @@ pub fn export_to_env_if_not_set() {
var_names::REWARDING_VALIDATOR_ADDRESS,
REWARDING_VALIDATOR_ADDRESS,
);
set_var_conditionally_to_default(
var_names::STATISTICS_SERVICE_DOMAIN_ADDRESS,
STATISTICS_SERVICE_DOMAIN_ADDRESS,
);
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
-1
View File
@@ -19,7 +19,6 @@ pub const GROUP_CONTRACT_ADDRESS: &str = "GROUP_CONTRACT_ADDRESS";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "MULTISIG_CONTRACT_ADDRESS";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "COCONUT_DKG_CONTRACT_ADDRESS";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "STATISTICS_SERVICE_DOMAIN_ADDRESS";
pub const NYXD: &str = "NYXD";
pub const NYM_API: &str = "NYM_API";
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
+2 -2
View File
@@ -9,7 +9,7 @@ license.workspace = true
[dependencies]
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
itertools = "0.10"
itertools = { workspace = true }
digest = "0.9"
rand = "0.8"
thiserror = { workspace = true }
@@ -33,7 +33,7 @@ default-features = false
[dev-dependencies]
criterion = { workspace = true, features = ["html_reports"] }
doc-comment = { workspace = true }
rand_chacha = "0.3"
rand_chacha = { workspace = true }
[[bench]]
name = "benchmarks"
+1 -1
View File
@@ -9,7 +9,7 @@ repository = { workspace = true }
[dependencies]
rand = { workspace = true }
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" }
generic-array = { workspace = true, optional = true, features = ["serde"] }
thiserror = { workspace = true }
zeroize = { workspace = true }
@@ -24,4 +24,4 @@ nym-topology = { path = "../../topology" }
version = "0.2.83"
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = { workspace = true }
+1 -1
View File
@@ -17,7 +17,7 @@ cosmrs.workspace = true
eyre = { workspace = true }
futures.workspace = true
humantime = { workspace = true }
sha2 = "0.10.8"
sha2 = { workspace = true }
serde = { workspace = true, features = ["derive"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
tendermint.workspace = true
+1 -1
View File
@@ -8,7 +8,7 @@ license.workspace = true
[dependencies]
anyhow = { workspace = true }
dirs = "4.0"
dirs = { workspace = true }
futures = { workspace = true }
log = { workspace = true }
pin-project = { workspace = true }
+12 -2
View File
@@ -27,6 +27,7 @@ use nym_task::manager::TaskStatus;
use nym_task::{TaskClient, TaskHandle};
use anyhow::anyhow;
use nym_validator_client::UserAgent;
use std::error::Error;
use std::path::PathBuf;
@@ -61,6 +62,8 @@ pub struct NymClient<S> {
setup_method: GatewaySetup,
user_agent: UserAgent,
/// Optional path to a .json file containing standalone network details.
custom_mixnet: Option<PathBuf>,
}
@@ -74,11 +77,17 @@ where
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Sync + Send,
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
{
pub fn new(config: Config, storage: S, custom_mixnet: Option<PathBuf>) -> Self {
pub fn new(
config: Config,
storage: S,
user_agent: UserAgent,
custom_mixnet: Option<PathBuf>,
) -> Self {
NymClient {
config,
storage,
setup_method: GatewaySetup::MustLoad { gateway_id: None },
user_agent,
custom_mixnet,
}
}
@@ -226,7 +235,8 @@ where
let mut base_builder =
BaseClientBuilder::new(&self.config.base, self.storage, dkg_query_client)
.with_gateway_setup(self.setup_method);
.with_gateway_setup(self.setup_method)
.with_user_agent(self.user_agent);
if let Some(custom_mixnet) = &self.custom_mixnet {
base_builder = base_builder.with_stored_topology(custom_mixnet)?;
-20
View File
@@ -1,20 +0,0 @@
# Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
# SPDX-License-Identifier: Apache-2.0
[package]
name = "nym-statistics-common"
version = "1.0.1"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-trait = { workspace = true }
log = { workspace = true }
reqwest = { workspace = true, features = ["json"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]}
thiserror = { workspace = true }
tokio = { workspace = true, features = ["time"] }
-51
View File
@@ -1,51 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::StatsError;
use crate::StatsMessage;
pub const DEFAULT_STATISTICS_SERVICE_ADDRESS: &str = "127.0.0.1";
pub const DEFAULT_STATISTICS_SERVICE_PORT: u16 = 8091;
pub const STATISTICS_SERVICE_VERSION: &str = "/v1";
pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic";
pub async fn build_and_send_statistics_request(
msg: StatsMessage,
url: String,
) -> Result<(), StatsError> {
reqwest::Client::new()
.post(format!(
"{url}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
))
.json(&msg)
.send()
.await?;
Ok(())
}
pub fn build_statistics_request_bytes(msg: StatsMessage) -> Result<Vec<u8>, StatsError> {
let json_msg = msg.to_json()?;
let req = reqwest::Request::new(
reqwest::Method::POST,
reqwest::Url::parse(&format!(
"http://{DEFAULT_STATISTICS_SERVICE_ADDRESS}:{DEFAULT_STATISTICS_SERVICE_PORT}{STATISTICS_SERVICE_VERSION}/{STATISTICS_SERVICE_API_STATISTICS}"
))
.unwrap(),
);
let data = format!(
"{} {} {:?}\n\
Content-Type: application/json\n\
Content-Length: {}\n\n\
{}\n",
req.method().as_str(),
req.url().as_str(),
req.version(),
json_msg.len(),
json_msg
);
Ok(data.into_bytes())
}
-57
View File
@@ -1,57 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use async_trait::async_trait;
use log::error;
use sqlx::types::chrono::{DateTime, Utc};
use std::time::Duration;
use tokio::time;
use crate::error::StatsError;
use crate::StatsMessage;
const STATISTICS_TIMER_INTERVAL: Duration = Duration::from_secs(60);
#[async_trait]
pub trait StatisticsCollector {
async fn create_stats_message(
&self,
interval: Duration,
timestamp: DateTime<Utc>,
) -> StatsMessage;
async fn send_stats_message(&self, stats_message: StatsMessage) -> Result<(), StatsError>;
async fn reset_stats(&mut self);
}
pub struct StatisticsSender<T: StatisticsCollector> {
collector: T,
interval: Duration,
timestamp: DateTime<Utc>,
}
impl<T: StatisticsCollector> StatisticsSender<T> {
pub fn new(collector: T) -> Self {
StatisticsSender {
collector,
interval: STATISTICS_TIMER_INTERVAL,
timestamp: Utc::now(),
}
}
pub async fn run(&mut self) {
let mut interval = time::interval(self.interval);
loop {
interval.tick().await;
let stats_message = self
.collector
.create_stats_message(self.interval, self.timestamp)
.await;
if let Err(e) = self.collector.send_stats_message(stats_message).await {
error!("Statistics not sent: {}", e);
}
self.collector.reset_stats().await;
self.timestamp = Utc::now();
}
}
}
-13
View File
@@ -1,13 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use thiserror::Error;
#[derive(Debug, Error)]
pub enum StatsError {
#[error("Serde JSON error: {0}")]
SerdeJsonError(#[from] serde_json::Error),
#[error("Reqwest error: {0}")]
ReqwestError(#[from] reqwest::Error),
}
-65
View File
@@ -1,65 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use error::StatsError;
pub mod api;
pub mod collector;
pub mod error;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsMessage {
pub stats_data: Vec<StatsData>,
pub interval_seconds: u32,
pub timestamp: String,
}
impl StatsMessage {
pub fn to_json(&self) -> Result<String, StatsError> {
Ok(serde_json::to_string(self)?)
}
pub fn from_json(s: &str) -> Result<Self, StatsError> {
Ok(serde_json::from_str(s)?)
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum StatsData {
Service(StatsServiceData),
Gateway(StatsGatewayData),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsGatewayData {
pub gateway_id: String,
pub inbox_count: u32,
}
impl StatsGatewayData {
pub fn new(gateway_id: String, inbox_count: u32) -> Self {
StatsGatewayData {
gateway_id,
inbox_count,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StatsServiceData {
pub requested_service: String,
pub request_bytes: u32,
pub response_bytes: u32,
}
impl StatsServiceData {
pub fn new(requested_service: String, request_bytes: u32, response_bytes: u32) -> Self {
StatsServiceData {
requested_service,
request_bytes,
response_bytes,
}
}
}
+4 -4
View File
@@ -8,21 +8,21 @@ rust-version = "1.58"
license.workspace = true
[dependencies]
base64 = "0.21.4"
base64 = { workspace = true }
eyre = { workspace = true }
hmac = { workspace = true }
itertools = "0.11"
itertools = { workspace = true }
log = { workspace = true }
reqwest = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.8"
sha2 = { workspace = true }
strum = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
ts-rs = { workspace = true }
url = { workspace = true }
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
x25519-dalek = { workspace = true, features = ["static_secrets"] }
cosmwasm-std = { workspace = true }
cosmrs = { workspace = true }
+1 -3
View File
@@ -124,7 +124,6 @@ pub struct GatewayNetworkRequesterDetails {
pub encryption_key: String,
pub open_proxy: bool,
pub enabled_statistics: bool,
// just a convenience wrapper around all the keys
pub address: String,
@@ -142,8 +141,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails {
writeln!(f, "\tencryption key: {}", self.encryption_key)?;
writeln!(f, "\taddress: {}", self.address)?;
writeln!(f, "\tuses open proxy: {}", self.open_proxy)?;
writeln!(f, "\tsends statistics: {}", self.enabled_statistics)
writeln!(f, "\tuses open proxy: {}", self.open_proxy)
}
}
+1 -1
View File
@@ -122,7 +122,7 @@ pub async fn setup_gateway_from_api(
nym_apis: &[Url],
) -> Result<InitialisationResult, WasmCoreError> {
let mut rng = thread_rng();
let gateways = current_gateways(&mut rng, nym_apis).await?;
let gateways = current_gateways(&mut rng, nym_apis, None).await?;
setup_gateway_wasm(client_store, force_tls, chosen_gateway, &gateways).await
}
+2 -2
View File
@@ -25,13 +25,13 @@ nym-network-defaults = { path = "../network-defaults" }
## verify:
hmac = { workspace = true, optional = true }
sha2 = { version = "0.10.8", optional = true }
sha2 = { workspace = true, optional = true }
## openapi:
utoipa = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
x25519-dalek = { workspace = true, features = ["static_secrets"] }
[dev-dependencies]
rand = "0.8.5"
+1 -2
View File
@@ -10,8 +10,7 @@ pub use config::Config;
pub use error::Error;
pub use public_key::PeerPublicKey;
pub use registration::{
ClientMac, ClientMessage, ClientRegistrationResponse, GatewayClient, GatewayClientRegistry,
InitMessage, Nonce,
ClientMac, ClientMessage, GatewayClient, GatewayClientRegistry, InitMessage, Nonce,
};
#[cfg(feature = "verify")]
+19 -11
View File
@@ -7,6 +7,7 @@ use base64::{engine::general_purpose, Engine};
use dashmap::DashMap;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::time::SystemTime;
use std::{fmt, ops::Deref, str::FromStr};
#[cfg(feature = "verify")]
@@ -18,13 +19,15 @@ use sha2::Sha256;
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
pub type PendingRegistrations = DashMap<PeerPublicKey, RegistrationData>;
pub type PrivateIPs = DashMap<IpAddr, Free>;
pub type PrivateIPs = DashMap<IpAddr, Taken>;
#[cfg(feature = "verify")]
pub type HmacSha256 = Hmac<Sha256>;
pub type Nonce = u64;
pub type Free = bool;
pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
@@ -32,6 +35,7 @@ pub type Free = bool;
pub enum ClientMessage {
Initial(InitMessage),
Final(GatewayClient),
Query(PeerPublicKey),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@@ -53,21 +57,25 @@ impl InitMessage {
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub enum ClientRegistrationResponse {
PendingRegistration(RegistrationData),
Registered,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct RegistrationData {
pub nonce: u64,
pub gateway_data: GatewayClient,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegistredData {
pub pub_key: PeerPublicKey,
pub private_ip: IpAddr,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RemainingBandwidthData {
pub available_bandwidth: u64,
pub suspended: bool,
}
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
/// Gateway/Nym node can then verify pub_key payload using the same process
#[derive(Serialize, Deserialize, Debug, Clone)]
+4 -2
View File
@@ -11,18 +11,20 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
base64 = "0.21.3"
base64 = { workspace = true }
chrono = { workspace = true }
dashmap = { workspace = true }
defguard_wireguard_rs = { workspace = true }
# The latest version on crates.io at the time of writing this (6.0.0) has a
# version mismatch with x25519-dalek/curve25519-dalek that is resolved in the
# latest commit. So pick that for now.
x25519-dalek = "2.0.0"
x25519-dalek = { workspace = true }
ip_network = { workspace = true }
log.workspace = true
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
nym-network-defaults = { path = "../network-defaults" }
nym-task = { path = "../task" }
nym-wireguard-types = { path = "../wireguard-types" }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] }
tokio-stream = { workspace = true }
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("peers in wireguard don't match with in-memory ")]
PeerMismatch,
#[error("{0}")]
Defguard(#[from] defguard_wireguard_rs::error::WireguardInterfaceError),
}
+25 -14
View File
@@ -1,3 +1,6 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
// #![warn(clippy::pedantic)]
// #![warn(clippy::expect_used)]
@@ -6,13 +9,14 @@
use dashmap::DashMap;
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask, WGApi};
use nym_crypto::asymmetric::encryption::KeyPair;
use nym_wireguard_types::{Config, Error, GatewayClient, GatewayClientRegistry};
use peer_controller::PeerControlMessage;
use nym_wireguard_types::{Config, Error, GatewayClient, GatewayClientRegistry, PeerPublicKey};
use peer_controller::PeerControlRequest;
use std::sync::Arc;
use tokio::sync::mpsc::{self, UnboundedReceiver};
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
const WG_TUN_NAME: &str = "nymwg";
pub(crate) mod error;
pub mod peer_controller;
pub struct WgApiWrapper {
@@ -39,14 +43,14 @@ pub struct WireguardGatewayData {
config: Config,
keypair: Arc<KeyPair>,
client_registry: Arc<GatewayClientRegistry>,
peer_tx: mpsc::UnboundedSender<PeerControlMessage>,
peer_tx: UnboundedSender<PeerControlRequest>,
}
impl WireguardGatewayData {
pub fn new(
config: Config,
keypair: Arc<KeyPair>,
) -> (Self, mpsc::UnboundedReceiver<PeerControlMessage>) {
) -> (Self, UnboundedReceiver<PeerControlRequest>) {
let (peer_tx, peer_rx) = mpsc::unbounded_channel();
(
WireguardGatewayData {
@@ -75,20 +79,26 @@ impl WireguardGatewayData {
let mut peer = Peer::new(Key::new(client.pub_key.to_bytes()));
peer.allowed_ips
.push(IpAddrMask::new(client.private_ip, 32));
let msg = PeerControlMessage::AddPeer(peer);
let msg = PeerControlRequest::AddPeer(peer);
self.peer_tx.send(msg).map_err(|_| Error::PeerModifyStopped)
}
pub fn remove_peer(&self, client: &GatewayClient) -> Result<(), Error> {
let key = Key::new(client.pub_key().to_bytes());
let msg = PeerControlMessage::RemovePeer(key);
let msg = PeerControlRequest::RemovePeer(key);
self.peer_tx.send(msg).map_err(|_| Error::PeerModifyStopped)
}
pub fn query_bandwidth(&self, peer_public_key: PeerPublicKey) -> Result<(), Error> {
let key = Key::new(peer_public_key.to_bytes());
let msg = PeerControlRequest::QueryBandwidth(key);
self.peer_tx.send(msg).map_err(|_| Error::PeerModifyStopped)
}
}
pub struct WireguardData {
pub inner: WireguardGatewayData,
pub peer_rx: UnboundedReceiver<PeerControlMessage>,
pub peer_rx: UnboundedReceiver<PeerControlRequest>,
}
/// Start wireguard device
@@ -96,6 +106,7 @@ pub struct WireguardData {
pub async fn start_wireguard(
task_client: nym_task::TaskClient,
wireguard_data: WireguardData,
control_tx: UnboundedSender<peer_controller::PeerControlResponse>,
) -> Result<std::sync::Arc<WgApiWrapper>, Box<dyn std::error::Error + Send + Sync + 'static>> {
use base64::{prelude::BASE64_STANDARD, Engine};
use defguard_wireguard_rs::{InterfaceConfiguration, WireguardInterfaceApi};
@@ -135,13 +146,13 @@ pub async fn start_wireguard(
wg_api.configure_peer_routing(&[catch_all_peer])?;
let wg_api = std::sync::Arc::new(WgApiWrapper::new(wg_api));
let mut controller = PeerController::new(wg_api.clone(), wireguard_data.peer_rx);
let mut controller = PeerController::new(
wg_api.clone(),
interface_config.peers,
wireguard_data.peer_rx,
control_tx,
);
tokio::spawn(async move { controller.run(task_client).await });
Ok(wg_api)
}
#[cfg(not(target_os = "linux"))]
pub async fn start_wireguard() {
todo!("WireGuard is currently only supported on Linux");
}
+128 -37
View File
@@ -1,91 +1,182 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::{
sync::Arc,
time::{Duration, SystemTime},
};
use defguard_wireguard_rs::{
host::{Host, Peer},
key::Key,
WGApi, WireguardInterfaceApi,
};
use chrono::{Timelike, Utc};
use defguard_wireguard_rs::{host::Peer, key::Key, WireguardInterfaceApi};
use nym_wireguard_types::registration::{RemainingBandwidthData, BANDWIDTH_CAP_PER_DAY};
use std::time::SystemTime;
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::sync::mpsc;
use tokio_stream::{wrappers::IntervalStream, StreamExt};
use crate::error::Error;
use crate::WgApiWrapper;
const DEFAULT_PEER_TIMEOUT: Duration = Duration::from_secs(60 * 60); // 1 hour
// To avoid any problems, keep this stale check time bigger (>2x) then the bandwidth cap
// reset time (currently that one is 24h, at UTC midnight)
const DEFAULT_PEER_TIMEOUT: Duration = Duration::from_secs(60 * 60 * 24 * 3); // 3 days
const DEFAULT_PEER_TIMEOUT_CHECK: Duration = Duration::from_secs(60); // 1 minute
pub enum PeerControlMessage {
pub enum PeerControlRequest {
AddPeer(Peer),
RemovePeer(Key),
QueryBandwidth(Key),
}
pub enum PeerControlResponse {
AddPeer {
success: bool,
},
RemovePeer {
success: bool,
},
QueryBandwidth {
bandwidth_data: Option<RemainingBandwidthData>,
},
}
pub struct PeerController {
peer_rx: mpsc::UnboundedReceiver<PeerControlMessage>,
request_rx: mpsc::UnboundedReceiver<PeerControlRequest>,
response_tx: mpsc::UnboundedSender<PeerControlResponse>,
wg_api: Arc<WgApiWrapper>,
timeout_check_interval: IntervalStream,
active_peers: HashMap<Key, Peer>,
suspended_peers: HashMap<Key, Peer>,
last_seen_bandwidth: HashMap<Key, u64>,
}
impl PeerController {
pub fn new(
wg_api: Arc<WgApiWrapper>,
peer_rx: mpsc::UnboundedReceiver<PeerControlMessage>,
peers: Vec<Peer>,
request_rx: mpsc::UnboundedReceiver<PeerControlRequest>,
response_tx: mpsc::UnboundedSender<PeerControlResponse>,
) -> Self {
let timeout_check_interval = tokio_stream::wrappers::IntervalStream::new(
tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK),
);
let active_peers = peers
.into_iter()
.map(|peer| (peer.public_key.clone(), peer))
.collect();
PeerController {
wg_api,
peer_rx,
request_rx,
response_tx,
timeout_check_interval,
active_peers,
suspended_peers: HashMap::new(),
last_seen_bandwidth: HashMap::new(),
}
}
fn remove_stale_peers(wg_api: &WGApi, host: Host) {
let current_timestamp = SystemTime::now();
for (key, peer) in host.peers.iter() {
if let Some(timestamp) = peer.last_handshake {
if let Ok(duration_since_handshake) = current_timestamp.duration_since(timestamp) {
if duration_since_handshake > DEFAULT_PEER_TIMEOUT {
if let Err(e) = wg_api.remove_peer(key) {
log::error!("Could not remove stale peer: {:?}", e);
} else {
log::debug!("Removed stale peer {:?}", key);
}
}
fn check_stale_peer(&self, peer: &Peer, current_timestamp: SystemTime) -> Result<bool, Error> {
if let Some(timestamp) = peer.last_handshake {
if let Ok(duration_since_handshake) = current_timestamp.duration_since(timestamp) {
if duration_since_handshake > DEFAULT_PEER_TIMEOUT {
self.wg_api.inner.remove_peer(&peer.public_key)?;
return Ok(true);
}
}
}
Ok(false)
}
fn check_suspend_peer(&mut self, peer: &Peer) -> Result<(), Error> {
let prev_peer = self
.active_peers
.get(&peer.public_key)
.ok_or(Error::PeerMismatch)?;
let data_usage =
(peer.rx_bytes + peer.tx_bytes).saturating_sub(prev_peer.rx_bytes + prev_peer.tx_bytes);
if data_usage > BANDWIDTH_CAP_PER_DAY {
self.wg_api.inner.remove_peer(&peer.public_key)?;
let (moved_key, moved_peer) = self
.active_peers
.remove_entry(&peer.public_key)
.ok_or(Error::PeerMismatch)?;
self.suspended_peers.insert(moved_key, moved_peer);
}
Ok(())
}
fn check_peers(&mut self) -> Result<(), Error> {
// Add 10 seconds to cover edge cases. At worst, we give ten free seconds worth of bandwidth
// by resetting the bandwidth twice
let reset = Utc::now().num_seconds_from_midnight() as u64
<= DEFAULT_PEER_TIMEOUT_CHECK.as_secs() + 10;
if reset {
for (_, peer) in self.suspended_peers.drain() {
self.wg_api.inner.configure_peer(&peer)?;
}
}
let host = self.wg_api.inner.read_interface_data()?;
self.last_seen_bandwidth = host
.peers
.iter()
.map(|(key, peer)| (key.clone(), peer.rx_bytes + peer.tx_bytes))
.collect();
if reset {
self.active_peers = host.peers;
} else {
let current_timestamp = SystemTime::now();
for peer in host.peers.values() {
if !self.check_stale_peer(peer, current_timestamp)? {
self.check_suspend_peer(peer)?;
}
}
}
Ok(())
}
pub async fn run(&mut self, mut task_client: nym_task::TaskClient) {
loop {
tokio::select! {
_ = self.timeout_check_interval.next() => {
match self.wg_api.inner.read_interface_data() {
Ok(host) => Self::remove_stale_peers(&self.wg_api.inner, host),
Err(e) => { log::error!("Could not read peer data: {:?}", e); },
if let Err(e) = self.check_peers() {
log::error!("Error while periodically checking peers: {:?}", e);
}
}
_ = task_client.recv() => {
log::trace!("PeerController handler: Received shutdown");
break;
}
msg = self.peer_rx.recv() => {
msg = self.request_rx.recv() => {
match msg {
Some(PeerControlMessage::AddPeer(peer)) => {
if let Err(e) = self.wg_api.inner.configure_peer(&peer) {
Some(PeerControlRequest::AddPeer(peer)) => {
let success = if let Err(e) = self.wg_api.inner.configure_peer(&peer) {
log::error!("Could not configure peer: {:?}", e);
}
false
} else {
self.active_peers.insert(peer.public_key.clone(), peer);
true
};
self.response_tx.send(PeerControlResponse::AddPeer { success }).ok();
}
Some(PeerControlMessage::RemovePeer(peer_pubkey)) => {
if let Err(e) = self.wg_api.inner.remove_peer(&peer_pubkey) {
Some(PeerControlRequest::RemovePeer(peer_pubkey)) => {
let success = if let Err(e) = self.wg_api.inner.remove_peer(&peer_pubkey) {
log::error!("Could not remove peer: {:?}", e);
}
false
} else {
self.active_peers.remove(&peer_pubkey);
self.suspended_peers.remove(&peer_pubkey);
true
};
self.response_tx.send(PeerControlResponse::RemovePeer { success }).ok();
}
Some(PeerControlRequest::QueryBandwidth(peer_pubkey)) => {
let msg = if self.suspended_peers.contains_key(&peer_pubkey) {
PeerControlResponse::QueryBandwidth { bandwidth_data: Some(RemainingBandwidthData{ available_bandwidth: 0, suspended: true }) }
} else if let Some(&consumed_bandwidth) = self.last_seen_bandwidth.get(&peer_pubkey) {
PeerControlResponse::QueryBandwidth { bandwidth_data: Some(RemainingBandwidthData{ available_bandwidth: BANDWIDTH_CAP_PER_DAY - consumed_bandwidth, suspended: false })}
} else {
PeerControlResponse::QueryBandwidth { bandwidth_data: None }
};
self.response_tx.send(msg).ok();
}
None => {
log::trace!("PeerController [main loop]: stopping since channel closed");
+39 -33
View File
@@ -3,7 +3,7 @@ title = "Nym Docs"
authors = ["Max Hampshire, Serinko, Alexia Lorenza Martinel"]
description = "Nym technical documentation"
language = "en"
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
multilingual = false # for the moment - ideally work on chinese, brazillian ,portugese spanish next
src = "src"
[rust]
@@ -14,17 +14,19 @@ edition = "2018"
#################
[preprocessor.theme]
sidebar-width = "280px"
content-max-width = "70%"
content-main-margin-left = "5%"
content-main-margin-right = "5%"
root-font-size = "70%"
# DO NOT CHANGE or you might overwrite the custom hbs file
turn-off = false
pagetoc = true
sidebar-width = "280px"
content-max-width = "80%"
root-font-size = "70%"
# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book,
# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`.
# this is because of a bug in the `mdbook-theme` plugin
turn-off = true
[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install`
# https://gitlab.com/tglman/mdbook-variables/
[preprocessor.variables.variables]
@@ -53,52 +55,56 @@ renderer = ["html"]
#########
[build]
build-dir = "book" # the directory where the output is placed
create-missing = true # whether or not to create missing pages
use-default-preprocessors = true # use the default preprocessors
extra-watch-dirs = [] # directories to watch for triggering builds
build-dir = "book" # the directory where the output is placed
create-missing = true # whether or not to create missing pages
use-default-preprocessors = true # use the default preprocessors
extra-watch-dirs = [] # directories to watch for triggering builds
##########
# OUTPUT #
##########
[output.html]
theme = "nym_themes"
theme = "themes"
default-theme = "coal"
preferred-dark-theme = "coal"
curly-quotes = true
copy-fonts = true
no-section-label = false
additional-css = ["./nym_themes/custom.css", "./nym_themes/mdbook-admonish.css", "./nym_themes/pagetoc.css"]
additional-js = ["./nym_themes/pagetoc.js"]
additional-css = [
"./themes/custom.css",
"./themes/mdbook-admonish.css",
"./themes/pagetoc.css",
]
additional-js = ["./themes/pagetoc.js"]
git-repository-url = "https://github.com/nymtech/nym"
git-repository-icon = "fa-github"
input-404 = "not-found.md"
[output.html.fold]
enable = true # whether or not to enable section folding
level = 0 # the depth to start folding
enable = true # whether or not to enable section folding
level = 0 # the depth to start folding
# controlling rust sample code blocks
[output.html.playground]
editable = false # allows editing the source code
copyable = true # include the copy button for copying code snippets
copy-js = true # includes the JavaScript for the code editor
line-numbers = true # displays line numbers for editable code
runnable = true # displays a run button for rust code
editable = false # allows editing the source code
copyable = true # include the copy button for copying code snippets
copy-js = true # includes the JavaScript for the code editor
line-numbers = true # displays line numbers for editable code
runnable = true # displays a run button for rust code
# options for the built in text search
[output.html.search]
enable = true # enables the search feature
limit-results = 30 # maximum number of search results
teaser-word-count = 30 # number of words used for a search result teaser
use-boolean-and = true # multiple search terms must all match
boost-title = 2 # ranking boost factor for matches in headers
boost-hierarchy = 1 # ranking boost factor for matches in page names
boost-paragraph = 1 # ranking boost factor for matches in text
expand = true # partial words will match longer terms
heading-split-level = 3 # link results to heading levels
copy-js = true # include Javascript code for search
enable = true # enables the search feature
limit-results = 30 # maximum number of search results
teaser-word-count = 30 # number of words used for a search result teaser
use-boolean-and = true # multiple search terms must all match
boost-title = 2 # ranking boost factor for matches in headers
boost-hierarchy = 1 # ranking boost factor for matches in page names
boost-paragraph = 1 # ranking boost factor for matches in text
expand = true # partial words will match longer terms
heading-split-level = 3 # link results to heading levels
copy-js = true # include Javascript code for search
[output.linkcheck]
warning-policy = "warn"
+35 -70
View File
@@ -1,94 +1,59 @@
#
# Summary
- [Introduction](introduction.md)
- [Clients Overview - Start Here!](clients-overview.md)
# Infrastructure
# SDKs
- [Rust SDK](sdk/rust/rust.md)
- [Message Types](sdk/rust/message-types.md)
- [Message Helpers](sdk/rust/message-helpers.md)
- [Troubleshooting](sdk/rust/troubleshooting.md)
- [Examples](sdk/rust/examples.md)
- [Simple Send](sdk/rust/examples/simple.md)
- [Create and Store Keys](sdk/rust/examples/keys.md)
- [Manual Storage](sdk/rust/examples/storage.md)
- [Anonymous Replies](sdk/rust/examples/surbs.md)
- [Use Custom Network Topology](sdk/rust/examples/custom-network.md)
- [Socks Proxy](sdk/rust/examples/socks.md)
- [Split Send and Receive](sdk/rust/examples/split-send.md)
- [Testnet Bandwidth Cred](sdk/rust/examples/credential.md)
- [Example Cargo file](sdk/rust/examples/cargo.md)
- [Typescript SDK](sdk/typescript.md)
- [What is Nym?](infrastructure/nym.md)
- [Nym vs Other Systems](infrastructure/nym-vs-others.md)
- [Node Types](infrastructure/node-types.md)
# Binaries
- [Pre-built Binaries](binaries/pre-built-binaries.md)
- [Building from Source](binaries/building-nym.md)
# Quickstart
# Standalone Clients
- [Websocket Client](clients/websocket-client.md)
- [Setup & Run](clients/websocket/setup.md)
- [Configuration](clients/websocket/config.md)
- [Using Your Client](clients/websocket/usage.md)
- [Examples](clients/websocket/examples.md)
- [Socks5 Client](clients/socks5-client.md)
- [Setup & Run](clients/socks5/setup.md)
- [Using Your Client](clients/socks5/usage.md)
- [Webassembly Client](clients/webassembly-client.md)
- [Overview](quickstart/overview.md)
- [Chat demo (webapp)](quickstart/chat-demo.md)
- [Coconut Credential Playground (webapp)](quickstart/cred-playground.md)
- [SOCKS Proxy (CLI)](quickstart/socks-proxy.md)
# User Manuals
- [NymVPN alpha](nymvpn/intro.md)
- [CLI](nymvpn/cli.md)
<!-- OUTDATED STUFF:
- [NymConnect X Monero](tutorials/monero.md)
- [NymConnect X Matrix](tutorials/matrix.md)
- [NymConnect X Telegram](tutorials/telegram.md)
- [NymConnect X Electrum](tutorials/electrum.md)
- [NymConnect X Firo wallet](tutorials/firo.md)
-->
# Tutorials
- [Stub: Updates Coming Soon!](./tutorials/coming-soon.md)
# Code Examples
- [Custom Service Providers](examples/custom-services.md)
- [Apps Using Network Requesters](examples/using-nrs.md)
- [Browser only](examples/browser-only.md)
- [Monorepo examples](examples/monorepo-examples.md)
# Integrations
- [Integration Options](integrations/integration-options.md)
[//]: # (- [Mixnet Integration]&#40;integrations/mixnet-integration.md&#41;)
- [Payment Integration](integrations/payment-integration.md)
# Tutorials
- [Rust SDK](tutorials/rust-sdk.md)
- [Blockchain Service pt1](tutorials/cosmos-service/intro.md)
- [Tutorial Overview](tutorials/cosmos-service/overview.md)
- [Preparing Your Environment](tutorials/cosmos-service/preparing-env.md)
- [Preparing Your Lib](tutorials/cosmos-service/lib.md)
- [Preparing Your Client](tutorials/cosmos-service/client.md)
- [Preparing Your Client pt2](tutorials/cosmos-service/client-src.md)
- [Preparing Your Service](tutorials/cosmos-service/service.md)
- [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md)
- [Querying the Chain](tutorials/cosmos-service/querying.md)
- [Typescript](tutorials/typescript.md)
- [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md)
- [Tutorial Overview](tutorials/simple-service-provider/overview.md)
- [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md)
- [Building Your User Client](tutorials/simple-service-provider/user-client.md)
- [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md)
- [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md)
- [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md)
[//]: # (TODO make generic )
[//]: # (# Shipyard Builders Hackathon 2023 )
[//]: # (- [General Info & Resources]&#40;shipyard/general.md&#41;)
[//]: # (- [Hackathon Challenges]&#40;shipyard/challenges-overview.md&#41;)
[//]: # (- [A Note on Infrastructure]&#40;shipyard/infra.md&#41;)
[//]: # (- [Submission Guidelines]&#40;shipyard/guidelines.md&#41;)
<!-- Commenting out as a lot of the stuff is deprecated, can be purged as a part of the large overhaul
# Events
- [Web3Privacy Now](./events/web3-privacy.md)
- [HCPP23-serinko](./events/hcpp23-serinko.md)
- [HCPP23-max](./events/hcpp23-max.md)
-->
# FAQ
- [General](faq/general-faq.md)
- [Integrations](faq/integrations-faq.md)
- [Rewards & Token](faq/rewards-faq.md)
# Community Resources
- [Nym DevRel AMAs](community-resources/ama.md)
- [Community Applications and Guides](community-resources/community-applications-and-guides.md)
- [Change Service Grantee Information](info-request.md)
# User Manuals
- [NymVPN alpha](nymvpn/intro.md)
- [CLI](nymvpn/cli.md)
---
# Misc.
@@ -0,0 +1,61 @@
# Building from Source
> Nym runs on Mac OS X, Linux, and Windows. All nodes **except the Desktop Wallet and NymConnect** on Windows should be considered experimental - it works fine if you're an app developer but isn't recommended for running nodes.
## Building Nym
Nym has two main codebases:
- the [Nym platform](https://github.com/nymtech/nym), written in Rust. This contains all of our code _except_ for the validators.
- the [Nym validators](https://github.com/nymtech/nyxd), written in Go.
> This page details how to build the main Nym platform code.
## Prerequisites
- Debian/Ubuntu: `pkg-config`, `build-essential`, `libssl-dev`, `curl`, `jq`, `git`
```
apt install pkg-config build-essential libssl-dev curl jq git
```
- Arch/Manjaro: `base-devel`
```
pacman -S base-devel
```
- Mac OS X: `pkg-config` , `brew`, `openss1`, `protobuf`, `curl`, `git`
Running the following the script installs Homebrew and the above dependencies:
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
- `Rust & cargo >= {{minimum_rust_version}}`
We recommend using the [Rust shell script installer](https://www.rust-lang.org/tools/install). Installing cargo from your package manager (e.g. `apt`) is not recommended as the packaged versions are usually too old.
If you really don't want to use the shell script installer, the [Rust installation docs](https://forge.rust-lang.org/infra/other-installation-methods.html) contain instructions for many platforms.
## Download and build Nym binaries
The following commands will compile binaries into the `nym/target/release` directory:
```sh
rustup update
git clone https://github.com/nymtech/nym.git
cd nym
git reset --hard # in case you made any changes on your branch
git pull # in case you've checked it out before
git checkout master # master branch has the latest release version: `develop` will most likely be incompatible with deployed public networks
cargo build --release # build your binaries with **mainnet** configuration
```
Quite a bit of stuff gets built. The key working parts for devs are the Client binaries and the CLI tool:
* [websocket client](../clients/websocket-client.md): `nym-client`
* [socks5 client](../clients/socks5-client.md): `nym-socks5-client`
* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.md): `nym-cli`
> You cannot build from GitHub's .zip or .tar.gz archive files on the releases page - the Nym build scripts automatically include the current git commit hash in the built binary during compilation, so the build will fail if you use the archive code (which isn't a Git repository). Check the code out from github using `git clone` instead.
@@ -0,0 +1,6 @@
# Pre-built Binaries
The [Github releases page](https://github.com/nymtech/nym/releases) has pre-built binaries which should work on Ubuntu 20.04 and other Debian-based systems, but at this stage cannot be guaranteed to work everywhere.
If the pre-built binaries don't work or are unavailable for your system, you will need to build the platform yourself.
@@ -0,0 +1,49 @@
# Clients Overview
A large proportion of the Nym mixnet's functionality is implemented client-side.
Clients perform the following actions on behalf of users:
* determine network topology - what mixnodes exist, what their keys are, etc.
* register with a gateway
* authenticate with a gateway
* receive and decrypt messages from the gateway
* create layer-encrypted Sphinx packets
* send Sphinx packets with real messages
* send Sphinx packet _cover traffic_ when no real messages are being sent
* retransmit un-acknowledged packet sends - if a client sends 100 packets to a gateway, but only receives an acknowledgement ('ack') for 95 of them, it will resend those 5 packets to the gateway again, to make sure that all packets are received.
> As a developer, you'll want to use a Nym client to send your application network traffic through the mixnet; whether that is an RPC call, a TCP connection request, or treating it like a UDP pipe, you need to send whatever bytes your app needs to send through it. However, unlike (e.g.) a TCP Socket, Nym client communication is message-based, so you cannot (yet) simply plug-and-play using the mixnet as a seamless drop-in replacement. We are currently working on stream-like abstractions for ease of integration with the Rust SDK.
## Types of Nym clients
At present, there are three Nym clients:
- the websocket (native) client
- the SOCKS5 client
- the wasm (webassembly) client
You need to choose which one you want incorporate into your app. Which one you use will depend largely on your preferred programming style and the purpose of your app.
### The websocket client
Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**.
> Rust developers can import websocket client functionality into their code via the [Rust SDK](sdk/rust/rust.md).
### The webassembly client
If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client.
It's packaged and [available on the npm registry](https://www.npmjs.com/package/@nymproject/nym-client-wasm), so you can `npm install` it into your JavaScript or TypeScript application.
> The webassembly client is most easily used via the [Typescript SDK](sdk/typescript.md). Typescript developers who wish to send API requests through the mixnet can can also check the [`mixfetch`]() package.
### The SOCKS5 client
The `nym-socks5-client` is useful for allowing existing applications to use the Nym mixnet without any code changes. All that's necessary is that they can use one of the SOCKS5, SOCKS4a, or SOCKS4 proxy protocols (which many applications can - crypto wallets, browsers, chat applications etc).
When used as a standalone client, it's less flexible as a way of writing custom applications than the other clients, but able to be used to proxy application traffic through the mixnet without having to make any code changes.
> Rust developers can import socks client functionality into their code via the [Rust SDK](sdk/rust/rust.md).
## Commonalities between clients
All Nym client packages present basically the same capabilities to the privacy application developer. They need to run as a persistent process in order to stay connected and ready to receive any incoming messages from their gateway nodes. They register and authenticate to gateways, and encrypt Sphinx packets.
@@ -25,14 +25,14 @@ You need to choose which one you want incorporate into your app. Which one you u
### The websocket client
Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**.
_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_.
> Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md).
### The webassembly client
If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client.
It's packaged and [available on the npm registry](https://www.npmjs.com/package/@nymproject/nym-client-wasm), so you can `npm install` it into your JavaScript or TypeScript application.
_The webassembly client is most easily used via the [Typescript SDK](../sdk/typescript.md)_.
> The webassembly client is most easily used via the [Typescript SDK](../sdk/typescript.md). Typescript developers who wish to send API requests through the mixnet can can also check the [`mixfetch`]() package.
### The SOCKS5 client
The `nym-socks5-client` is useful for allowing existing applications to use the Nym mixnet without any code changes. All that's necessary is that they can use one of the SOCKS5, SOCKS4a, or SOCKS4 proxy protocols (which many applications can - crypto wallets, browsers, chat applications etc).
@@ -1,6 +1,6 @@
# Socks5 Client
> The Nym socks5 client was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code on this page, go there first.
> The Nym Socks5 Client was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code on this page, go there first.
## Current version
```
@@ -60,7 +60,7 @@ There are 2 pieces of software that work together to send SOCKS traffic through
The `nym-socks5-client` allows you to do the following from your local machine:
* Take a TCP data stream from a application that can send traffic via SOCKS5.
* Chop up the TCP stream into multiple Sphinx packets, assigning sequence numbers to them, while leaving the TCP connection open for more data
* Send the Sphinx packets through the mixnet to a [network requester](../nodes/network-requester.md). Packets are shuffled and mixed as they transit the mixnet.
* Send the Sphinx packets through the mixnet to a [network requester](https://nymtech.net/operators/nodes/network-requester.md). Packets are shuffled and mixed as they transit the mixnet.
The `nym-network-requester` then reassembles the original TCP stream using the packets' sequence numbers, and make the intended request. It will then chop up the response into Sphinx packets and send them back through the mixnet to your `nym-socks5-client`. The application will then receive its data, without even noticing that it wasn't talking to a "normal" SOCKS5 proxy!
@@ -100,11 +100,11 @@ Before you can use the client, you need to initalise a new instance of it, which
The `--id` in the example above is a local identifier so that you can name your clients and keep track of them on your local system; it is **never** transmitted over the network.
The `--use-reply-surbs` field denotes whether you wish to send [SURBs](../architecture/traffic-flow.md#private-replies-using-surbs) along with your request. It defaults to `false`, we are explicitly setting it as `true`. It defaults to `false` for compatibility with older versions of the [Network Requester](../nodes/network-requester.md).
The `--use-reply-surbs` field denotes whether you wish to send [SURBs](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) along with your request. It defaults to `false`, we are explicitly setting it as `true`. It defaults to `false` for compatibility with older versions of the [Network Requester](https://nymtech.net/nodes/network-requester.md).
The `--provider` field needs to be filled with the Nym address of a Network Requester that can make network requests on your behalf. If you don't want to [run your own](../nodes/network-requester.md) you can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/service-providers) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [this list](https://harbourmaster.nymtech.net/).
The `--provider` field needs to be filled with the Nym address of a Network Requester that can make network requests on your behalf. If you don't want to [run your own](https://nymtech.net/operators/nodes/network-requester.md) you can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/service-providers) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [this list](https://harbourmaster.nymtech.net/).
Since the nodes on this list are the infrastructure for [Nymconnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html) they will support all apps on the [default whitelist](../nodes/network-requester.md#network-requester-whitelist): Keybase, Telegram, Electrum, Blockstream Green, and Helios.
Since the nodes on this list are the infrastructure for [Nymconnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html) they will support all apps on the [default whitelist](https://nymtech.net/operators/nodes/network-requester.md#network-requester-whitelist): Keybase, Telegram, Electrum, Blockstream Green, and Helios.
#### Choosing a Gateway
By default - as in the example above - your client will choose a random gateway to connect to.
@@ -1,4 +1,4 @@
# SOCKS Proxy (CLI)
# Setup
> `nym-socks5-client` now also supports SOCKS4 and SOCKS4A protocols as well as SOCKS5.
@@ -39,33 +39,4 @@ Now your client is initialised, start it with the following:
./nym-socks5-client run --id <ID>
```
## Proxying traffic
After completing the steps above, your local `nym-socks5-client` will be listening on `localhost:1080` ready to proxy traffic to the Network Requester set as the `--provider` when initialising.
When trying to connect your app, generally the proxy settings are found in `settings->advanced` or `settings->connection`.
Here is an example of setting the proxy connecting in Blockstream Green:
![Blockstream Green settings](../images/blockstream-green.gif)
Most wallets and other applications will work basically the same way: find the network proxy settings, enter the proxy url (host: **localhost**, port: **1080**).
In some other applications, this might be written as **localhost:1080** if there's only one proxy entry field.
## Supported Applications
Any application which can be redirected over Socks5 proxy should work. Nym community has been successfully running over Nym Mixnet these applications:
- Bitcoin Electrum wallet
- Monero wallet (GUI and CLI with monerod)
- Telegram chat
- Element/Matrix chat
- Firo wallet
- ircd chat
- Blockstream Green
Keep in mind that Nym has been developing a new client **[NymVPN](https://nymvpn.com) (GUI and CLI) routing all users traffic through the Mixnet.**
## Further reading
If you want to dig more into the architecture and use of the socks5 client check out its documentation [here](https://nymtech.net/docs/clients/socks5-client.html).
@@ -0,0 +1,33 @@
# Using Your Client
## Proxying traffic
After completing the steps above, your local `nym-socks5-client` will be listening on `localhost:1080` ready to proxy traffic to the Network Requester set as the `--provider` when initialising.
When trying to connect your app, generally the proxy settings are found in `settings->advanced` or `settings->connection`.
Here is an example of setting the proxy connecting in Blockstream Green:
![Blockstream Green settings](../../images/blockstream-green.gif)
Most wallets and other applications will work basically the same way: find the network proxy settings, enter the proxy url (host: **localhost**, port: **1080**).
In some other applications, this might be written as **localhost:1080** if there's only one proxy entry field.
## Supported Applications
Any application which can be redirected over Socks5 proxy should work. Nym community has been successfully running over Nym Mixnet these applications:
- Bitcoin Electrum wallet
- Monero wallet (GUI and CLI with monerod)
- Telegram chat
- Element/Matrix chat
- Firo wallet
- Blockstream Green
> DarkFi's ircd chat was previously supported: they have moved to DarkIrc: whether the existing integration work is still operational needs to be tested.
Keep in mind that Nym has been developing a new client **[NymVPN](https://nymvpn.com) (GUI and CLI) routing all users traffic through the Mixnet.**
## Further reading
If you want to dig more into the architecture and use of the socks5 client check out its documentation [here](https://nymtech.net/docs/clients/socks5-client.html).
@@ -11,7 +11,7 @@ There are a number of message types that you can send up the websocket as define
```
## Getting your own address
When you start your app, it is best practice to ask the native client to tell you what your own address is (from the generated configuration files - see [here](../addressing-system.md) for more on Nym's addressing scheme). If you are running a service, you need to do this in order to know what address to give others. In a client-side piece of code you can also use this as a test to make sure your websocket connection is running smoothly. To do this, send:
When you start your app, it is best practice to ask the native client to tell you what your own address is (from the generated configuration files - see [here](https://nymtech.net/docs/architecture/addressing-system.md) for more on Nym's addressing scheme). If you are running a service, you need to do this in order to know what address to give others. In a client-side piece of code you can also use this as a test to make sure your websocket connection is running smoothly. To do this, send:
```json
{
@@ -58,7 +58,7 @@ In some applications, e.g. where people are chatting with friends who they know,
**If that fits your security model, good. However, will probably be the case that you want to send anonymous replies using Single Use Reply Blocks (SURBs)**.
You can read more about SURBs [here](../../architecture/traffic-flow.md#private-replies-using-surbs) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**.
You can read more about SURBs [here](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**.
Your client will send along a number of `replySurbs` to the recipient of the message. These are pre-addressed Sphinx packets that the recipient can write to the payload of (i.e. write response data to), but not view the final destination of. If the recipient is unable to fit the response data into the bucket of SURBs sent to it, it will use a SURB to request more SURBs be sent to it from your client.
@@ -1,7 +0,0 @@
# DevRel AMAs
The Nym Technology Developer Relations AMA (Ask Me Anything) is an event organised by the Nym team to engage and connect with the developer community as well as answer any questions that they may have.
> ⚠️ Hosted every fortnight on Wednesday @ 4pm UTC
Archives of these calls can be found [here](https://www.youtube.com/watch?v=0kVXR7aNOyg&list=PLoc3wV2YJYwohgwzf5IinyebV4GGYsa9K).
@@ -1,122 +0,0 @@
# Community Applications
If you would like to share your application here, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal).
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;">Pastenym
>A [pastebin](https://pastebin.com) inspired project, offer a solution for sharing text with Nym products to offer full anonymity, even on metadata level.
* [Github](https://github.com/notrustverify/pastenym)
* [Deployed App](https://pastenym.ch)
## <img src='../images/profile_picture/pineappleproxy_pp.png' style="float: right; width: 75px; height: 75px;">Nostr-Nym
> [Nostr-nym](https://github.com/notrustverify/nostr-nym) offer a solution to use [Nostr](https://nostr.how/en/what-is-nostr) protocol by giving the possibility to run a relay on mixnet. By using a nostr client compatible with the mixnet, users can protect their privacy to be able to use Nostr has the want, without being observed.
* [Github](https://github.com/notrustverify/nostr-nym)
* [Deployed App](https://nostrnym.pnproxy.org/)
* [Documentation](https://blog.notrustverify.ch/nostr-relay-on-nym)
## <img src='../images/profile_picture/ethereum_rpc_spook_pp.png' style="float: right; width: 75px; height: 75px;"> Spook
> Ethereum RPC request mixer uses the Nym network mixing service to anonymize RPC requests to the Ethereum network without revealing sensitive data and metadata.
* [Github](https://github.com/EdenBlockVC/spook)
## <img src='../images/profile_picture/ethereum_transaction_broadcaster_root_pp.png' style="float: right; width: 75px; height: 75px;"> Ethereum Transaction Broadcaster
> Ethereum Transaction Broadcaster that uses the Nym Mixnet to provide privacy and anonymity for transactions on the Ethereum network command-line interface.
* [Github](https://github.com/noot/nym-ethtx)
## <img src='../images/profile_picture/nymdrive_saleel_pp.png' style="float: right; width: 75px; height: 75px;">NymDrive
> An open-source, decentralized, E2E encrypted, privacy friendly alternative to Google Drive/Dropbox, allowing for file encryption and decryption using the Nym Mixnet.
* [Github](https://github.com/saleel/nymdrive)
* [Demo](https://www.youtube.com/watch?v=5Rx73nw8NYI)
* [Presentation](https://docs.google.com/presentation/d/1MpvIK32Mx9VKLVfMTcvbeyrsKHHUsTvDQ-3n31dR0NE/edit#slide=id.p)
## <img src='../images/profile_picture/nym_dashboard_pp.svg' style="float: right; width: 75px; height: 75px;">Nym Dashboard
> Developed by No Trust Verify, this dashboard is a great tool to get information about the mixnet, gateways and mixnodes.
* [Deployed App](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1)
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;">Is Nym Up
> Explore whether we're up through IsNymUp, a tool that helps check the heath of the Nym network as well as some mixnet related statistics!
* [Deployed App](https://isnymup.com/)
## <img src='../images/profile_picture/darkfi_over_nym_pp.png' style="float: right; width: 75px; height: 75px;">DarkFi over Nym
> DarkFi leverages Nym's mixnet as a pluggable transport for IRCD, their p2p IRC variant. Users can anonymously connect to peers over the network, ensuring secure and private communication within the DarkFi ecosystem.
* [Github](https://github.com/darkrenaissance/darkfi)
* [Documentation](https://darkrenaissance.github.io/darkfi/clients/nym_outbound.html)
## <img src='../images/profile_picture/nymstr_email_pp.png' style="float: right; width: 75px; height: 75px;">Nymstr email
> Experience secure and private email communication with ease using Nymstr email, which enables seamless transmission of emails over a SOCKS5 proxy and our NYM mixnet!
* [Github](https://github.com/dial0ut/nymstr-email)
## <img src='../images/profile_picture/minibolt_pp.png' style="float: right; width: 75px; height: 75px;">Minibolt
> Proxies the clearnet connections of a Bitcoin node and its associated tools using the NYM mixnet.
* [Github](https://github.com/minibolt-guide/minibolt)
* [Documentation](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core)
## <img src='../images/profile_picture/nymgraph_pp.png' style="float: right; width: 75px; height: 75px;">NymGraph
> NymGraph is a graphical chat client for Nym running on Ubuntu and Debian. Test it to chat over the Nym network!
* [Github](https://github.com/Tyz3/nymgraph)
<br/> <br/>
# Community Guides
We aren't the only ones writing documentation: the Nym developer community is also a great source of guides and resources, some of which we've included here.
## <img src='../images/profile_picture/pastenym_ntv_pp.png' style="float: right; width: 75px; height: 75px;"> No Trust Verify
>No Trust Verify is a project that aims to build open-source, privacy-enhancing technologies that make it easier to use the Internet securely and anonymously. Their focus is on providing tools and services that make it simple for developers to create decentralized applications (dApps) that respect users' privacy.
* [Awesome Nym list](https://notrustverify.github.io/awesome-nym/) ([GitHub](https://github.com/notrustverify/awesome-nym))
* A lot of guides can be found on the [NTV Blog](https://blog.notrustverify.ch/)
## <img src='../images/profile_picture/pineappleproxy_pp.png' style="float: right; width: 75px; height: 75px;">The Way of the NYMJA
by Pineapple Proxy🍍
>Born out of a study group from Nym's Shipyard Academy, Pineapple Proxy has emerged as a cluster of motivated and skilled individuals who see the new internet taking shape. With vibecare at the heart of their approach, this zesty collective is on a mission to make privacy convenient for everyone via content, new tools, events, and novel experiences. They believe in collective intelligence, empathy, and collaboration as the means by which privacy will become a meaningful reality.
* [Website](https://pnproxy.org/welcome.html) ([GitHub](https://github.com/Pineapple-Proxy-DAO/web))
@@ -1,6 +0,0 @@
# Forums
Welcome to our page dedicated to providing you with links to open forums discussing privacy-enhancing technologies, as well as general privacy topics. These forums are a great place to learn more about the latest developments in privacy technology, as well as to connect with other individuals who are passionate about protecting their online privacy. Whether you're new to the world of privacy or an experienced user, you're sure to find valuable information and resources on these forums.
🚧 coming soon 🚧
@@ -1,6 +1,9 @@
# Browser only
With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework.
- Oreowallet have integrated `mixFetch` into their browser-extension wallet to run transactions through the mixnet.
- [Codebase](https://github.com/oreoslabs/oreowallet-extension/tree/mixFetch)
- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet.
- [Website](https://notrustverify.github.io/mixfetch-examples/)
- [Codebase](https://github.com/notrustverify/mixfetch-examples)
@@ -1,6 +1,11 @@
# Custom Services
Custom services involve two pieces of code that communicate via the mixnet: a client, and a custom server/service. This custom service will most likely interact with the wider internet / a clearnet service on your behalf, with the mixnet between you and the service, acting as a privacy shield.
> The current model of relying on a Service Provider has some issues, such as additional complexity in deployment and maintenance, as well as creating potential chokepoints for app traffic. Work is going on (in the open in our [monorepo](https://github.com/nymtech/nym) ofc) to start removing this requirement as much as possible, by allowing for the creation of packet-contents in such a way that the existing Network Requester/Exit Gateway infrastructure can support network requests in a similar way to `mixFetch`. More on this as and when it is released.
- [Nym Zcash RPC demo](https://github.com/nymtech/nym-zcash-rpc-demo), although used to only pipe RPC traffic, is a proof of concept 'generic' mixnet piping example which exposes a TPC Socket on the client side for incoming traffic, pipes this through the mixnet, and then streams TCP packets 'out' the other side. A good example of non-app-specific traffic transport which developers could also quite easily use as a template for their own app-specific work.
- [Codebase](https://github.com/nymtech/nym-zcash-rpc-demo)
- PasteNym is a private pastebin alternative. It involves a browser-based frontend utilising the Typescript SDK and a Python-based backend service communicating with a standalone Nym Websocket Client. **If you're a Python developer, start here!**.
- [Frontend codebase](https://github.com/notrustverify/pastenym)
- [Backend codebase](https://github.com/notrustverify/pastenym-frontend)
@@ -1,45 +0,0 @@
# Nym General FAQ
> If you have questions which are not answered below, please share them at our [DevRel AMAs](../community-resources/ama.md) or seek support in [Nym's community](https://nymtech.net/community)
### What is Nym?
Nym is a privacy platform that secures user data and protects against surveillance at the network level.
The platform does so by leveraging different technological components:
- **Nym Mixnet**, a type of overlay network that makes both content and metadata of transactions private through mixing, network-level obfuscation and incentivisation (using Sphinx);
- A blockchain called **Nyx**, our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of NYM, as well as smart contracts, in order to create a robust, decentralized, and secure environment incentives for the Mixnet;
- **Coconut**, a zero-knowledge signature scheme, that creates an application-level private access control layer to power Zk-Nyms;
- A utility token **NYM**, to pay for usage, measure reputation and serve as rewards for the privacy infrastructure.
Simply put, the [Nym network ("Nym")](https://www.feat-nym-update-nym-web.websites.dev.nymte.ch/nym-whitepaper.pdf) is a decentralized and incentivized infrastructure to provision privacy to a broad range of message-based applications and services. Think of it as a [*"Layer 0" privacy infrastructure*](https://blog.nymtech.net/nym-layer-0-privacy-infrastructure-for-the-whole-internet-e53238f9b8e7) for the entire internet.
**Related articles:**
- [*Nym is not a blockchain, but is powered by one*](https://blog.nymtech.net/nym-is-not-a-blockchain-but-it-is-powered-by-one-4bb16ef16587)
- [*Nym tokens*](https://blog.nymtech.net/nym-tokens-where-do-they-live-and-how-are-they-distributed-cross-chain-8d134bf9c41f)
- [*A breakdown of the smart contracts that run the Nym token economics*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95)
- [*Zk-Nyms are here*](https://blog.nymtech.net/a-breakdown-of-the-smart-contracts-that-run-the-nym-token-economics-3a61b4139f95)
- [*Sphinx: the anonymous data format that powers Nym*](https://blog.nymtech.net/sphinx-tl-dr-the-data-packet-that-can-anonymize-bitcoin-and-the-internet-18d152c6e4dc)
### What's the difference between Nym and VPNs?
Nym is not an onion routing system, it is not a decentralized VPN - its much more than that. Nym is a mixnet meant to stop precisely the traffic analysis attacks that Tor and dVPNs are vulnerable to.
It is an orthogonal design that maintains better privacy and can support anonymity, although usually with a cost in terms of latency.
It basically is an infrastructure on which privacy preserving apps can be built, leveraging the Mixnet and Coconut credentials, amongst others.
The **Nym mixnet and VPNs differ** because VPNs do not mix nor do they protect metadata from an adversary who may be able to watch the entire network.
**Related articles:**
- [*VPNs, Tor, I2P, how does Nym compare? *](https://blog.nymtech.net/vpns-tor-i2p-how-does-nym-compare-8576824617b8)
### What is Nyms VPN?
Since Q2 2023 the Nym core team has been working on launching the **first major consumer facing product** that runs on top of the Nym mixnet: a high speed, trustless and decentralized VPN, paid for via the NYM token - facilitating anonymous payments if wished.
The product positions itself as a full-network protection service available across all of a users devices, **leveraging the Nym Mixnet** and other primitives to offer split tunneling and traffic obfuscation techniques to protect against censorship.
**Related articles:**
- [*What does it take to build the most powerful VPN?*](https://blog.nymtech.net/what-does-it-take-to-build-the-worlds-most-powerful-vpn-d351a76ec4e6)
@@ -46,4 +46,4 @@ If you have successfully completed KYC on Synaps earlier and provided your Nym w
Using the Nym network is free for now, but user fees will be introduced in the future and those will be paid in NYM tokens, so set them aside! And until then, you can contribute to running our decentralized infrastructure and earn mix mining rewards by setting up Nym mix nodes and bonding your tokens to them. You don't need to run nodes to contribute to the security and performance of the Nym network though. You can pledge your trust in someone else's node by delegating your NYM tokens to it, and receive a share of their mix mining rewards.
You can find out more about how staking works in [this](https://www.youtube.com/watch?v=PcNGcTwlm0I) video from our Chief Scientist Claudia Diaz and if you need help setting up your mix node, choosing one to delegate your tokens to, or anything else, our community is there to help on [Discord](https://discord.gg/nym) and [Telegram](https://t.me/nymchan).
You can find out more about how staking works in [this](https://www.youtube.com/watch?v=PcNGcTwlm0I) video from our Chief Scientist Claudia Diaz and if you need help setting up your mix node, choosing one to delegate your tokens to, or anything else, our community is there to help on [Discord](https://nymtech.net/go/discord) and [Telegram](https://t.me/nymchan).
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

@@ -1,5 +1,5 @@
# Integration Options
If you've already gone through the different [Quick Start](../quickstart/overview.md) options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process.
If you've already gone through the different options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process.
Below are a resources that will be useful for either beginning to integrate mixnet functionality into existing application code or build a new app using Nym.
@@ -7,8 +7,6 @@ Below are a resources that will be useful for either beginning to integrate mixn
- The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links.
- To get an idea of what is possible / has already been built, check the [community applications and resources](../community-resources/community-applications-and-guides.md) page, as well as the [developer tutorials codebase](https://github.com/nymtech/developer-tutorials).
> If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page.
@@ -1,5 +0,0 @@
# Chat demo (webapp)
You can find a browser-based 'hello world' chat app [here](https://chat-demo.nymtech.net).
Either open in two browser windows and send messages to yourself, or share with a friend and send messages to each other through the mixnet.
@@ -1,5 +0,0 @@
# Coconut Credential Playground (webapp)
There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials.
For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html).
@@ -1,22 +0,0 @@
# NymConnect Beta (GUI)
NymConnect is a one-button GUI application that wraps around the `nym-socks5-client` for proxying application traffic through the Mixnet.
You can watch our video on getting started with NymConnect:
<iframe width="700" height="400" src="https://www.youtube.com/embed/quj8H2qeOwY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
Install NymConnect and select an application that you want to privacy-enhance from the dropdown menu. For now, NymConnect can be used with Electrum Wallet, Keybase, desktop Telegram and Blockstream Green. Configure these to run via a SOCKS5 proxy and send their data through the Nym mixnet!
**Please note that NymConnect is currently released in beta. Please report bugs via Github**.
## Usage instuctions
* [Download](https://github.com/nymtech/nym/releases/) and install NymConnect.
* Select your service provider from the dropdown menu.
* Click `connect` - NymConnect will connect to a service provider and its SOCKS Proxy (IP) and Port will be displayed.
* Click on IP or Port to copy their values to the clipboard.
* Go to your app settings and look for the network/proxy settings. Select `running via SOCKS5 proxy` and paste the IP and Port values given by NymConnect.
Your traffic from that application will now run through the mixnet for privacy and unlinkability!
@@ -1,7 +0,0 @@
# Overview
There are multiple options to quickly connect to Nym and play with both the mixnet and credentials on the Sandbox testnet.
At most, these involve running Nym as a second process alongside an existing application in order to send traffic through the mixnet, most are either interact webpages or a standalone app.
If you've already covered the information in this section, or want to jump straight into integrating/ a Nym connection into an existing application, head to the [Integrations](../integrations/integration-options.md) section.
@@ -1,9 +1,9 @@
# Coconut credential generation
The following code shows how you can use the SDK to create and use a [credential](../../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet.
The following code shows how you can use the SDK to create and use a credential representing paid bandwidth on the Sandbox testnet.
```rust,noplayground
{{#include ../../../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}}
```
You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../../coconut.md).
You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](https://nymtech.net/docs/coconut.md).

Some files were not shown because too many files have changed in this diff Show More