Compare commits

..

1 Commits

Author SHA1 Message Date
Tommy Verrall 6f1321e1b0 testing cosmwasm docker optimiser 2024-05-23 10:44:45 +02:00
212 changed files with 4515 additions and 3058 deletions
@@ -35,7 +35,7 @@ jobs:
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: 1.77
toolchain: 1.77.0
target: wasm32-unknown-unknown
override: true
@@ -47,6 +47,17 @@ jobs:
- name: Build release contracts
run: make contracts
- name: Install CosmWasm optimizer
run: |
sudo apt-get update
sudo apt-get install -y docker.io
- name: Optimize WASM contracts
run: |
docker run --rm -v $(pwd)/contracts/target/wasm32-unknown-unknown/release:/code \
--mount type=volume,source=cosmwasm_cache,target=/code/cache \
cosmwasm/workspace-optimizer:0.12.9
- name: Prepare build output
shell: bash
env:
@@ -58,8 +69,7 @@ jobs:
cp contracts/target/wasm32-unknown-unknown/release/nym_coconut_dkg.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw3_flex_multisig.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/cw4_group.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_service_provider_directory.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_name_service.wasm $OUTPUT_DIR
cp contracts/target/wasm32-unknown-unknown/release/nym_ecash.wasm $OUTPUT_DIR
- name: Deploy branch to CI www
continue-on-error: true
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
- uses: rlespinasse/github-slug-action@v3.x
- uses: actions/setup-node@v3
with:
node-version: 18.17
node-version: 18
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
-39
View File
@@ -4,45 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.5-ragusa] (2024-05-22)
- Feature/nym node api location ([#4605])
- Add optional signature to IPR request/response ([#4604])
- Feature/unstable tested nodes endpoint ([#4601])
- nym-api: make report/avg_uptime endpoints ignore blacklist ([#4599])
- removed blocking for coconut in the final epoch state ([#4598])
- allow using explicit admin address for issuing freepasses ([#4595])
- Use rfc3339 for last_polled in described nym-api endpoint ([#4591])
- Explicitly handle constraint unique violation when importing credential ([#4588])
- [bugfix] noop flag for nym-api for nymvisor compatibility ([#4586])
- Chore/additional helpers ([#4585])
- Feature/wasm coconut ([#4584])
- upgraded axum and related deps to the most recent version ([#4573])
- Feature/nyxd scraper pruning ([#4564])
- Run cargo autoinherit on the main workspace ([#4553])
- Add rustls-tls to reqwest in validator-client ([#4552])
- Feature/rewarder voucher issuance ([#4548])
- make sure 'OffsetDateTimeJsonSchemaWrapper' is serialised with legacy format ([#4613])
[#4613]: https://github.com/nymtech/nym/pull/4613
[#4605]: https://github.com/nymtech/nym/pull/4605
[#4604]: https://github.com/nymtech/nym/pull/4604
[#4601]: https://github.com/nymtech/nym/pull/4601
[#4599]: https://github.com/nymtech/nym/pull/4599
[#4598]: https://github.com/nymtech/nym/pull/4598
[#4595]: https://github.com/nymtech/nym/pull/4595
[#4591]: https://github.com/nymtech/nym/pull/4591
[#4588]: https://github.com/nymtech/nym/pull/4588
[#4586]: https://github.com/nymtech/nym/pull/4586
[#4585]: https://github.com/nymtech/nym/pull/4585
[#4584]: https://github.com/nymtech/nym/pull/4584
[#4573]: https://github.com/nymtech/nym/pull/4573
[#4564]: https://github.com/nymtech/nym/pull/4564
[#4553]: https://github.com/nymtech/nym/pull/4553
[#4552]: https://github.com/nymtech/nym/pull/4552
[#4548]: https://github.com/nymtech/nym/pull/4548
## [2024.4-nutella] (2024-05-08)
- [fix] apply disable_poisson_rate from internal NR/IPR cfgs ([#4579])
Generated
+187 -107
View File
@@ -43,6 +43,19 @@ dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher 0.3.0",
"cpufeatures",
"ctr 0.8.0",
"opaque-debug 0.3.1",
]
[[package]]
name = "aes"
version = "0.8.4"
@@ -50,7 +63,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cipher 0.4.4",
"cpufeatures",
]
@@ -61,9 +74,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"aes 0.8.4",
"cipher 0.4.4",
"ctr 0.9.2",
"ghash",
"subtle 2.5.0",
]
@@ -524,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164"
dependencies = [
"bs58 0.5.1",
"hmac",
"hmac 0.12.1",
"k256",
"once_cell",
"pbkdf2",
@@ -586,7 +599,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330"
dependencies = [
"byte-tools",
"crypto-mac",
"crypto-mac 0.7.0",
"digest 0.8.1",
"opaque-debug 0.2.3",
]
@@ -814,7 +827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher",
"cipher 0.4.4",
"cpufeatures",
]
@@ -826,7 +839,7 @@ checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20",
"cipher",
"cipher 0.4.4",
"poly1305",
"zeroize",
]
@@ -873,6 +886,15 @@ dependencies = [
"half",
]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "cipher"
version = "0.4.4"
@@ -1166,7 +1188,7 @@ dependencies = [
"rand_core 0.6.4",
"serde",
"serde_json",
"signature",
"signature 2.2.0",
"subtle-encoding",
"tendermint",
"thiserror",
@@ -1185,7 +1207,7 @@ dependencies = [
"rand_core 0.6.4",
"serde",
"serde_json",
"signature",
"signature 2.2.0",
"subtle-encoding",
"tendermint",
"tendermint-rpc",
@@ -1451,6 +1473,16 @@ dependencies = [
"subtle 1.0.0",
]
[[package]]
name = "crypto-mac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e"
dependencies = [
"generic-array 0.14.7",
"subtle 2.5.0",
]
[[package]]
name = "csv"
version = "1.3.0"
@@ -1472,13 +1504,22 @@ dependencies = [
"memchr",
]
[[package]]
name = "ctr"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
dependencies = [
"cipher 0.3.0",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
"cipher 0.4.4",
]
[[package]]
@@ -1530,6 +1571,7 @@ dependencies = [
"byteorder",
"digest 0.9.0",
"rand_core 0.5.1",
"serde",
"subtle 2.5.0",
"zeroize",
]
@@ -1543,11 +1585,9 @@ dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"digest 0.10.7",
"fiat-crypto",
"platforms",
"rustc_version 0.4.0",
"serde",
"subtle 2.5.0",
"zeroize",
]
@@ -1764,9 +1804,8 @@ checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "defguard_wireguard_rs"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba16f17698d4b389907310af018b0c3a80b025bba9c38d947cbc6dd70921743"
version = "0.3.0"
source = "git+https://github.com/neacsu/wireguard-rs.git?rev=c2cd0c1119f699f4bc43f5e6ffd6fc242caa42ed#c2cd0c1119f699f4bc43f5e6ffd6fc242caa42ed"
dependencies = [
"base64 0.21.7",
"libc",
@@ -1946,10 +1985,20 @@ dependencies = [
"elliptic-curve",
"rfc6979",
"serdect",
"signature",
"signature 2.2.0",
"spki",
]
[[package]]
name = "ed25519"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
dependencies = [
"serde",
"signature 1.6.4",
]
[[package]]
name = "ed25519"
version = "2.2.3"
@@ -1957,8 +2006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"pkcs8",
"serde",
"signature",
"signature 2.2.0",
]
[[package]]
@@ -1976,16 +2024,16 @@ dependencies = [
[[package]]
name = "ed25519-dalek"
version = "2.1.1"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
"curve25519-dalek 4.1.2",
"ed25519",
"rand_core 0.6.4",
"curve25519-dalek 3.2.0",
"ed25519 1.5.3",
"rand 0.7.3",
"serde",
"sha2 0.10.8",
"subtle 2.5.0",
"serde_bytes",
"sha2 0.9.9",
"zeroize",
]
@@ -2777,13 +2825,33 @@ dependencies = [
"winapi",
]
[[package]]
name = "hkdf"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b"
dependencies = [
"digest 0.9.0",
"hmac 0.11.0",
]
[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
"hmac 0.12.1",
]
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac 0.11.0",
"digest 0.9.0",
]
[[package]]
@@ -3341,7 +3409,7 @@ dependencies = [
"elliptic-curve",
"once_cell",
"sha2 0.10.8",
"signature",
"signature 2.2.0",
]
[[package]]
@@ -3620,7 +3688,7 @@ dependencies = [
"nym-ordered-buffer",
"nym-service-providers-common",
"nym-socks5-requests",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -3861,7 +3929,7 @@ dependencies = [
[[package]]
name = "nym-api"
version = "1.1.38"
version = "1.1.37"
dependencies = [
"anyhow",
"async-trait",
@@ -3910,7 +3978,9 @@ dependencies = [
"nym-vesting-contract-common",
"okapi",
"pin-project",
"rand 0.7.3",
"rand 0.8.5",
"rand_chacha 0.2.2",
"rand_chacha 0.3.1",
"reqwest 0.12.4",
"rocket",
@@ -3947,7 +4017,6 @@ dependencies = [
"nym-node-requests",
"schemars",
"serde",
"serde_json",
"tendermint",
"time",
"ts-rs",
@@ -3976,7 +4045,7 @@ dependencies = [
"nym-crypto",
"nym-network-defaults",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"thiserror",
"url",
"zeroize",
@@ -4022,7 +4091,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.36"
version = "1.1.35"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -4103,7 +4172,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.35"
version = "1.1.34"
dependencies = [
"bs58 0.5.1",
"clap 4.5.4",
@@ -4126,7 +4195,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"tap",
@@ -4174,7 +4243,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"sha2 0.10.8",
@@ -4254,7 +4323,7 @@ dependencies = [
"nym-bin-common",
"nym-node-tester-utils",
"nym-node-tester-wasm",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde-wasm-bindgen 0.6.5",
"serde_json",
@@ -4397,7 +4466,7 @@ dependencies = [
"nym-credentials-interface",
"nym-crypto",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"thiserror",
"time",
@@ -4418,25 +4487,25 @@ dependencies = [
name = "nym-crypto"
version = "0.4.0"
dependencies = [
"aes",
"aes 0.8.4",
"blake3",
"bs58 0.5.1",
"cipher",
"ctr",
"cipher 0.4.4",
"ctr 0.9.2",
"digest 0.10.7",
"ed25519-dalek",
"generic-array 0.14.7",
"hkdf",
"hmac",
"hkdf 0.12.4",
"hmac 0.12.1",
"nym-pemstore",
"nym-sphinx-types",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand 0.7.3",
"rand_chacha 0.2.2",
"serde",
"serde_bytes",
"subtle-encoding",
"thiserror",
"x25519-dalek",
"x25519-dalek 1.1.1",
"zeroize",
]
@@ -4558,7 +4627,7 @@ dependencies = [
"nym-wireguard",
"nym-wireguard-types",
"once_cell",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"sqlx",
@@ -4591,7 +4660,7 @@ dependencies = [
"nym-sphinx",
"nym-task",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"si-scale",
"thiserror",
@@ -4620,7 +4689,7 @@ dependencies = [
"nym-crypto",
"nym-pemstore",
"nym-sphinx",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"thiserror",
@@ -4848,7 +4917,7 @@ dependencies = [
"nym-topology",
"nym-types",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"sysinfo 0.27.8",
@@ -4936,7 +5005,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.36"
version = "1.1.35"
dependencies = [
"addr",
"anyhow",
@@ -4970,7 +5039,7 @@ dependencies = [
"nym-types",
"pretty_env_logger",
"publicsuffix",
"rand 0.8.5",
"rand 0.7.3",
"regex",
"reqwest 0.12.4",
"serde",
@@ -5005,7 +5074,7 @@ dependencies = [
[[package]]
name = "nym-node"
version = "1.1.2"
version = "1.1.1"
dependencies = [
"anyhow",
"bip39",
@@ -5031,9 +5100,8 @@ dependencies = [
"nym-sphinx-addressing",
"nym-task",
"nym-types",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand 0.7.3",
"semver 1.0.23",
"serde",
"serde_json",
@@ -5052,12 +5120,11 @@ version = "0.1.0"
dependencies = [
"axum 0.7.5",
"axum-extra",
"base64 0.21.7",
"colored",
"dashmap",
"fastrand 2.1.0",
"headers",
"hmac",
"hmac 0.12.1",
"hyper 1.3.1",
"ipnetwork 0.16.0",
"nym-crypto",
@@ -5067,7 +5134,7 @@ dependencies = [
"nym-task",
"nym-wireguard",
"nym-wireguard-types",
"rand 0.8.5",
"rand 0.7.3",
"serde_json",
"thiserror",
"time",
@@ -5077,7 +5144,7 @@ dependencies = [
"tracing",
"utoipa",
"utoipa-swagger-ui",
"x25519-dalek",
"x25519-dalek 2.0.1",
]
[[package]]
@@ -5094,7 +5161,7 @@ dependencies = [
"nym-exit-policy",
"nym-http-api-client",
"nym-wireguard-types",
"rand_chacha 0.3.1",
"rand_chacha 0.2.2",
"schemars",
"serde",
"serde_json",
@@ -5115,7 +5182,7 @@ dependencies = [
"nym-sphinx-params",
"nym-task",
"nym-topology",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"thiserror",
@@ -5130,7 +5197,7 @@ dependencies = [
"futures",
"js-sys",
"nym-node-tester-utils",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -5185,11 +5252,11 @@ dependencies = [
"chacha20",
"chacha20poly1305",
"criterion",
"curve25519-dalek 4.1.2",
"curve25519-dalek 3.2.0",
"fastrand 1.9.0",
"getrandom 0.2.15",
"log",
"rand 0.8.5",
"rand 0.7.3",
"rayon",
"sphinx-packet",
"thiserror",
@@ -5237,7 +5304,7 @@ dependencies = [
"nym-validator-client",
"parking_lot 0.12.2",
"pretty_env_logger",
"rand 0.8.5",
"rand 0.7.3",
"reqwest 0.12.4",
"tap",
"thiserror",
@@ -5280,7 +5347,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.35"
version = "1.1.34"
dependencies = [
"bs58 0.5.1",
"clap 4.5.4",
@@ -5299,7 +5366,7 @@ dependencies = [
"nym-socks5-client-core",
"nym-sphinx",
"nym-topology",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"tap",
@@ -5332,7 +5399,7 @@ dependencies = [
"nym-task",
"nym-validator-client",
"pin-project",
"rand 0.8.5",
"rand 0.7.3",
"reqwest 0.12.4",
"schemars",
"serde",
@@ -5358,7 +5425,7 @@ dependencies = [
"nym-credential-storage",
"nym-crypto",
"nym-socks5-client-core",
"rand 0.8.5",
"rand 0.7.3",
"safer-ffi",
"serde",
"tokio",
@@ -5412,7 +5479,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand 0.7.3",
"rand_distr",
"thiserror",
"tokio",
@@ -5430,7 +5497,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"thiserror",
"zeroize",
@@ -5442,7 +5509,7 @@ version = "0.1.0"
dependencies = [
"nym-crypto",
"nym-sphinx-types",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"thiserror",
]
@@ -5458,8 +5525,8 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand 0.7.3",
"rand_chacha 0.2.2",
"serde",
"thiserror",
"wasm-bindgen",
@@ -5473,7 +5540,7 @@ dependencies = [
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-types",
"rand 0.8.5",
"rand 0.7.3",
"thiserror",
]
@@ -5490,7 +5557,7 @@ dependencies = [
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.8.5",
"rand 0.7.3",
"thiserror",
]
@@ -5601,7 +5668,7 @@ dependencies = [
"nym-sphinx-addressing",
"nym-sphinx-routing",
"nym-sphinx-types",
"rand 0.8.5",
"rand 0.7.3",
"semver 0.11.0",
"serde",
"serde_json",
@@ -5631,7 +5698,7 @@ dependencies = [
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
"cosmwasm-std",
"eyre",
"hmac",
"hmac 0.12.1",
"itertools 0.11.0",
"log",
"nym-config",
@@ -5649,7 +5716,7 @@ dependencies = [
"thiserror",
"ts-rs",
"url",
"x25519-dalek",
"x25519-dalek 2.0.1",
]
[[package]]
@@ -5774,16 +5841,14 @@ name = "nym-wireguard"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"dashmap",
"defguard_wireguard_rs",
"ip_network",
"log",
"nym-crypto",
"nym-network-defaults",
"nym-task",
"nym-wireguard-types",
"tokio",
"x25519-dalek",
"x25519-dalek 2.0.1",
]
[[package]]
@@ -5792,23 +5857,21 @@ version = "0.1.0"
dependencies = [
"base64 0.21.7",
"dashmap",
"hmac",
"hmac 0.12.1",
"log",
"nym-config",
"nym-crypto",
"nym-network-defaults",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde_json",
"sha2 0.10.8",
"thiserror",
"utoipa",
"x25519-dalek",
"x25519-dalek 2.0.1",
]
[[package]]
name = "nymvisor"
version = "0.1.1"
version = "0.1.0"
dependencies = [
"anyhow",
"bytes",
@@ -6127,7 +6190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"hmac",
"hmac 0.12.1",
]
[[package]]
@@ -6686,12 +6749,12 @@ dependencies = [
[[package]]
name = "rand_distr"
version = "0.4.3"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
checksum = "c9e9532ada3929fb8b2e9dbe28d1e06c9b2cc65813f074fcb6bd5fbefeff9d56"
dependencies = [
"num-traits",
"rand 0.8.5",
"rand 0.7.3",
]
[[package]]
@@ -7005,7 +7068,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
dependencies = [
"hmac",
"hmac 0.12.1",
"subtle 2.5.0",
]
@@ -7797,6 +7860,12 @@ dependencies = [
"libc",
]
[[package]]
name = "signature"
version = "1.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
[[package]]
name = "signature"
version = "2.2.0"
@@ -7867,26 +7936,25 @@ dependencies = [
[[package]]
name = "sphinx-packet"
version = "0.1.1"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dabeca95bf5fd0563d6be7ebcb1c6a9fcb135746a0ba9050c47dc68c8607e595"
checksum = "cc43eda802856ee82a7555c7b75ceb9e07451741c7a2f5f23d036020e01189d4"
dependencies = [
"aes",
"aes 0.7.5",
"arrayref",
"blake2 0.8.1",
"bs58 0.5.1",
"bs58 0.4.0",
"byteorder",
"chacha",
"ctr",
"curve25519-dalek 4.1.2",
"digest 0.10.7",
"hkdf",
"hmac",
"curve25519-dalek 3.2.0",
"digest 0.9.0",
"hkdf 0.11.0",
"hmac 0.11.0",
"lioness",
"log",
"rand 0.8.5",
"rand 0.7.3",
"rand_distr",
"sha2 0.10.8",
"sha2 0.9.9",
"subtle 2.5.0",
]
@@ -8277,7 +8345,7 @@ checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b"
dependencies = [
"bytes",
"digest 0.10.7",
"ed25519",
"ed25519 2.2.3",
"ed25519-consensus",
"flex-error",
"futures",
@@ -8292,7 +8360,7 @@ dependencies = [
"serde_json",
"serde_repr",
"sha2 0.10.8",
"signature",
"signature 2.2.0",
"subtle 2.5.0",
"subtle-encoding",
"tendermint-proto",
@@ -9428,7 +9496,7 @@ dependencies = [
"nym-task",
"nym-topology",
"nym-validator-client",
"rand 0.8.5",
"rand 0.7.3",
"serde",
"serde-wasm-bindgen 0.6.5",
"thiserror",
@@ -9884,6 +9952,18 @@ dependencies = [
"tap",
]
[[package]]
name = "x25519-dalek"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
dependencies = [
"curve25519-dalek 3.2.0",
"rand_core 0.5.1",
"serde",
"zeroize",
]
[[package]]
name = "x25519-dalek"
version = "2.0.1"
+6 -6
View File
@@ -172,7 +172,7 @@ bincode = "1.3.3"
bip39 = { version = "2.0.0", features = ["zeroize"] }
bitvec = "1.0.0"
blake3 = "1.3.1"
bs58 = "0.5.1"
bs58 = "0.5.0"
bytecodec = "0.4.15"
bytes = "1.5.0"
cargo_metadata = "0.18.1"
@@ -195,13 +195,13 @@ criterion = "0.4"
csv = "1.3.0"
ctr = "0.9.1"
cupid = "0.6.1"
curve25519-dalek = "4.1"
curve25519-dalek = "3.2"
dashmap = "5.5.3"
defguard_wireguard_rs = "0.4.2"
defguard_wireguard_rs = { git = "https://github.com/neacsu/wireguard-rs.git", rev = "c2cd0c1119f699f4bc43f5e6ffd6fc242caa42ed" }
doc-comment = "0.3"
dotenvy = "0.15.6"
ecdsa = "0.16"
ed25519-dalek = "2.1"
ed25519-dalek = "1.0"
etherparse = "0.13.0"
eyre = "0.6.9"
flate2 = "1.0.28"
@@ -247,7 +247,7 @@ rand = "0.8.5"
rand-07 = "0.7.3"
rand_chacha_02 = "0.2"
rand_core = "0.6.3"
rand_distr = "0.4"
rand_distr = "0.3"
rand_pcg = "0.3.1"
rand_seeder = "0.2.3"
rayon = "1.5.1"
@@ -266,7 +266,7 @@ serde_repr = "0.1"
serde_with = "3.4.0"
serde_yaml = "0.9.25"
si-scale = "0.2.2"
sphinx-packet = "0.1.1"
sphinx-packet = "0.1.0"
sqlx = "0.6.3"
strum = "0.25"
subtle-encoding = "0.5"
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.35"
version = "1.1.34"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -25,7 +25,7 @@ bs58 = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] }
dirs = "4.0"
log = { workspace = true } # self explanatory
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde_json = { workspace = true }
thiserror = { workspace = true }
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.35"
version = "1.1.34"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
@@ -16,7 +16,7 @@ serde_json = { workspace = true }
tap = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
rand = { workspace = true }
rand = "0.7.3"
time = { workspace = true }
url = { workspace = true }
zeroize = { workspace = true }
+1 -1
View File
@@ -9,7 +9,7 @@ license.workspace = true
[dependencies]
bip39 = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
rand = "0.7.3"
thiserror = { workspace = true }
url = { workspace = true }
zeroize = { workspace = true }
+1 -1
View File
@@ -17,7 +17,7 @@ clap = { workspace = true, optional = true }
futures = { workspace = true }
humantime-serde = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10.6"
+1 -1
View File
@@ -14,7 +14,7 @@ futures = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
tokio = { workspace = true, features = ["macros"] }
si-scale = { workspace = true }
time.workspace = true
@@ -220,18 +220,9 @@ impl<C, St> GatewayClient<C, St> {
#[cfg(not(target_arch = "wasm32"))]
pub async fn establish_connection(&mut self) -> Result<(), GatewayClientError> {
debug!(
"Attemting to establish connection to gateway at: {}",
self.gateway_address
);
let ws_stream = match connect_async(&self.gateway_address).await {
Ok((ws_stream, _)) => ws_stream,
Err(error) => {
return Err(GatewayClientError::NetworkConnectionFailed {
address: self.gateway_address.clone(),
source: error,
})
}
Err(e) => return Err(GatewayClientError::NetworkError(e)),
};
self.connection = SocketState::Available(Box::new(ws_stream));
@@ -23,9 +23,6 @@ pub enum GatewayClientError {
#[error("There was a network error: {0}")]
NetworkErrorWasm(#[from] JsError),
#[error("connection failed: {address}: {source}")]
NetworkConnectionFailed { address: String, source: WsError },
#[error("Invalid URL: {0}")]
InvalidURL(String),
+1 -1
View File
@@ -23,5 +23,5 @@ nym-api-requests = { path = "../../nym-api/nym-api-requests" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
[dev-dependencies]
rand = "0.8.5"
rand = "0.7.3"
+5 -5
View File
@@ -17,10 +17,10 @@ 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 }
rand = { workspace = true, optional = true }
serde_bytes = { version = "0.11.6", optional = true }
x25519-dalek = { version = "1.1", optional = true }
ed25519-dalek = { workspace = true, optional = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"], optional = true }
serde_bytes = { workspace = true, optional = true }
serde_crate = { version = "1.0", optional = true, default_features = false, features = ["derive"], package = "serde" }
subtle-encoding = { workspace = true, features = ["bech32-preview"] }
thiserror = { workspace = true }
@@ -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 = "0.2"
[features]
default = ["sphinx"]
+4 -11
View File
@@ -56,7 +56,7 @@ pub struct KeyPair {
impl KeyPair {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let private_key = x25519_dalek::StaticSecret::random_from_rng(rng);
let private_key = x25519_dalek::StaticSecret::new(rng);
let public_key = (&private_key).into();
KeyPair {
@@ -211,7 +211,7 @@ impl FromStr for PrivateKey {
impl PrivateKey {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let x25519_secret = x25519_dalek::StaticSecret::random_from_rng(rng);
let x25519_secret = x25519_dalek::StaticSecret::new(rng);
PrivateKey(x25519_secret)
}
@@ -358,23 +358,16 @@ mod sphinx_key_conversion {
let private = &keys.private_key;
let public = &keys.public_key;
let dummy_remote = KeyPair::new(&mut rng);
let dh1 = private.diffie_hellman(&dummy_remote.public_key);
let private_bytes = private.to_bytes();
let public_bytes = public.to_bytes();
let sphinx_private: nym_sphinx_types::PrivateKey = private.into();
let recovered_private = PrivateKey::from(sphinx_private);
let dh2 = recovered_private.diffie_hellman(&dummy_remote.public_key);
let sphinx_public: nym_sphinx_types::PublicKey = public.into();
let recovered_public = PublicKey::from(sphinx_public);
assert_eq!(private_bytes, recovered_private.to_bytes());
assert_eq!(public_bytes, recovered_public.to_bytes());
// even though the byte representation of the private key changed, the resultant DH is the same
// which is what matters
assert_eq!(dh1, dh2);
}
}
+15 -21
View File
@@ -1,8 +1,8 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use ed25519_dalek::ed25519::signature::Signature as SignatureTrait;
pub use ed25519_dalek::SignatureError;
use ed25519_dalek::{Signer, SigningKey};
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
use std::fmt::{self, Display, Formatter};
@@ -30,9 +30,6 @@ pub enum Ed25519RecoveryError {
#[error(transparent)]
MalformedBytes(#[from] SignatureError),
#[error(transparent)]
BytesLengthError(#[from] std::array::TryFromSliceError),
#[error("the base58 representation of the public key was malformed - {source}")]
MalformedPublicKeyString {
#[source]
@@ -67,11 +64,11 @@ pub struct KeyPair {
impl KeyPair {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let ed25519_signing_key = ed25519_dalek::SigningKey::generate(rng);
let ed25519_keypair = ed25519_dalek::Keypair::generate(rng);
KeyPair {
private_key: PrivateKey(ed25519_signing_key.to_bytes()),
public_key: PublicKey(ed25519_signing_key.verifying_key()),
private_key: PrivateKey(ed25519_keypair.secret),
public_key: PublicKey(ed25519_keypair.public),
}
}
@@ -112,7 +109,7 @@ impl PemStorableKeyPair for KeyPair {
/// ed25519 EdDSA Public Key
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct PublicKey(ed25519_dalek::VerifyingKey);
pub struct PublicKey(ed25519_dalek::PublicKey);
impl Display for PublicKey {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
@@ -138,9 +135,7 @@ impl PublicKey {
}
pub fn from_bytes(b: &[u8]) -> Result<Self, Ed25519RecoveryError> {
Ok(PublicKey(ed25519_dalek::VerifyingKey::from_bytes(
b.try_into()?,
)?))
Ok(PublicKey(ed25519_dalek::PublicKey::from_bytes(b)?))
}
pub fn to_base58_string(self) -> String {
@@ -194,7 +189,7 @@ impl<'d> Deserialize<'d> for PublicKey {
where
D: Deserializer<'d>,
{
Ok(PublicKey(ed25519_dalek::VerifyingKey::deserialize(
Ok(PublicKey(ed25519_dalek::PublicKey::deserialize(
deserializer,
)?))
}
@@ -228,7 +223,7 @@ impl Display for PrivateKey {
impl<'a> From<&'a PrivateKey> for PublicKey {
fn from(pk: &'a PrivateKey) -> Self {
PublicKey(SigningKey::from_bytes(&pk.0).verifying_key())
PublicKey((&pk.0).into())
}
}
@@ -243,7 +238,7 @@ impl FromStr for PrivateKey {
impl PrivateKey {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let ed25519_secret = ed25519_dalek::SigningKey::generate(rng).to_bytes();
let ed25519_secret = ed25519_dalek::SecretKey::generate(rng);
PrivateKey(ed25519_secret)
}
@@ -253,11 +248,11 @@ impl PrivateKey {
}
pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
self.0
self.0.to_bytes()
}
pub fn from_bytes(b: &[u8]) -> Result<Self, Ed25519RecoveryError> {
Ok(PrivateKey(b.try_into()?))
Ok(PrivateKey(ed25519_dalek::SecretKey::from_bytes(b)?))
}
pub fn to_base58_string(&self) -> String {
@@ -272,8 +267,9 @@ impl PrivateKey {
}
pub fn sign<M: AsRef<[u8]>>(&self, message: M) -> Signature {
let signing_key: SigningKey = self.0.into();
let sig = signing_key.sign(message.as_ref());
let expanded_secret_key = ed25519_dalek::ExpandedSecretKey::from(&self.0);
let public_key: PublicKey = self.into();
let sig = expanded_secret_key.sign(message.as_ref(), &public_key.0);
Signature(sig)
}
@@ -342,9 +338,7 @@ impl Signature {
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Ed25519RecoveryError> {
Ok(Signature(ed25519_dalek::Signature::from_bytes(
bytes.try_into()?,
)))
Ok(Signature(ed25519_dalek::Signature::from_bytes(bytes)?))
}
}
+2 -2
View File
@@ -3,11 +3,11 @@
use crate::asymmetric::encryption;
use crate::hkdf;
#[cfg(feature = "rand")]
use cipher::crypto_common::rand_core::{CryptoRng, RngCore};
use cipher::{Key, KeyIvInit, StreamCipher};
use digest::crypto_common::BlockSizeUser;
use digest::Digest;
#[cfg(feature = "rand")]
use rand::{CryptoRng, RngCore};
/// Generate an ephemeral encryption keypair and perform diffie-hellman to establish
/// shared key with the remote.
+1 -1
View File
@@ -8,7 +8,7 @@ license.workspace = true
[dependencies]
futures = { workspace = true }
rand = { workspace = true }
rand = "0.7.3"
serde = { workspace = true }
serde_json = { workspace = true }
+1 -1
View File
@@ -9,7 +9,7 @@ repository = { workspace = true }
[dependencies]
log = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
rand_distr = { workspace = true }
thiserror = { workspace = true }
+1 -1
View File
@@ -8,7 +8,7 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
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 }
+1 -1
View File
@@ -14,5 +14,5 @@ serde = { workspace = true } # implementing serialization/deserialization for so
thiserror = { workspace = true }
[dev-dependencies]
rand = "0.8.5"
rand = "0.7"
nym-crypto = { path = "../../crypto", features = ["rand"] }
@@ -8,7 +8,7 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
bs58 = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
@@ -24,4 +24,4 @@ nym-topology = { path = "../../topology" }
version = "0.2.83"
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = "0.2"
+1 -1
View File
@@ -11,7 +11,7 @@ repository = { workspace = true }
[dependencies]
log = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
thiserror = { workspace = true }
nym-sphinx-addressing = { path = "../addressing" }
+1 -1
View File
@@ -8,7 +8,7 @@ license = { workspace = true }
repository = { workspace = true }
[dependencies]
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
thiserror = { workspace = true }
nym-crypto = { path = "../../crypto" }
+1 -1
View File
@@ -15,7 +15,7 @@ pub use sphinx_packet::{
self, DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, MAX_PATH_LENGTH, NODE_ADDRESS_LENGTH,
PAYLOAD_KEY_SIZE,
},
crypto::{self, PrivateKey, PublicKey},
crypto::{self, EphemeralSecret, PrivateKey, PublicKey, SharedSecret},
header::{self, delays, delays::Delay, ProcessedHeader, SphinxHeader, HEADER_SIZE},
packet::builder::DEFAULT_PAYLOAD_SIZE,
payload::{Payload, PAYLOAD_OVERHEAD_SIZE},
+1 -1
View File
@@ -12,7 +12,7 @@ dirs = "4.0"
futures = { workspace = true }
log = { workspace = true }
pin-project = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
reqwest = { workspace = true }
schemars = { workspace = true, features = ["preserve_order"] }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
+1 -1
View File
@@ -14,7 +14,7 @@ documentation = { workspace = true }
[dependencies]
bs58 = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
thiserror = { workspace = true }
async-trait = { workspace = true, optional = true }
semver = "0.11"
+1 -1
View File
@@ -11,7 +11,7 @@ repository = "https://github.com/nymtech/nym"
[dependencies]
async-trait = { workspace = true }
js-sys = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] }
serde-wasm-bindgen = { workspace = true }
thiserror = { workspace = true }
+1 -3
View File
@@ -17,9 +17,7 @@ log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
nym-config = { path = "../config" }
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
nym-network-defaults = { path = "../network-defaults" }
# feature-specific dependencies:
@@ -34,7 +32,7 @@ serde_json = { workspace = true, optional = true }
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }
[dev-dependencies]
rand = "0.8.5"
rand = "0.7.3"
nym-crypto = { path = "../crypto", features = ["rand"]}
-23
View File
@@ -1,23 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::net::{IpAddr, SocketAddr};
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct Config {
/// Socket address this node will use for binding its wireguard interface.
/// default: `0.0.0.0:51822`
pub bind_address: SocketAddr,
/// Private IP address of the wireguard gateway.
/// default: `10.1.0.1`
pub private_ip: IpAddr,
/// Port announced to external clients wishing to connect to the wireguard interface.
/// Useful in the instances where the node is behind a proxy.
pub announced_port: u16,
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
/// The maximum value for IPv4 is 32 and for IPv6 is 128
pub private_network_prefix: u8,
}
-3
View File
@@ -32,7 +32,4 @@ pub enum Error {
#[source]
source: hmac::digest::MacError,
},
#[error("peers can't be modified anymore")]
PeerModifyStopped,
}
+1 -4
View File
@@ -1,17 +1,14 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod config;
pub mod error;
pub mod public_key;
pub mod registration;
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, ClientRegistrationResponse, GatewayClient, InitMessage, Nonce,
};
#[cfg(feature = "verify")]
-4
View File
@@ -24,10 +24,6 @@ impl PeerPublicKey {
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn inner(&self) -> PublicKey {
self.0
}
}
impl fmt::Display for PeerPublicKey {
+14 -14
View File
@@ -12,12 +12,12 @@ use std::{fmt, ops::Deref, str::FromStr};
#[cfg(feature = "verify")]
use hmac::{Hmac, Mac};
#[cfg(feature = "verify")]
use nym_crypto::asymmetric::encryption::PrivateKey;
use nym_crypto::asymmetric::encryption::{PrivateKey, PublicKey};
#[cfg(feature = "verify")]
use sha2::Sha256;
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
pub type PendingRegistrations = DashMap<PeerPublicKey, RegistrationData>;
pub type PendingRegistrations = DashMap<PeerPublicKey, Nonce>;
pub type PrivateIPs = DashMap<IpAddr, Free>;
#[cfg(feature = "verify")]
@@ -56,16 +56,14 @@ impl InitMessage {
#[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,
PendingRegistration {
nonce: u64,
gateway_data: GatewayClient,
wg_port: u16,
},
Registered {
success: bool,
},
}
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
@@ -89,7 +87,7 @@ impl GatewayClient {
#[cfg(feature = "verify")]
pub fn new(
local_secret: &PrivateKey,
remote_public: x25519_dalek::PublicKey,
remote_public: PublicKey,
private_ip: IpAddr,
nonce: u64,
) -> Self {
@@ -98,6 +96,8 @@ impl GatewayClient {
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
let remote_public = x25519_dalek::PublicKey::from(remote_public.to_bytes());
let dh = static_secret.diffie_hellman(&remote_public);
// TODO: change that to use our nym_crypto::hmac module instead
@@ -220,7 +220,7 @@ mod tests {
let client = GatewayClient::new(
client_key_pair.private_key(),
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
*gateway_key_pair.public_key(),
"10.0.0.42".parse().unwrap(),
nonce,
);
+3 -3
View File
@@ -12,16 +12,16 @@ license.workspace = true
[dependencies]
base64 = "0.21.3"
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"
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" }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] }
[target."cfg(target_os = \"linux\")".dependencies]
defguard_wireguard_rs = { git = "https://github.com/neacsu/wireguard-rs.git", rev = "c2cd0c1119f699f4bc43f5e6ffd6fc242caa42ed" }
+28 -126
View File
@@ -3,142 +3,44 @@
// #![warn(clippy::expect_used)]
// #![warn(clippy::unwrap_used)]
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 std::sync::Arc;
use tokio::sync::mpsc::{self, UnboundedReceiver};
const WG_TUN_NAME: &str = "nymwg";
pub mod peer_controller;
pub struct WgApiWrapper {
inner: WGApi,
}
impl WgApiWrapper {
pub fn new(wg_api: WGApi) -> Self {
WgApiWrapper { inner: wg_api }
}
}
impl Drop for WgApiWrapper {
fn drop(&mut self) {
if let Err(e) = defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&self.inner)
{
log::error!("Could not remove the wireguard interface: {:?}", e);
}
}
}
#[derive(Clone)]
pub struct WireguardGatewayData {
config: Config,
keypair: Arc<KeyPair>,
client_registry: Arc<GatewayClientRegistry>,
peer_tx: mpsc::UnboundedSender<PeerControlMessage>,
}
impl WireguardGatewayData {
pub fn new(
config: Config,
keypair: Arc<KeyPair>,
) -> (Self, mpsc::UnboundedReceiver<PeerControlMessage>) {
let (peer_tx, peer_rx) = mpsc::unbounded_channel();
(
WireguardGatewayData {
config,
keypair,
client_registry: Arc::new(DashMap::default()),
peer_tx,
},
peer_rx,
)
}
pub fn config(&self) -> Config {
self.config
}
pub fn keypair(&self) -> &Arc<KeyPair> {
&self.keypair
}
pub fn client_registry(&self) -> &Arc<GatewayClientRegistry> {
&self.client_registry
}
pub fn add_peer(&self, client: &GatewayClient) -> Result<(), Error> {
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);
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);
self.peer_tx.send(msg).map_err(|_| Error::PeerModifyStopped)
}
}
pub struct WireguardData {
pub inner: WireguardGatewayData,
pub peer_rx: UnboundedReceiver<PeerControlMessage>,
}
pub mod setup;
/// Start wireguard device
#[cfg(target_os = "linux")]
pub async fn start_wireguard(
task_client: nym_task::TaskClient,
wireguard_data: WireguardData,
) -> 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};
use ip_network::IpNetwork;
use peer_controller::PeerController;
mut task_client: nym_task::TaskClient,
_gateway_client_registry: std::sync::Arc<
nym_wireguard_types::registration::GatewayClientRegistry,
>,
) -> Result<defguard_wireguard_rs::WGApi, Box<dyn std::error::Error + Send + Sync + 'static>> {
use crate::setup::{peer_allowed_ips, peer_static_public_key, PRIVATE_KEY};
use defguard_wireguard_rs::{
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
};
use nym_network_defaults::{WG_PORT, WG_TUN_DEVICE_ADDRESS};
let mut peers = vec![];
for peer_client in wireguard_data.inner.client_registry().iter() {
let mut peer = Peer::new(Key::new(peer_client.pub_key.to_bytes()));
let peer_ip_mask = IpAddrMask::new(peer_client.private_ip, 32);
peer.set_allowed_ips(vec![peer_ip_mask]);
peers.push(peer);
}
let ifname = String::from(WG_TUN_NAME);
let wg_api = defguard_wireguard_rs::WGApi::new(ifname.clone(), false)?;
wg_api.create_interface()?;
let ifname = String::from("wg0");
let wgapi = WGApi::new(ifname.clone(), false)?;
wgapi.create_interface()?;
let interface_config = InterfaceConfiguration {
name: ifname.clone(),
prvkey: BASE64_STANDARD.encode(wireguard_data.inner.keypair().private_key().to_bytes()),
address: wireguard_data.inner.config().private_ip.to_string(),
port: wireguard_data.inner.config().announced_port as u32,
peers,
prvkey: PRIVATE_KEY.to_string(),
address: WG_TUN_DEVICE_ADDRESS.to_string(),
port: WG_PORT as u32,
peers: vec![],
};
wg_api.configure_interface(&interface_config)?;
wgapi.configure_interface(&interface_config)?;
let peer = peer_static_public_key();
let mut peer = Peer::new(Key::new(peer.to_bytes()));
let peer_ip = peer_allowed_ips();
let peer_ip_mask = IpAddrMask::new(peer_ip.network_address(), peer_ip.netmask());
peer.set_allowed_ips(vec![peer_ip_mask]);
wgapi.configure_peer(&peer)?;
wgapi.configure_peer_routing(&[peer.clone()])?;
// Use a dummy peer to create routing rule for the entire network space
let mut catch_all_peer = Peer::new(Key::new([0; 32]));
let network = IpNetwork::new_truncate(
wireguard_data.inner.config().private_ip,
wireguard_data.inner.config().private_network_prefix,
)?;
catch_all_peer.set_allowed_ips(vec![IpAddrMask::new(
network.network_address(),
network.netmask(),
)]);
wg_api.configure_peer_routing(&[catch_all_peer])?;
tokio::spawn(async move { task_client.recv().await });
let wg_api = std::sync::Arc::new(WgApiWrapper::new(wg_api));
let mut controller = PeerController::new(wg_api.clone(), wireguard_data.peer_rx);
tokio::spawn(async move { controller.run(task_client).await });
Ok(wg_api)
Ok(wgapi)
}
#[cfg(not(target_os = "linux"))]
-58
View File
@@ -1,58 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::sync::Arc;
use defguard_wireguard_rs::{host::Peer, key::Key, WireguardInterfaceApi};
use tokio::sync::mpsc;
use crate::WgApiWrapper;
pub enum PeerControlMessage {
AddPeer(Peer),
RemovePeer(Key),
}
pub struct PeerController {
peer_rx: mpsc::UnboundedReceiver<PeerControlMessage>,
wg_api: Arc<WgApiWrapper>,
}
impl PeerController {
pub fn new(
wg_api: Arc<WgApiWrapper>,
peer_rx: mpsc::UnboundedReceiver<PeerControlMessage>,
) -> Self {
PeerController { wg_api, peer_rx }
}
pub async fn run(&mut self, mut task_client: nym_task::TaskClient) {
loop {
tokio::select! {
_ = task_client.recv() => {
log::trace!("PeerController handler: Received shutdown");
break;
}
msg = self.peer_rx.recv() => {
match msg {
Some(PeerControlMessage::AddPeer(peer)) => {
if let Err(e) = self.wg_api.inner.configure_peer(&peer) {
log::error!("Could not configure peer: {:?}", e);
}
}
Some(PeerControlMessage::RemovePeer(peer_pubkey)) => {
if let Err(e) = self.wg_api.inner.remove_peer(&peer_pubkey) {
log::error!("Could not remove peer: {:?}", e);
}
}
None => {
log::trace!("PeerController [main loop]: stopping since channel closed");
break;
}
}
}
}
}
}
}
+56
View File
@@ -0,0 +1,56 @@
use std::net::IpAddr;
use base64::{engine::general_purpose, Engine as _};
use log::info;
// The wireguard UDP listener
pub const WG_ADDRESS: &str = "0.0.0.0";
// The private key of the listener
// Corresponding public key: "WM8s8bYegwMa0TJ+xIwhk+dImk2IpDUKslDBCZPizlE="
pub(crate) const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg=";
// The AllowedIPs for the connected peer, which is one a single IP and the same as the IP that the
// peer has configured on their side.
const ALLOWED_IPS: &str = "10.1.0.2";
fn decode_base64_key(base64_key: &str) -> [u8; 32] {
general_purpose::STANDARD
.decode(base64_key)
.unwrap()
.try_into()
.unwrap()
}
pub fn server_static_private_key() -> x25519_dalek::StaticSecret {
// TODO: this is a temporary solution for development
let static_private_bytes: [u8; 32] = decode_base64_key(PRIVATE_KEY);
let static_private = x25519_dalek::StaticSecret::from(static_private_bytes);
let static_public = x25519_dalek::PublicKey::from(&static_private);
info!(
"wg public key: {}",
general_purpose::STANDARD.encode(static_public)
);
static_private
}
pub fn peer_static_public_key() -> x25519_dalek::PublicKey {
// A single static public key is used during development
// Read from NYM_PEER_PUBLIC_KEY env variable
let peer = std::env::var("NYM_PEER_PUBLIC_KEY").expect("NYM_PEER_PUBLIC_KEY must be set");
let peer_static_public_bytes: [u8; 32] = decode_base64_key(&peer);
let peer_static_public = x25519_dalek::PublicKey::from(peer_static_public_bytes);
info!(
"Adding wg peer public key: {}",
general_purpose::STANDARD.encode(peer_static_public)
);
peer_static_public
}
pub fn peer_allowed_ips() -> ip_network::IpNetwork {
let key: IpAddr = ALLOWED_IPS.parse().unwrap();
let cidr = 32u8;
ip_network::IpNetwork::new_truncate(key, cidr).unwrap()
}
+348 -284
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -32,7 +32,7 @@ cw-multi-test = { workspace = true }
cw3-flex-multisig = { path = "../multisig/cw3-flex-multisig" }
cw4-group = { path = "../multisig/cw4-group" }
rand_chacha = "0.3"
rand_chacha = "0.2"
[[test]]
name = "coconut-test"
@@ -25,7 +25,7 @@ nym-vesting-contract = { path = "../vesting" }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
# external dependencies
rand_chacha = "0.3"
rand_chacha = "0.2"
[[test]]
name = "mixnet-vesting-test"
+1 -1
View File
@@ -44,7 +44,7 @@ time = { version = "0.3", features = ["macros"] }
semver = { workspace = true, default-features = false }
[dev-dependencies]
rand_chacha = "0.3"
rand_chacha = "0.2"
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
[build-dependencies]
+1 -1
View File
@@ -33,7 +33,7 @@ cw-multi-test = { workspace = true }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
nym-sphinx-addressing = { path = "../../common/nymsphinx/addressing" }
rand = "0.8.5"
rand_chacha = "0.3"
rand_chacha = "0.2"
rstest = "0.17.0"
[features]
@@ -31,7 +31,7 @@ vergen = { version = "=7.4.3", default-features = false, features = ["build", "g
anyhow = "1.0.40"
cw-multi-test = { workspace = true }
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
rand_chacha = "0.3"
rand_chacha = "0.2"
rstest = "0.17.0"
[features]
-157
View File
@@ -2,160 +2,6 @@
This page displays a full list of all the changes during our release cycle from [`v2024.3-eclipse`](https://github.com/nymtech/nym/blob/nym-binaries-v2024.3-eclipse/CHANGELOG.md) onwards. Operators can find here the newest updates together with links to relevant documentation. The list is sorted so that the newest changes appear first.
## `v2024.5-ragusa`
- [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.5-ragusa)
- [Release CHANGELOG.md](https://github.com/nymtech/nym/blob/nym-binaries-v2024.5-ragusa/CHANGELOG.md)
- [`nym-node`](nodes/nym-node.md) version `1.1.2`
~~~admonish example collapsible=true title="CHANGELOG.md"
- Feature/nym node api location ([#4605])
- Add optional signature to IPR request/response ([#4604])
- Feature/unstable tested nodes endpoint ([#4601])
- nym-api: make report/avg_uptime endpoints ignore blacklist ([#4599])
- removed blocking for coconut in the final epoch state ([#4598])
- allow using explicit admin address for issuing freepasses ([#4595])
- Use rfc3339 for last_polled in described nym-api endpoint ([#4591])
- Explicitly handle constraint unique violation when importing credential ([#4588])
- [bugfix] noop flag for nym-api for nymvisor compatibility ([#4586])
- Chore/additional helpers ([#4585])
- Feature/wasm coconut ([#4584])
- upgraded axum and related deps to the most recent version ([#4573])
- Feature/nyxd scraper pruning ([#4564])
- Run cargo autoinherit on the main workspace ([#4553])
- Add rustls-tls to reqwest in validator-client ([#4552])
- Feature/rewarder voucher issuance ([#4548])
[#4605]: https://github.com/nymtech/nym/pull/4605
[#4604]: https://github.com/nymtech/nym/pull/4604
[#4601]: https://github.com/nymtech/nym/pull/4601
[#4599]: https://github.com/nymtech/nym/pull/4599
[#4598]: https://github.com/nymtech/nym/pull/4598
[#4595]: https://github.com/nymtech/nym/pull/4595
[#4591]: https://github.com/nymtech/nym/pull/4591
[#4588]: https://github.com/nymtech/nym/pull/4588
[#4586]: https://github.com/nymtech/nym/pull/4586
[#4585]: https://github.com/nymtech/nym/pull/4585
[#4584]: https://github.com/nymtech/nym/pull/4584
[#4573]: https://github.com/nymtech/nym/pull/4573
[#4564]: https://github.com/nymtech/nym/pull/4564
[#4553]: https://github.com/nymtech/nym/pull/4553
[#4552]: https://github.com/nymtech/nym/pull/4552
[#4548]: https://github.com/nymtech/nym/pull/4548
~~~
### Features
- New `nym-node` API endpoint `/api/v1/auxiliary-details`: to expose any additional information. Currently it's just the location. `nym-api` will then query all nodes for that information and put it in the `self-described` endpoint.
- New `nym-node` location available - use one of the three options to add this to your node config:
1. Update the `location` field under `[host]` section of `config.toml`
2. For new nodes: Initialise the node with `--location` flag, where they have to provide the country info. Either full country name (e.g. 'Jamaica'), two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided.
3. For existing nodes: It's also possible to use exactly the same `--location` argument as above, but make sure to also provide `--write-changes` (or `-w`) flag to persist those changes!
- [Feature/unstable tested nodes endpoint](https://github.com/nymtech/nym/pull/4601): Adds new data structures (`TestNode`, `TestRoute`, `PartialTestResult`) to handle test results for Mixnodes and Gateways. With the inclusion of pagination to handle large API responses efficiently. Lastly, introducing a new route with the tag `unstable` thus meaning not to be consumed without a user risk, prefixes in endpoints with unstable, are what it says on the tin.
~~~admonish example collapsible=true title="Testing steps performed"
- Deploy new api changes to sandbox environment
- Ensure current operations are transactional and standed operations are working
- Run a script to ensure that the new endpoints are working as expected with pagination
<img width="719" alt="image" src="https://github.com/nymtech/nym/assets/60836166/91285971-e82a-4e5a-8a58-880505ae1be9">
~~~
- [`nym-api`: make report/avg_uptime endpoints ignore blacklist](https://github.com/nymtech/nym/pull/4599): When querying for node specific data, it's no longer going to go through the entire list of all cached (and filtered nodes) to find it; instead it will attempt to retrieve a single unfiltered entry.
~~~admonish example collapsible=true title="Testing steps performed"
- Build the project and deployed it in a test environment.
- Manually test API endpoints for mixnode and gateway data.
- Verify that the endpoints return the expected data and handle blacklists correctly.
- API performance improved due to the efficient `HashMap` lookups
- Data in mainnet will differ from test nets due to the increased amount of gateways and mixnodes in that environment
- Test standard uptime routes:
```sh
curl -X 'GET' 'https://validator.nymtech.net/api/v1/status/gateway/Fo4f4SQLdoyoGkFae5TpVhRVoXCF8UiypLVGtGjujVPf/avg_uptime' -H 'accept: application/json'
```
~~~
- [Use rfc3339 for last_polled in described nym-api endpoint](https://github.com/nymtech/nym/pull/4591): Fix issue where the validator-client can't parse the nym-api response for the described endpoint, in particular the `latest_polled` field that was recently added, by making the field use `rfc3339`
- **Note:** This will require upgrading `nym-api` and everything that depends on the described endpoint.
~~~admonish example collapsible=true title="Testing steps performed"
- Update a `nym-api` to the binary built from this branch, then restart the api
- Check the `journalctl` for error messages
- Connected via client and could not see the error messages, this is backwards compatible
- Local testing using sdk examples:
```sh
cd <PATH_TO>/nym/sdk/rust/nym-sdk
cargo run --example simple
# outcome
thread 'main' panicked at sdk/rust/nym-sdk/examples/simple.rs:9:64:
called Result::unwrap() on an Err value: ClientCoreError(ValidatorClientError(NymAPIError { source: ReqwestClientError { source: reqwest::Error { kind: Request, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None,
```
~~~
- [Upgrade `axum` and related dependencies to the most recent version](https://github.com/nymtech/nym/pull/4573)
- [Run cargo autoinherit on the main workspace](https://github.com/nymtech/nym/pull/4553): Move several dependencies to the workspace level using cargo autoinherit, to make it easier to keep our dependencies up to date.
- Run cargo autoinherit in the root
- Merge in the new workspace deps in the main list
- We made sure to not mix in other changes as well - all features flags for all crates should be the same as before
~~~admonish example collapsible=true title="Testing steps performed"
- Run `cargo autoinherit` in the root directory to move dependencies to the workspace level
- Merge the new workspace dependencies into the main list
- Ensure no other changes were mixed in during the process
- Verify that all feature flags for all crates remained the same as before
- Build all the binaries from this branch to confirm successful compilation
- Deploy the built binaries across different environments to ensure there were no issues
~~~
- [Add rustls-tls to reqwest in validator-client](https://github.com/nymtech/nym/pull/4552): An attempt to make possible to end up in a situation where use use the validator-client but without functioning TLS support. For the monorepo this is masked by cargo feature unification, but becomes a problem for outside consumers, as as been noticed in many of the vpn client implementations.
- In `validator-client`: `reqwest`, enable `rustls-tls` for `non-wasm32`
- In `client-core`: Use default features enabled for `non-wasm32` and switch to `webpki` roots, since that's what we're using with `reqwest` anyway
- In `gateway-client`: Switch to `webpki` roots, since that's what we're using with `reqwest` anyway
#### Crypto
- [Remove blocking for coconut in the final epoch state](https://github.com/nymtech/nym/pull/4598)
~~~admonish example collapsible=true title="Testing steps performed"
- Build the project to ensure no compilation errors
- Run tests to verify the functionality of the `issue_credential` function
- Execute integration tests to check the behaviour during an epoch transition.
~~~
- [Allow using explicit admin address for issuing freepasses](https://github.com/nymtech/nym/pull/4595)
- [Explicitly handle constraint unique violation when importing credential](https://github.com/nymtech/nym/pull/4588): Add a strong type for when a duplicate credential is imported so the vpn lib can handle this.
- [Feature/wasm coconut](https://github.com/nymtech/nym/pull/4584): This pull request requires [\#4585](https://github.com/nymtech/nym/pull/4585) to be merged first
- [Feature/nyxd scraper pruning](https://github.com/nymtech/nym/pull/4564): This PR introduces storage pruning to `nyxd` scraper which is then used by the validators rewarder.
~~~admonish example collapsible=true title="Testing steps performed"
- Add a `main.rs` file in the `nyxd` scraper dir, underneath `lib.rs`, amend `config.pruning_options.validate()?;` to be `let _ = config.pruning_options.validate();` in the mod.rs file
- Test the different variations of `pruning_options`:
- Check the *default* option: `pruning_options: PruningOptions::default()`
- Check the *nothing* option: `pruning_options: PruningOptions::nothing()`
- Check the *custom* option, example: `pruning_options: PruningOptions { keep_recent: (500), interval: (10), strategy: (PruningStrategy::Custom) }`
- Check the pruning *in real life* for the validator rewarder
- Validate that the database table `blocks` was being updated accordingly
~~~
- [Feature/rewarder voucher issuance](https://github.com/nymtech/nym/pull/4548)
- Introduces signature checks on issued credential data
- Stores evidence of any failures/malicious behaviour in the internal db
### Bugfix
- [`noop` flag for `nym-api` for `nymvisor` compatibility](https://github.com/nymtech/nym/pull/4586)
- The application starts correctly and logs the starting message
- The `--no_banner` flag works as intended, providing compatibility with `nymvisor`
~~~admonish example collapsible=true title="Testing steps performed"
- Build the project to ensure no compilation errors
- Run the binary with different command-line arguments to verify the CLI functionality
- Test with and without the `--no_banner` flag to ensure compatibility and expected behavior
- Verify logging setup and configuration file parsing
~~~
### Operators Guide updates
- [`nym-gateway-probe`](testing/gateway-probe.md): A CLI tool to check in-real-time networking status of any Gateway locally.
- [Where to host your `nym-node`?](legal/isp-list.md): A list of Internet Service Providers (ISPs) by Nym Operators community. We invite all operators to add their experiences with different ISPs to strengthen the community knowledge and Nym mixnet performance.
- Make sure you run `nym-node` with `--wireguard-enabled false` and add a location description to your `config.toml`, both documented in [`nym-node` setup manual](nodes/setup.md#mode-exit-gateway).
---
## `v2024.4-nutella`
- [Merged PRs](https://github.com/nymtech/nym/milestone/59?closed=1)
@@ -168,9 +14,6 @@ called Result::unwrap() on an Err value: ClientCoreError(ValidatorClientError(Ny
- [Network configuration](nodes/configuration.md#connectivity-test-and-configuration) section updates, in particular for `--mode mixnode` operators
- [VPS IPv6 troubleshooting](troubleshooting/vps-isp.md#ipv6-troubleshooting) updates
---
## `v2024.3-eclipse`
- Release [Changelog.md](https://github.com/nymtech/nym/blob/nym-binaries-v2024.3-eclipse/CHANGELOG.md)
@@ -6,5 +6,3 @@
[Cherry Servers](https://www.cherryservers.com),"Lithuania, Netherlands, USA, Singapore","No","Yes","Issued IP doesnt match the location offered by the provider.","05/2024"
[Njalla](https://nja.la),"Sweden","Yes","Yes","Privacy vandguards! The biggest VPS 45 is 3 cores only, but it works better than many “larger” servers on the market.","05/2024"
[HostSailor](https://hostsailor.com),"USA","Yes, based on ticket","Yes","The IPv6 setup needs custom research and is not documented","05/2024"
[Misaka](https://www.misaka.io/),"South Africa","Yes, native support","No","Very Expensive","05/2024"
[IsHosting](https://ishosting.com/en),"Brazil, Netherlands","Yes, based on ticket","Yes","Expensive","05/2024"
1 **ISP** **Locations** **Public IPv6** **Crypto Payments** **Comments** **Last Updated**
6 [Cherry Servers](https://www.cherryservers.com) Lithuania, Netherlands, USA, Singapore No Yes Issued IP doesn’t match the location offered by the provider. 05/2024
7 [Njalla](https://nja.la) Sweden Yes Yes Privacy vandguards! The biggest VPS 45 is 3 cores only, but it works better than many “larger” servers on the market. 05/2024
8 [HostSailor](https://hostsailor.com) USA Yes, based on ticket Yes The IPv6 setup needs custom research and is not documented 05/2024
[Misaka](https://www.misaka.io/) South Africa Yes, native support No Very Expensive 05/2024
[IsHosting](https://ishosting.com/en) Brazil, Netherlands Yes, based on ticket Yes Expensive 05/2024
+17 -15
View File
@@ -26,7 +26,7 @@ Once VPS and Nym wallet are configured, binaries ready, the operators of `nym-no
During the testing events series [Fast and Furious](https://nymtech.net/events/fast-and-furious) we found out, that after introducing IP Packet Router and [Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) as default features, only a fragment of Exit Gateways routes correctly through IPv4 and IPv6. We built a useful monitor to check out your Gateway (`nym-node --mode exit-gateway`) at [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/).
Below is a fast - *ten command* - deployment for seasoned operators to migrate and setup the node, configure networking and connectivity and verify that it all works as it should by getting two free jokes through the Mixnet.
Below is a fast - ten commands - deployment for seasoned operators to migrate and setup the node, configure networking and connectivity and verify that it all works as it should by getting two free jokes through the Mixnet.
```admonish caution
If you are not well familiar with `nym-node` setup, automation, and `nymtun0` configuration, follow the [steps above](#steps-for-nym-node-operators) page by page. You can use this flow as a reference later on.
@@ -39,22 +39,20 @@ If you are not well familiar with `nym-node` setup, automation, and `nymtun0` co
curl -o network_tunnel_manager.sh -L https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/9d785d6ee3aa2970553633eccbd89a827f49fab5/network_tunnel_manager.sh && chmod +x network_tunnel_manager.sh
```
3. In case you had a`nym-gateway` running, stop the process (directly or systemd service), and [**migrate to `nym-node`**](setup.md#migrate) now!
3. If you have a running `nym-node` or `nym-gateway` (alone or service), stop the process
- In case your node was a `nym-gateway`, [**migrate to `nym-node`**](setup.md#migrate) now!
4. Apply the rules:
```sh
sudo ./network_tunnel_manager.sh apply_iptables_rules
```
5. Check Nymtun IP tables:
4. Check Nymtun IP tables:
```sh
sudo ./network_tunnel_manager.sh check_nymtun_iptables
```
- if there's no process running it shouldn't get anything
6. Display IPv6:
5. Display IPv6:
```sh
sudo ./network_tunnel_manager.sh fetch_and_display_ipv6
```
- You should see a `global ipv6` address:
- If you have a `global ipv6` address this is good, if not the next step should fix it
~~~admonish example collapsible=true title="Correct `./network_tunnel_manager.sh fetch_and_display_ipv6` output:"
```sh
iptables-persistent is already installed.
@@ -63,18 +61,21 @@ operation fetch_ipv6_address_nym_tun completed successfully.
```
~~~
6. Apply the rules:
```sh
sudo ./network_tunnel_manager.sh apply_iptables_rules
```
- and check them again like in point 4.
7. (If you didn't have a `nym-node` service yet) Create `systemd` [automation and configuration file](configuration.md#systemd), reload and enable the service
8. Start `nym-node` service:
```sh
sudo service nym-node start && journalctl -u nym-node -f -n 100
```
9. Upgrade your node version in the smart contract, [using Nym wallet](manual-upgrade.md#step-2-updating-your-node-information-in-the-smart-contract)
- If you don't run this as an upgrade but started a fresh new node, you need to [bond](bonding.md) the gateway now. After that finish the verification steps below.
10. After a minute of running properly, validate your `nymtun0` routing:
- Display the address
9. After a minute of running properly, check `nymtun0`:
```sh
ip addr show nymtun0
```
@@ -93,8 +94,9 @@ ip addr show nymtun0
```
~~~
- Run a joke through the Mixnet - you should get two jokes (IPv4 and IPv6 routing):
10. Validate your IPv6 and IPv4 networking by running a joke via Mixnet:
```sh
sudo ./network_tunnel_manager.sh joke_through_the_mixnet
```
Make sure that you get the validation of IPv4 and IPv6 connectivity, in case of problems, check [troubleshooting page](../troubleshooting/vps-isp.md#incorrect-gateway-network-check). After proceed to [bonding](bonding.md).
+110 -29
View File
@@ -28,7 +28,7 @@ Currently `nym-node` binary enables to run only one `--mode` at a time. In the f
Every `exit-gateway` mode is basically an `entry-gateway` with NR (Network Requester) and IPR (IP Packet Router) enabled. This means that every `exit-gateway` is automatically seen as an `entry-gateway` but not the opposite.
Gateway operators can check out the node performance, connectivity and much more in our new tool [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/).
Gateway operators can check out the performance, connectivity and much more in our new tool [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/).
To determine which mode your node is running, you can check the `:8080/api/v1/roles` endpoint. For example:
```
@@ -56,10 +56,6 @@ https://<DOMAIN>/api/v1/swagger/#/
There are a few changes from the individual binaries used in the past. For example by default `run` command does `init` function as well, local node `--id` will be set by default unless specified otherwise etcetera.
```admonish info
You can always use `--help` flag to see the commands or arguments associated with a given command.
```
Run `./nym-node --help` to see all available commands:
~~~admonish example collapsible=true title="`./nym-node --help` output:"
@@ -68,6 +64,31 @@ Run `./nym-node --help` to see all available commands:
```
~~~
<!--
IN CASE CMD-RUN DOESN'T WORK HAR PASTE THIS:
Usage: nym-node [OPTIONS] <COMMAND>
Commands:
build-info Show build information of this binary
bonding-information Show bonding information of this node depending on its currently selected mode
node-details Show details of this node
migrate Attempt to migrate an existing mixnode or gateway into a nym-node
run Start this nym-node
sign Use identity key of this node to sign provided message
help Print this message or the help of the given subcommand(s)
Options:
-c, --config-env-file <CONFIG_ENV_FILE>
Path pointing to an env file that configures the nym-node and overrides any preconfigured values [env: NYMNODE_CONFIG_ENV_FILE_ARG=]
--no-banner
Flag used for disabling the printed banner in tty [env: NYMNODE_NO_BANNER=]
-h, --help
Print help
-V, --version
Print version
-->
To list all available flags for each command, run `./nym-node <COMMAND> --help` for example `./nym-node run --help`:
~~~admonish example collapsible=true title="`./nym-node run --help` output:"
@@ -76,17 +97,89 @@ To list all available flags for each command, run `./nym-node <COMMAND> --help`
```
~~~
```admonish bug
The Wireguard flags currently have limited functionality. This feature is under development and testing.
<!-- IN CASE CMD-RUN DOESN'T WORK HAR PASTE THIS:
**Keep Wireguard disabled for the time being!**
```
Start this nym-node
Usage: nym-node run [OPTIONS]
Options:
--id <ID>
Id of the nym-node to use [env: NYMNODE_ID=] [default: default-nym-node]
--config-file <CONFIG_FILE>
Path to a configuration file of this node [env: NYMNODE_CONFIG=]
--deny-init
Forbid a new node from being initialised if configuration file for the provided specification doesn't already exist [env: NYMNODE_DENY_INIT=]
--init-only
If this is a brand new nym-node, specify whether it should only be initialised without actually running the subprocesses [env: NYMNODE_INIT_ONLY=]
--mode <MODE>
Specifies the current mode of this nym-node [env: NYMNODE_MODE=] [possible values: mixnode, entry-gateway, exit-gateway]
-w, --write-changes
If this node has been initialised before, specify whether to write any new changes to the config file [env: NYMNODE_WRITE_CONFIG_CHANGES=]
--bonding-information-output <BONDING_INFORMATION_OUTPUT>
Specify output file for bonding information of this nym-node, i.e. its encoded keys. NOTE: the required bonding information is still a subject to change and this argument should be treated only as a preview of future features [env: NYMNODE_BONDING_INFORMATION_OUTPUT=]
-o, --output <OUTPUT>
Specify the output format of the bonding information (`text` or `json`) [env: NYMNODE_OUTPUT=] [default: text] [possible values: text, json]
--public-ips <PUBLIC_IPS>
Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients. In nearly all circumstances, it's going to be identical to the address you're going to use for bonding [env: NYMNODE_PUBLIC_IPS=]
--hostname <HOSTNAME>
Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients [env: NYMNODE_HOSTNAME=]
--location <LOCATION>
Optional **physical** location of this node's server. Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g. 'PL'), three-letter alpha3 (e.g. 'POL') or three-digit numeric-3 (e.g. '616') can be provided [env: NYMNODE_LOCATION=]
--http-bind-address <HTTP_BIND_ADDRESS>
Socket address this node will use for binding its http API. default: `0.0.0.0:8080` [env: NYMNODE_HTTP_BIND_ADDRESS=]
--landing-page-assets-path <LANDING_PAGE_ASSETS_PATH>
Path to assets directory of custom landing page of this node [env: NYMNODE_HTTP_LANDING_ASSETS=]
--http-access-token <HTTP_ACCESS_TOKEN>
An optional bearer token for accessing certain http endpoints. Currently only used for prometheus metrics [env: NYMNODE_HTTP_ACCESS_TOKEN=]
--expose-system-info <EXPOSE_SYSTEM_INFO>
Specify whether basic system information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_INFO=] [possible values: true, false]
--expose-system-hardware <EXPOSE_SYSTEM_HARDWARE>
Specify whether basic system hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE=] [possible values: true, false]
--expose-crypto-hardware <EXPOSE_CRYPTO_HARDWARE>
Specify whether detailed system crypto hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true, false]
--mixnet-bind-address <MIXNET_BIND_ADDRESS>
Address this node will bind to for listening for mixnet packets default: `0.0.0.0:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=]
--nym-api-urls <NYM_API_URLS>
Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=]
--nyxd-urls <NYXD_URLS>
Addresses to nyxd chain endpoint which the node will use for chain interactions [env: NYMNODE_NYXD=]
--wireguard-enabled <WIREGUARD_ENABLED>
Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS>
Socket address this node will use for binding its wireguard interface. default: `0.0.0.0:51822` [env: NYMNODE_WG_BIND_ADDRESS=]
--wireguard-private-network-ip <WIREGUARD_PRIVATE_NETWORK_IP>
Ip address of the private wireguard network. default: `10.1.0.0` [env: NYMNODE_WG_IP_NETWORK=]
--wireguard-announced-port <WIREGUARD_ANNOUNCED_PORT>
Port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=]
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX>
The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is 32 and for IPv6 is 128 [env: NYMNODE_WG_PRIVATE_NETWORK_PREFIX=]
--verloc-bind-address <VERLOC_BIND_ADDRESS>
Socket address this node will use for binding its verloc API. default: `0.0.0.0:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=]
--entry-bind-address <ENTRY_BIND_ADDRESS>
Socket address this node will use for binding its client websocket API. default: `0.0.0.0:9000` [env: NYMNODE_ENTRY_BIND_ADDRESS=]
--announce-ws-port <ANNOUNCE_WS_PORT>
Custom announced port for listening for websocket client traffic. If unspecified, the value from the `bind_address` will be used instead [env: NYMNODE_ENTRY_ANNOUNCE_WS_PORT=]
--announce-wss-port <ANNOUNCE_WSS_PORT>
If applicable, announced port for listening for secure websocket client traffic [env: NYMNODE_ENTRY_ANNOUNCE_WSS_PORT=]
--enforce-zk-nyms <ENFORCE_ZK_NYMS>
Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet or if it also accepts non-paying clients [env: NYMNODE_ENFORCE_ZK_NYMS=] [possible values: true, false]
--mnemonic <MNEMONIC>
Custom cosmos wallet mnemonic used for zk-nym redemption. If no value is provided, a fresh mnemonic is going to be generated [env: NYMNODE_MNEMONIC=]
--upstream-exit-policy-url <UPSTREAM_EXIT_POLICY_URL>
Specifies the url for an upstream source of the exit policy used by this node [env: NYMNODE_UPSTREAM_EXIT_POLICY=]
--open-proxy <OPEN_PROXY>
Specifies whether this exit node should run in 'open-proxy' mode and thus would attempt to resolve **ANY** request it receives [env: NYMNODE_OPEN_PROXY=] [possible values: true, false]
-h, --help
Print help
-->
The Wireguard flags currently have limited functionality, with `--wireguard-enabled` being the most relevant, enabling or disabling wireguard functionality.
#### Flags Summary
Some of the most useful flags and their explanation:
~~~admonish example collapsible=true title="Flags explanation:"
- `--id <YOUR_ID>`: Local identifier of your node. This `<ID>` determines your config path located at `~/.nym/nym-nodes/<ID>/config/config.toml`, default value is `default-nym-node`
- `--config-file <PATH>`: Used for the migrate command to indicate the location of the existing node config file. Default path is `~/.nym/nym-nodes/default-nym-node/config/config.toml`
- `--deny-init`: Use this flag to prevent a new node from being initialized. It's recommended to use this after the first run to avoid accidental spinning up of a second node.
@@ -97,9 +190,9 @@ Some of the most useful flags and their explanation:
- `--expose-system-info <true/false>`: Sets your system info visibility on the network.
- `--expose-system-hardware <true/false>`: Sets your system hardware info visibility on the network.
- `--expose-crypto-hardware <true/false>`: Sets your crypto hardware info visibility on the network.
~~~
### Commands & Examples
## Commands & Examples
**`nym-node` introduces a default human readible ID (local only) `default-nym-node`, which is used if there is not an explicit custom `--id <ID>` specified. All configuration is stored in `~/.nym/nym-nodes/default-nym-node/config/config.toml` or `~/.nym/nym-nodes/<ID>/config/config.toml` respectively.**
@@ -123,34 +216,22 @@ To prevent over-flooding of our documentation we cannot provide with every singl
As part of the transition, `allowed.list` on Exit Gateway embedded Network Requester was depreciated.
**Initialise and run** in one command:
**Initialise and run:**
```sh
# simple default
./nym-node run --mode exit-gateway
# with other options
./nym-node run --id <ID> --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "<YOUR_DOMAIN>" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location <COUNTRY_FULL_NAME> --wireguard-enabled false
# <YOUR_DOMAIN> is in format without 'https://' prefix
# <COUNTRY_FULL_NAME> is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided.
# keep wireguard disabled
./nym-node run --id <ID> --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "<YOUR_DOMAIN>" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --wireguard-enabled true
```
**Initialise only** without running the node with `--init-only` command :
Initialise only with a custom `--id` and `--init-only` command :
```sh
# simple default
./nym-node run --init-only --mode exit-gateway
# with a custom `--id` and other options
./nym-node run --id <ID> --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "<YOUR_DOMAIN>" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 true --location <COUNTRY_FULL_NAME> --wireguard-enabled false
# <YOUR_DOMAIN> is in format without 'https://' prefix
# <COUNTRY_FULL_NAME> is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided.
# keep wireguard disabled
./nym-node run --id <ID> --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "<YOUR_DOMAIN>" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 true --wireguard-enabled true
```
Run the node with custom `--id` without initialising, using `--deny-init` command
Run the node with custom `--id` without initialising
```sh
./nym-node run --id <ID> --deny-init --mode exit-gateway
```
@@ -24,7 +24,7 @@ git clone https://github.com/nymtech/nym-vpn-client.git
2. Build `nym-gateway-probe`:
```sh
cd nym-vpn-client/nym-vpn-core
cd nym-vpn-client
cargo build --release -p nym-gateway-probe
```
@@ -34,7 +34,7 @@ cargo build --release -p nym-gateway-probe
```sh
./target/release/nym-gateway-probe --help
```
~~~admonish example collapsible=true title="`nym-gateway-probe --help`"
~~~admonish collapsible=true
```
Usage: nym-gateway-probe [OPTIONS]
@@ -48,7 +48,7 @@ Options:
```
~~~
To run the client, simply add a flag `--gateway` with a targeted gateway identity key.
To run the client, simply add a flag `--gateway` with a targeted gateway identity key.
```sh
./target/release/nym-gateway-probe --gateway <GATEWAY_IDENTITY_KEY>
@@ -74,6 +74,6 @@ For any `nym-node --mode exit-gateway` the aim is to have this outcome:
}
```
If your Gateway is blacklisted, the probe will not work.
If you don't provide a `--gateway` flag it will pick a random one to test.
@@ -124,13 +124,13 @@ nym-node 103349 root 57u IPv6 1333229976 0t0 TCP [2a03:b0c0:3:d0::ff3:f
##### Query `systemd` journal with `journalctl`
```sh
```
sudo journalctl -u nym-node -o cat | grep "Since startup mixed"
```
If you have created `nym-node.service` file (i.e. you are running your Ny, Node via `systemd`) then this command shows you how many packets have you mixed so far, and should return a list of messages like this:
```sh
```
2021-05-18T12:35:24.057Z INFO nym_node::node::metrics > Since startup mixed 233639 packets!
2021-05-18T12:38:02.178Z INFO nym_node::node::metrics > Since startup mixed 233739 packets!
2021-05-18T12:40:32.344Z INFO nym_node::node::metrics > Since startup mixed 233837 packets!
@@ -146,7 +146,7 @@ A `build-info` command prints the build information like commit hash, rust versi
For example `./target/debug/nym-node --no-banner build-info --output json` will return:
```sh
```
{"binary_name":"nym-network-requester","build_timestamp":"2023-07-24T15:38:37.00657Z","build_version":"1.1.23","commit_sha":"c70149400206dce24cf20babb1e64f22202672dd","commit_timestamp":"2023-07-24T14:45:45Z","commit_branch":"feature/simplify-cli-parsing","rustc_version":"1.71.0","rustc_channel":"stable","cargo_profile":"debug"}
```
@@ -154,13 +154,13 @@ For example `./target/debug/nym-node --no-banner build-info --output json` will
##### Scan ports with `nmap`:
```sh
```
nmap -p 1789 <IP ADDRESS> -Pn
```
If your Nym Node is configured properly it should output something like this:
```sh
```
bob@desktop:~$ nmap -p 1789 95.296.134.220 -Pn
Host is up (0.053s latency).
@@ -169,16 +169,9 @@ PORT STATE SERVICE
1789/tcp open hello
```
##### Check with `telnet`
Your node should connect to telnet when running:
```sh
telnet <IP_ADDRESS> <PORT>
```
##### Query online nodes:
```sh
```
curl --location --request GET 'https://validator.nymtech.net/api/v1/mixnodes/'
```
@@ -191,15 +184,6 @@ You can query Gateways by replacing `nym-mixnodes` with `nym-gateways` in the ab
We currently have an API set up returning our metrics tests of the network. There are two endpoints to ping for information about your Mix Node, `report` and `history`. Find more information about this in the [Mixnodes metrics documentation](../nodes/maintenance.md#metrics--api-endpoints).
For more information about available endpoints and their status, you can refer to:
```sh
# for http
http://<IP>:8080/api/v1/swagger/#/
# for https reversed proxy
https://<DOMAIN>/api/v1/swagger/#/
```
### Why is my node not mixing any packets?
If you are still unable to see your node on the dashboard, or your node is declaring it has not mixed any packets, there are several potential issues:
@@ -245,6 +229,12 @@ Check that you have provided the correct information when bonding your Nym Node
> All delegated stake will be lost when un-bonding! However the Nym Node must be operational in the first place for the delegation to have any effect.
#### Missing `announce-host` flag
On certain cloud providers such as AWS and Google Cloud, you need to do some additional configuration of your firewall and use `--host` with your **local ip** and `--announce-host` with the **public ip** of your Mix Node host.
If the difference between the two is unclear, contact the help desk of your VPS provider.
### Running on a local machine behind NAT with no fixed IP address
Your ISP has to be IPv6 ready if you want to run a Nym Node on your local machine. Sadly, in 2020, most of them are not and you won't get an IPv6 address by default from your ISP. Usually it is an extra paid service or they simply don't offer it.
@@ -272,7 +262,43 @@ Most of the `ERROR` and `WARN` messages in your node logs are benign - as long a
More specific errors and warnings are covered below.
#### `tokio runtime worker` error
If you are running into issues with an error including the following:
```
thread 'tokio-runtime-worker' panicked at 'Failed to create TCP listener: Os { code: 99, kind: AddrNotAvailable, message: "Cannot assign requested address" }'
```
Then you need to `--announce-host <PUBLIC_IP>` and `--host <LOCAL_IP>` on startup. This issue is addressed [above](#missing-`announce-host`-flag)
<!-- NEEDS TO BE REWORKED AND ADD WARNING TO NOT CHANGE OTHER PORTS FOR API
### Can I use a port other than 1789?
Yes! Here is what you will need to do:
Assuming you would like to use port `1337` for your Nym Node, you need to open the new port (and close the old one):
```
sudo ufw allow 1337
sudo ufw deny 1789
```
And then edit the node's `config.toml`.
> If you want to change the port for an already running node, you need to stop the process before editing your config file.
The config file is located at `~/.nym/nym-nodes/<ID>/config/config.toml`.
For example, assuming `<YOUR_ID>` was chosen to be `alice-node`:
```
nano ~/.nym/nym-nodes/alice-node/config/config.toml
```
You will need to edit two parts of the file. `announce_address` and `listening_address` in the `config.toml` file. Simply replace `:1789` (the default port) with `:1337` (your new port) after your IP address.
Finally, restart your node. You should see if the Mix Node is using the port you have changed in the config.toml file right after you run the node.
-->
### What is `verloc` and do I have to configure my Nym Node to implement it?
`verloc` is short for _verifiable location_. Mix Nodes and Gateways now measure speed-of-light distances to each other, in an attempt to verify how far apart they are. In later releases, this will allow us to algorithmically verify node locations in a non-fake-able and trustworthy manner.
@@ -296,68 +322,17 @@ Nym API measures performance by routing traffic through the Mixnet. If the avera
In case your Gateway appeared on the [blacklist](https://validator.nymtech.net/api/v1/gateways/blacklisted), it's because there is some flaw in the configuration. The most common sources of problems are:
- Bonding before starting the node/service
- Bonding before opening [needed ports](../nodes/vps-setup.md#configure-your-firewall)
- Bonding before opening [the needed ports](../nodes/vps-setup.md#configure-your-firewall)
- VPS restarted without operator having a [systemd automation](../nodes/configuration.md#systemd) or some alert notification flow setup
What to do:
1. Make sure your node is running and do not stop it if there is no need
2. Open all needed [needed ports](../nodes/vps-setup.md#configure-your-firewall)
3. Check your `config.toml` - often people have filled `hostname` without such hostname being configured or a wrong IP address after moving their node.
4. [Check Gateway Connectivity](#check-gateway-connectivity)
5. See logs of your Gateway and search [for errors](#nym-node-errors) - if you find any unusual one, you can ask in the [Element Node Operators](https://matrix.to/#/#operators:nymtech.chat) channel
- If your logs show that your Node has `cover down: 0.00` that means that the embedded IPR and NR is not sending any cover traffic.
6. When all problems addressed:Wait until your node gets above 50% of performance (average of last 24h) - this will likely take several hours, up to a day. During this time your node is tested by `nym-api` and every positive response picks up your Gateway's routing score.
- Make sure your node is running and do not stop it if there is no need
- Open all needed ports
- Wait until your node gets above 50% of performance (average of last 24h) - this will likely take several hours, up to a day. During this time your node is tested by `nym-api` and every positive response picks up your Gateway's routing score.
**Do not restart your Nym Node without reason, your routing score will only get worse!**
### Check Gateway connectivity
**1. Check out the API endpoints**
Start with checking if your Gateway IPR and NR is active. To determine which mode your node is running, you can check the `:8080/api/v1/roles` endpoint. For example:
```
# for http
http://<IP_ADDRESS>:8080/api/v1/roles
# for https reversed proxy
https://<DOMAIN>/api/v1/roles
```
Everything necessary will exist on your node by default. For instance, if you're running a mixnode, you'll find that a NR (Network Requester) and IPR (IP Packet Router) address exist, but they will be ignored in `mixnode` mode.
For more information about available endpoints and their status, you can refer to:
```sh
# for http
http://<IP>:8080/api/v1/swagger/#/
# for https reversed proxy
https://<DOMAIN>/api/v1/swagger/#/
```
**2. Configure IPv4 and IPv6 tables and rules**
- In case you haven't, follow the steps in the node [configuration](../nodes/configuration.md) chapter [connectivity test and configurastion](../nodes/configuration.md#connectivity-test-and-configuration).
**3. Test connectivity**
- Telnet - from your local machine try to connect to your VPS bu running:
```sh
telnet <IP_ADDRESS> <PORT>
```
- [Websocket wcat](https://github.com/websockets/wscat):
- Install on your local machine:
```sh
sudo apt install node-ws
```
- Run `wscat` pointing to the IP of your VPS with port `9000`:
```
wscat -c ws://<IP>:<PORT>
```
### My exit Gateway "is still not online..."
The Nyx chain epoch takes up to 60 min. To prevent the Gateway getting blacklisted, it's essential to start it before the bonding process and let it running. In case it already got [blacklisted](#my-gateway-is-backlisted) check the steps above.
+1 -1
View File
@@ -30,7 +30,7 @@ humantime-serde = { workspace = true }
ipnetwork = "0.16"
log = { workspace = true }
once_cell = { workspace = true }
rand = { workspace = true }
rand = "0.7"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { workspace = true, features = [
+1 -1
View File
@@ -15,7 +15,7 @@ bs58 = { workspace = true }
futures = { workspace = true }
generic-array = { workspace = true, features = ["serde"] }
log = { workspace = true }
rand = { workspace = true }
rand = { version = "0.7.3", features = ["wasm-bindgen"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
@@ -82,10 +82,8 @@ impl SharedKeys {
)
}
};
let mac = compute_keyed_hmac::<GatewayIntegrityHmacAlgorithm>(
self.mac_key().as_slice(),
&encrypted_data,
);
let mac =
compute_keyed_hmac::<GatewayIntegrityHmacAlgorithm>(self.mac_key(), &encrypted_data);
mac.into_bytes().into_iter().chain(encrypted_data).collect()
}
@@ -104,7 +102,7 @@ impl SharedKeys {
let message_bytes = &enc_data[mac_size..];
if !recompute_keyed_hmac_and_verify_tag::<GatewayIntegrityHmacAlgorithm>(
self.mac_key().as_slice(),
self.mac_key(),
message_bytes,
mac_tag,
) {
+1 -1
View File
@@ -421,7 +421,7 @@ impl BinaryResponse {
let message_bytes = &raw_req[mac_size..];
if !recompute_keyed_hmac_and_verify_tag::<GatewayIntegrityHmacAlgorithm>(
shared_keys.mac_key().as_slice(),
shared_keys.mac_key(),
message_bytes,
mac_tag,
) {
+6 -36
View File
@@ -6,7 +6,6 @@ use nym_gateway::config::old_config_v1_1_20::ConfigV1_1_20;
use nym_gateway::config::old_config_v1_1_28::ConfigV1_1_28;
use nym_gateway::config::old_config_v1_1_29::ConfigV1_1_29;
use nym_gateway::config::old_config_v1_1_31::ConfigV1_1_31;
use nym_gateway::config::old_config_v1_1_36::ConfigV1_1_36;
use nym_gateway::config::{default_config_filepath, Config};
use nym_gateway::error::GatewayError;
@@ -25,8 +24,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, GatewayError> {
let updated_step1: ConfigV1_1_28 = old_config.into();
let updated_step2: ConfigV1_1_29 = updated_step1.into();
let updated_step3: ConfigV1_1_31 = updated_step2.into();
let updated_step4: ConfigV1_1_36 = updated_step3.into();
let updated: Config = updated_step4.into();
let updated: Config = updated_step3.into();
updated
.save_to_default_location()
.map_err(|err| GatewayError::ConfigSaveFailure {
@@ -50,8 +48,7 @@ fn try_upgrade_v1_1_28_config(id: &str) -> Result<bool, GatewayError> {
let updated_step1: ConfigV1_1_29 = old_config.into();
let updated_step2: ConfigV1_1_31 = updated_step1.into();
let updated_step3: ConfigV1_1_36 = updated_step2.into();
let updated: Config = updated_step3.into();
let updated: Config = updated_step2.into();
updated
.save_to_default_location()
.map_err(|err| GatewayError::ConfigSaveFailure {
@@ -74,30 +71,6 @@ fn try_upgrade_v1_1_29_config(id: &str) -> Result<bool, GatewayError> {
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_31 = old_config.into();
let updated_step2: ConfigV1_1_36 = updated_step1.into();
let updated: Config = updated_step2.into();
updated
.save_to_default_location()
.map_err(|err| GatewayError::ConfigSaveFailure {
path: default_config_filepath(id),
id: id.to_string(),
source: err,
})?;
Ok(true)
}
fn try_upgrade_v1_1_31_config(id: &str) -> Result<bool, GatewayError> {
// explicitly load it as v1.1.31 (which is incompatible with the current, i.e. 1.1.32+)
let Ok(old_config) = ConfigV1_1_31::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the gateway is using <= v1.1.31 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_36 = old_config.into();
let updated: Config = updated_step1.into();
updated
.save_to_default_location()
@@ -110,14 +83,14 @@ fn try_upgrade_v1_1_31_config(id: &str) -> Result<bool, GatewayError> {
Ok(true)
}
fn try_upgrade_v1_1_36_config(id: &str) -> Result<bool, GatewayError> {
// explicitly load it as v1.1.36 (which is incompatible with the current, i.e. 1.1.37+)
let Ok(old_config) = ConfigV1_1_36::read_from_default_path(id) else {
fn try_upgrade_v1_1_31_config(id: &str) -> Result<bool, GatewayError> {
// explicitly load it as v1.1.30 (which is incompatible with the current, i.e. 1.1.31+)
let Ok(old_config) = ConfigV1_1_31::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the gateway is using <= v1.1.36 config template.");
info!("It seems the gateway is using <= v1.1.30 config template.");
info!("It is going to get updated to the current specification.");
let updated: Config = old_config.into();
@@ -145,9 +118,6 @@ pub(crate) fn try_upgrade_config(id: &str) -> Result<(), GatewayError> {
if try_upgrade_v1_1_31_config(id)? {
return Ok(());
}
if try_upgrade_v1_1_36_config(id)? {
return Ok(());
}
Ok(())
}
+45 -3
View File
@@ -11,7 +11,7 @@ use nym_config::{
must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate,
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT};
use nym_network_defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT, WG_PORT};
use serde::{Deserialize, Serialize};
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
@@ -20,13 +20,12 @@ use std::time::Duration;
use url::Url;
use zeroize::{Zeroize, ZeroizeOnDrop};
pub use crate::config::persistence::paths::GatewayPaths;
pub use crate::config::persistence::paths::{GatewayPaths, WireguardPaths};
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_28;
pub mod old_config_v1_1_29;
pub mod old_config_v1_1_31;
pub mod old_config_v1_1_36;
pub mod persistence;
mod template;
@@ -86,6 +85,10 @@ pub struct Config {
pub gateway: Gateway,
// currently not really used for anything useful
#[serde(default)]
pub wireguard: Wireguard,
pub storage_paths: GatewayPaths,
pub network_requester: NetworkRequester,
@@ -118,6 +121,7 @@ impl Config {
},
http: Default::default(),
gateway: default_gateway,
wireguard: Default::default(),
storage_paths: GatewayPaths::new_default(id.as_ref()),
network_requester: Default::default(),
ip_packet_router: Default::default(),
@@ -131,6 +135,7 @@ impl Config {
host: impl Into<Host>,
http: impl Into<Http>,
gateway: impl Into<Gateway>,
wireguard: impl Into<Wireguard>,
storage_paths: impl Into<GatewayPaths>,
network_requester: impl Into<NetworkRequester>,
ip_packet_router: impl Into<IpPacketRouter>,
@@ -142,6 +147,7 @@ impl Config {
host: host.into(),
http: http.into(),
gateway: gateway.into(),
wireguard: wireguard.into(),
storage_paths: storage_paths.into(),
network_requester: network_requester.into(),
ip_packet_router: ip_packet_router.into(),
@@ -256,6 +262,8 @@ impl Config {
let http_port = self.http.bind_address.port();
self.http.bind_address = SocketAddr::new(listening_address, http_port);
let wg_port = self.wireguard.bind_address.port();
self.wireguard.bind_address = SocketAddr::new(listening_address, wg_port);
self
}
@@ -339,6 +347,40 @@ impl Default for Http {
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Wireguard {
/// Specifies whether the wireguard service is enabled on this node.
pub enabled: bool,
/// Socket address this node will use for binding its wireguard interface.
/// default: `0.0.0.0:51822`
pub bind_address: SocketAddr,
/// Port announced to external clients wishing to connect to the wireguard interface.
/// Useful in the instances where the node is behind a proxy.
pub announced_port: u16,
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
/// The maximum value for IPv4 is 32 and for IPv6 is 128
pub private_network_prefix: u8,
/// Paths for wireguard keys, client registries, etc.
pub storage_paths: WireguardPaths,
}
impl Default for Wireguard {
fn default() -> Self {
Wireguard {
enabled: false,
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), WG_PORT),
announced_port: WG_PORT,
private_network_prefix: 16,
storage_paths: WireguardPaths {},
}
}
}
// we only really care about the mnemonic being zeroized
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Zeroize, ZeroizeOnDrop)]
pub struct Gateway {
+14 -14
View File
@@ -1,6 +1,8 @@
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::config::persistence::paths::{GatewayPaths, WireguardPaths};
use nym_bin_common::logging::LoggingSettings;
use nym_config::{
must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR,
};
@@ -12,11 +14,8 @@ use std::path::{Path, PathBuf};
use std::time::Duration;
use url::Url;
use super::old_config_v1_1_36::{
ConfigV1_1_36, DebugV1_1_36, GatewayPathsV1_1_36, GatewayV1_1_36, KeysPathsV1_1_36,
LoggingSettingsV1_1_36, NetworkRequesterV1_1_36, WireguardPathsV1_1_36, WireguardV1_1_36,
};
use super::{Host, Http};
use super::persistence::paths::KeysPaths;
use super::{Config, Debug, Gateway, Host, Http, NetworkRequester, Wireguard};
const DEFAULT_GATEWAYS_DIR: &str = "gateways";
@@ -106,13 +105,13 @@ impl ConfigV1_1_31 {
}
}
impl From<ConfigV1_1_31> for ConfigV1_1_36 {
impl From<ConfigV1_1_31> for Config {
fn from(value: ConfigV1_1_31) -> Self {
Self {
save_path: value.save_path,
host: value.host,
http: value.http,
gateway: GatewayV1_1_36 {
gateway: Gateway {
version: value.gateway.version,
id: value.gateway.id,
only_coconut_credentials: value.gateway.only_coconut_credentials,
@@ -126,17 +125,17 @@ impl From<ConfigV1_1_31> for ConfigV1_1_36 {
nyxd_urls: value.gateway.nyxd_urls,
cosmos_mnemonic: value.gateway.cosmos_mnemonic,
},
wireguard: WireguardV1_1_36 {
wireguard: Wireguard {
enabled: value.wireguard.enabled,
bind_address: value.wireguard.bind_address,
announced_port: value.wireguard.announced_port,
private_network_prefix: Default::default(),
storage_paths: WireguardPathsV1_1_36 {
storage_paths: WireguardPaths {
// no fields (yet)
},
},
storage_paths: GatewayPathsV1_1_36 {
keys: KeysPathsV1_1_36 {
storage_paths: GatewayPaths {
keys: KeysPaths {
private_identity_key_file: value.storage_paths.keys.private_identity_key_file,
public_identity_key_file: value.storage_paths.keys.public_identity_key_file,
private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file,
@@ -148,16 +147,16 @@ impl From<ConfigV1_1_31> for ConfigV1_1_36 {
ip_packet_router_config: Default::default(),
// /\ ADDED
},
network_requester: NetworkRequesterV1_1_36 {
network_requester: NetworkRequester {
enabled: value.network_requester.enabled,
},
// \/ ADDED
ip_packet_router: Default::default(),
// /\ ADDED
logging: LoggingSettingsV1_1_36 {
logging: LoggingSettings {
// no fields (yet)
},
debug: DebugV1_1_36 {
debug: Debug {
packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff,
packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff,
initial_connection_timeout: value.debug.initial_connection_timeout,
@@ -166,6 +165,7 @@ impl From<ConfigV1_1_31> for ConfigV1_1_36 {
stored_messages_filename_length: value.debug.stored_messages_filename_length,
message_retrieval_limit: value.debug.message_retrieval_limit,
use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version,
..Default::default()
},
}
}
-378
View File
@@ -1,378 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::config::persistence::paths::GatewayPaths;
use nym_bin_common::logging::LoggingSettings;
use nym_config::{
must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR,
};
use nym_network_defaults::WG_PORT;
use serde::{Deserialize, Deserializer, Serialize};
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::path::{Path, PathBuf};
use std::time::Duration;
use url::Url;
use super::persistence::paths::KeysPaths;
use super::{Config, Debug, Gateway, Host, Http, NetworkRequester};
const DEFAULT_GATEWAYS_DIR: &str = "gateways";
// 'DEBUG'
// where applicable, the below are defined in milliseconds
const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000);
const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000);
const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000);
const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500);
const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000;
const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16;
const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100;
fn de_maybe_port<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
where
D: Deserializer<'de>,
{
let port = u16::deserialize(deserializer)?;
if port == 0 {
Ok(None)
} else {
Ok(Some(port))
}
}
fn de_maybe_path<'de, D>(deserializer: D) -> Result<Option<PathBuf>, D::Error>
where
D: Deserializer<'de>,
{
let path = PathBuf::deserialize(deserializer)?;
if path.as_os_str().is_empty() {
Ok(None)
} else {
Ok(Some(path))
}
}
/// Derive default path to gateway's config directory.
/// It should get resolved to `$HOME/.nym/gateways/<id>/config`
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
must_get_home()
.join(NYM_DIR)
.join(DEFAULT_GATEWAYS_DIR)
.join(id)
.join(DEFAULT_CONFIG_DIR)
}
/// Derive default path to gateways's config file.
/// It should get resolved to `$HOME/.nym/gateways/<id>/config/config.toml`
pub fn default_config_filepath<P: AsRef<Path>>(id: P) -> PathBuf {
default_config_directory(id).join(DEFAULT_CONFIG_FILENAME)
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigV1_1_36 {
// additional metadata holding on-disk location of this config file
#[serde(skip)]
pub(crate) save_path: Option<PathBuf>,
pub host: Host,
#[serde(default)]
pub http: Http,
pub gateway: GatewayV1_1_36,
#[serde(default)]
// currently not really used for anything useful
pub wireguard: WireguardV1_1_36,
pub storage_paths: GatewayPathsV1_1_36,
pub network_requester: NetworkRequesterV1_1_36,
#[serde(default)]
pub ip_packet_router: IpPacketRouterV1_1_36,
#[serde(default)]
pub logging: LoggingSettingsV1_1_36,
#[serde(default)]
pub debug: DebugV1_1_36,
}
impl ConfigV1_1_36 {
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
read_config_from_toml_file(default_config_filepath(id))
}
}
impl From<ConfigV1_1_36> for Config {
fn from(value: ConfigV1_1_36) -> Self {
Self {
save_path: value.save_path,
host: value.host,
http: value.http,
gateway: Gateway {
version: value.gateway.version,
id: value.gateway.id,
only_coconut_credentials: value.gateway.only_coconut_credentials,
listening_address: value.gateway.listening_address,
mix_port: value.gateway.mix_port,
clients_port: value.gateway.clients_port,
clients_wss_port: value.gateway.clients_wss_port,
enabled_statistics: value.gateway.enabled_statistics,
statistics_service_url: value.gateway.statistics_service_url,
nym_api_urls: value.gateway.nym_api_urls,
nyxd_urls: value.gateway.nyxd_urls,
cosmos_mnemonic: value.gateway.cosmos_mnemonic,
},
storage_paths: GatewayPaths {
keys: KeysPaths {
private_identity_key_file: value.storage_paths.keys.private_identity_key_file,
public_identity_key_file: value.storage_paths.keys.public_identity_key_file,
private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file,
public_sphinx_key_file: value.storage_paths.keys.public_sphinx_key_file,
},
clients_storage: value.storage_paths.clients_storage,
network_requester_config: value.storage_paths.network_requester_config,
// \/ ADDED
ip_packet_router_config: Default::default(),
// /\ ADDED
},
network_requester: NetworkRequester {
enabled: value.network_requester.enabled,
},
// \/ ADDED
ip_packet_router: Default::default(),
// /\ ADDED
logging: LoggingSettings {
// no fields (yet)
},
debug: Debug {
packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff,
packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff,
initial_connection_timeout: value.debug.initial_connection_timeout,
maximum_connection_buffer_size: value.debug.maximum_connection_buffer_size,
presence_sending_delay: value.debug.presence_sending_delay,
stored_messages_filename_length: value.debug.stored_messages_filename_length,
message_retrieval_limit: value.debug.message_retrieval_limit,
use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version,
..Default::default()
},
}
}
}
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct GatewayV1_1_36 {
/// Version of the gateway for which this configuration was created.
pub version: String,
/// ID specifies the human readable ID of this particular gateway.
pub id: String,
/// Indicates whether this gateway is accepting only coconut credentials for accessing the
/// the mixnet, or if it also accepts non-paying clients
#[serde(default)]
pub only_coconut_credentials: bool,
/// Address to which this mixnode will bind to and will be listening for packets.
pub listening_address: IpAddr,
/// Port used for listening for all mixnet traffic.
/// (default: 1789)
pub mix_port: u16,
/// Port used for listening for all client-related traffic.
/// (default: 9000)
pub clients_port: u16,
/// If applicable, announced port for listening for secure websocket client traffic.
/// (default: None)
#[serde(deserialize_with = "de_maybe_port")]
pub clients_wss_port: Option<u16>,
/// Whether gateway collects and sends anonymized statistics
pub enabled_statistics: bool,
/// Domain address of the statistics service
pub statistics_service_url: Url,
/// Addresses to APIs from which the node gets the view of the network.
#[serde(alias = "validator_api_urls")]
pub nym_api_urls: Vec<Url>,
/// Addresses to validators which the node uses to check for double spending of ERC20 tokens.
#[serde(alias = "validator_nymd_urls")]
pub nyxd_urls: Vec<Url>,
/// Mnemonic of a cosmos wallet used in checking for double spending.
// #[deprecated(note = "move to storage")]
// TODO: I don't think this should be stored directly in the config...
pub cosmos_mnemonic: bip39::Mnemonic,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(default)]
#[serde(deny_unknown_fields)]
pub struct WireguardV1_1_36 {
/// Specifies whether the wireguard service is enabled on this node.
pub enabled: bool,
/// Socket address this node will use for binding its wireguard interface.
/// default: `0.0.0.0:51820`
pub bind_address: SocketAddr,
/// Port announced to external clients wishing to connect to the wireguard interface.
/// Useful in the instances where the node is behind a proxy.
pub announced_port: u16,
/// The prefix denoting the maximum number of the clients that can be connected via Wireguard.
/// The maximum value for IPv4 is 32 and for IPv6 is 128
pub private_network_prefix: u8,
/// Paths for wireguard keys, client registries, etc.
pub storage_paths: WireguardPathsV1_1_36,
}
impl Default for WireguardV1_1_36 {
fn default() -> Self {
Self {
enabled: false,
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), WG_PORT),
announced_port: WG_PORT,
storage_paths: WireguardPathsV1_1_36 {},
private_network_prefix: 16,
}
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct WireguardPathsV1_1_36 {
// pub keys:
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GatewayPathsV1_1_36 {
pub keys: KeysPathsV1_1_36,
/// Path to sqlite database containing all persistent data: messages for offline clients,
/// derived shared keys and available client bandwidths.
#[serde(alias = "persistent_storage")]
pub clients_storage: PathBuf,
/// Path to the configuration of the embedded network requester.
#[serde(deserialize_with = "de_maybe_path")]
pub network_requester_config: Option<PathBuf>,
// pub node_description: PathBuf,
// pub cosmos_bip39_mnemonic: PathBuf,
/// Path to the configuration of the embedded ip packet router.
#[serde(deserialize_with = "de_maybe_path")]
pub ip_packet_router_config: Option<PathBuf>,
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
pub struct KeysPathsV1_1_36 {
/// Path to file containing private identity key.
pub private_identity_key_file: PathBuf,
/// Path to file containing public identity key.
pub public_identity_key_file: PathBuf,
/// Path to file containing private sphinx key.
pub private_sphinx_key_file: PathBuf,
/// Path to file containing public sphinx key.
pub public_sphinx_key_file: PathBuf,
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct NetworkRequesterV1_1_36 {
/// Specifies whether network requester service is enabled in this process.
pub enabled: bool,
}
#[allow(clippy::derivable_impls)]
impl Default for NetworkRequesterV1_1_36 {
fn default() -> Self {
Self { enabled: false }
}
}
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoggingSettingsV1_1_36 {
// well, we need to implement something here at some point...
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct DebugV1_1_36 {
/// Initial value of an exponential backoff to reconnect to dropped TCP connection when
/// forwarding sphinx packets.
#[serde(with = "humantime_serde")]
pub packet_forwarding_initial_backoff: Duration,
/// Maximum value of an exponential backoff to reconnect to dropped TCP connection when
/// forwarding sphinx packets.
#[serde(with = "humantime_serde")]
pub packet_forwarding_maximum_backoff: Duration,
/// Timeout for establishing initial connection when trying to forward a sphinx packet.
#[serde(with = "humantime_serde")]
pub initial_connection_timeout: Duration,
/// Maximum number of packets that can be stored waiting to get sent to a particular connection.
pub maximum_connection_buffer_size: usize,
/// Delay between each subsequent presence data being sent.
#[serde(with = "humantime_serde")]
pub presence_sending_delay: Duration,
/// Length of filenames for new client messages.
pub stored_messages_filename_length: u16,
/// Number of messages from offline client that can be pulled at once from the storage.
pub message_retrieval_limit: i64,
/// Specifies whether the mixnode should be using the legacy framing for the sphinx packets.
// it's set to true by default. The reason for that decision is to preserve compatibility with the
// existing nodes whilst everyone else is upgrading and getting the code for handling the new field.
// It shall be disabled in the subsequent releases.
pub use_legacy_framed_packet_version: bool,
}
impl Default for DebugV1_1_36 {
fn default() -> Self {
Self {
packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF,
packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF,
initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT,
presence_sending_delay: DEFAULT_PRESENCE_SENDING_DELAY,
maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE,
stored_messages_filename_length: DEFAULT_STORED_MESSAGE_FILENAME_LENGTH,
message_retrieval_limit: DEFAULT_MESSAGE_RETRIEVAL_LIMIT,
use_legacy_framed_packet_version: false,
}
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct IpPacketRouterV1_1_36 {
/// Specifies whether ip packet router service is enabled in this process.
pub enabled: bool,
}
#[allow(clippy::derivable_impls)]
impl Default for IpPacketRouterV1_1_36 {
fn default() -> Self {
Self { enabled: false }
}
}
+12
View File
@@ -169,3 +169,15 @@ impl KeysPaths {
&self.public_sphinx_key_file
}
}
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct WireguardPaths {
// pub keys:
}
impl WireguardPaths {
pub fn new_empty() -> Self {
WireguardPaths {}
}
}
+9 -21
View File
@@ -38,6 +38,7 @@ pub enum GatewayError {
ConfigLoadFailure {
id: String,
path: PathBuf,
#[source]
source: io::Error,
},
@@ -47,6 +48,7 @@ pub enum GatewayError {
NetworkRequesterConfigLoadFailure {
id: String,
path: PathBuf,
#[source]
source: io::Error,
},
@@ -57,16 +59,7 @@ pub enum GatewayError {
IpPacketRouterConfigLoadFailure {
id: String,
path: PathBuf,
source: io::Error,
},
#[error(
"failed to load config file for wireguard (gateway-id: '{id}') using path '{}'. detailed message: {source}",
path.display()
)]
WireguardConfigLoadFailure {
id: String,
path: PathBuf,
#[source]
source: io::Error,
},
@@ -76,6 +69,7 @@ pub enum GatewayError {
ConfigSaveFailure {
id: String,
path: PathBuf,
#[source]
source: io::Error,
},
@@ -86,7 +80,10 @@ pub enum GatewayError {
},
#[error("could not obtain the information about current gateways on the network: {source}")]
NetworkGatewaysQueryFailure { source: ValidatorClientError },
NetworkGatewaysQueryFailure {
#[source]
source: ValidatorClientError,
},
#[error("address {account} has an invalid bech32 prefix. it uses '{actual_prefix}' while '{expected_prefix}' was expected")]
InvalidBech32AccountPrefix {
@@ -148,6 +145,7 @@ pub enum GatewayError {
#[error("failed to catch an interrupt: {source}")]
ShutdownFailure {
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
@@ -169,16 +167,6 @@ pub enum GatewayError {
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[error("failed to remove wireguard interface: {0}")]
WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError),
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[error("wireguard not set")]
WireguardNotSet,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
#[error("failed to catch an interrupt: {source}")]
StdError {
source: Box<dyn std::error::Error + Send + Sync>,
},
}
impl From<ClientCoreError> for GatewayError {
+41 -2
View File
@@ -4,6 +4,7 @@
use crate::config::Config;
use crate::error::GatewayError;
use crate::helpers::load_public_key;
use ipnetwork::IpNetwork;
use log::{debug, error, warn};
use nym_bin_common::bin_info_owned;
use nym_crypto::asymmetric::{encryption, identity};
@@ -11,18 +12,30 @@ use nym_network_requester::RequestFilter;
use nym_node_http_api::api::api_requests;
use nym_node_http_api::api::api_requests::v1::network_requester::exit_policy::models::UsedExitPolicy;
use nym_node_http_api::api::api_requests::SignedHostInformation;
use nym_node_http_api::router::WireguardAppState;
use nym_node_http_api::NymNodeHttpError;
use nym_sphinx::addressing::clients::Recipient;
use nym_task::TaskClient;
use nym_wireguard_types::registration::GatewayClientRegistry;
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
fn load_gateway_details(
config: &Config,
) -> Result<api_requests::v1::gateway::models::Gateway, GatewayError> {
let wireguard = if config.wireguard.enabled {
Some(api_requests::v1::gateway::models::Wireguard {
port: config.wireguard.announced_port,
public_key: "placeholder key value".to_string(),
})
} else {
None
};
Ok(api_requests::v1::gateway::models::Gateway {
enforces_zk_nyms: config.gateway.only_coconut_credentials,
client_interfaces: api_requests::v1::gateway::models::ClientInterfaces {
wireguard: None,
wireguard,
mixnet_websockets: Some(api_requests::v1::gateway::models::WebSockets {
ws_port: config.gateway.clients_port,
wss_port: config.gateway.clients_wss_port,
@@ -140,6 +153,8 @@ pub(crate) struct HttpApiBuilder<'a> {
identity_keypair: &'a identity::KeyPair,
// TODO: this should be a wg specific key and not re-used sphinx
sphinx_keypair: Arc<encryption::KeyPair>,
client_registry: Option<Arc<GatewayClientRegistry>>,
}
impl<'a> HttpApiBuilder<'a> {
@@ -155,6 +170,7 @@ impl<'a> HttpApiBuilder<'a> {
exit_policy: None,
identity_keypair,
sphinx_keypair,
client_registry: None,
}
}
@@ -218,6 +234,15 @@ impl<'a> HttpApiBuilder<'a> {
self
}
#[must_use]
pub(crate) fn with_wireguard_client_registry(
mut self,
client_registry: Arc<GatewayClientRegistry>,
) -> Self {
self.client_registry = Some(client_registry);
self
}
pub(crate) fn start(self, task_client: TaskClient) -> Result<(), GatewayError> {
debug!("starting http API");
@@ -256,8 +281,22 @@ impl<'a> HttpApiBuilder<'a> {
)?);
}
let wireguard_private_network = IpNetwork::new(
IpAddr::from(Ipv4Addr::new(10, 1, 0, 0)),
self.gateway_config.wireguard.private_network_prefix,
)?;
let wg_state = self.client_registry.and_then(|client_registry| {
WireguardAppState::new(
client_registry,
Default::default(),
self.gateway_config.wireguard.bind_address.port(),
wireguard_private_network,
)
.ok()
});
let bind_address = self.gateway_config.http.bind_address;
let router = nym_node_http_api::NymNodeRouter::new(config, None, None);
let router = nym_node_http_api::NymNodeRouter::new(config, None, wg_state);
tokio::spawn(async move {
let server = match router.build_server(&bind_address).await {
+20 -27
View File
@@ -16,6 +16,7 @@ use crate::node::client_handling::websocket::connection_handler::coconut::Coconu
use crate::node::helpers::{initialise_main_storage, load_network_requester_config};
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
use crate::node::statistics::collector::GatewayStatisticsCollector;
use dashmap::DashMap;
use futures::channel::{mpsc, oneshot};
use log::*;
use nym_crypto::asymmetric::{encryption, identity};
@@ -27,6 +28,7 @@ use nym_task::{TaskClient, TaskHandle, TaskManager};
use nym_types::gateway::GatewayNodeDetailsResponse;
use nym_validator_client::nyxd::{Coin, CosmWasmClient};
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
use nym_wireguard_types::registration::GatewayClientRegistry;
use rand::seq::SliceRandom;
use rand::thread_rng;
use std::net::SocketAddr;
@@ -124,11 +126,9 @@ pub struct Gateway<St = PersistentStorage> {
/// x25519 keypair used for Diffie-Hellman. Currently only used for sphinx key derivation.
sphinx_keypair: Arc<encryption::KeyPair>,
storage: St,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: Option<nym_wireguard::WireguardData>,
client_registry: Arc<GatewayClientRegistry>,
run_http_server: bool,
task_client: Option<TaskClient>,
@@ -149,8 +149,7 @@ impl<St> Gateway<St> {
config,
network_requester_opts,
ip_packet_router_opts,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: None,
client_registry: Arc::new(DashMap::new()),
run_http_server: true,
task_client: None,
})
@@ -171,8 +170,7 @@ impl<St> Gateway<St> {
identity_keypair,
sphinx_keypair,
storage,
#[cfg(all(feature = "wireguard", target_os = "linux"))]
wireguard_data: None,
client_registry: Arc::new(DashMap::new()),
run_http_server: true,
task_client: None,
}
@@ -186,9 +184,12 @@ impl<St> Gateway<St> {
self.task_client = Some(task_client)
}
#[cfg(all(feature = "wireguard", target_os = "linux"))]
pub fn set_wireguard_data(&mut self, wireguard_data: nym_wireguard::WireguardData) {
self.wireguard_data = Some(wireguard_data)
pub fn set_wireguard_client_registry(&mut self, client_registry: Arc<GatewayClientRegistry>) {
// sanity check:
if Arc::strong_count(&self.client_registry) != 1 {
panic!("the client registry is already being used elsewhere")
}
self.client_registry = client_registry
}
pub async fn node_details(&self) -> Result<GatewayNodeDetailsResponse, GatewayError> {
@@ -226,14 +227,10 @@ impl<St> Gateway<St> {
#[cfg(all(feature = "wireguard", target_os = "linux"))]
async fn start_wireguard(
&mut self,
&self,
shutdown: TaskClient,
) -> Result<Arc<nym_wireguard::WgApiWrapper>, Box<dyn std::error::Error + Send + Sync>> {
if let Some(wireguard_data) = self.wireguard_data.take() {
nym_wireguard::start_wireguard(shutdown, wireguard_data).await
} else {
Err(Box::new(GatewayError::WireguardNotSet))
}
) -> Result<defguard_wireguard_rs::WGApi, Box<dyn std::error::Error + Send + Sync>> {
nym_wireguard::start_wireguard(shutdown, Arc::clone(&self.client_registry)).await
}
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
@@ -558,6 +555,7 @@ impl<St> Gateway<St> {
self.identity_keypair.as_ref(),
self.sphinx_keypair.clone(),
)
.with_wireguard_client_registry(self.client_registry.clone())
.with_maybe_network_requester(self.network_requester_opts.as_ref().map(|o| &o.config))
.with_maybe_network_request_filter(nr_request_filter)
.with_maybe_ip_packet_router(self.ip_packet_router_opts.as_ref().map(|o| &o.config))
@@ -567,26 +565,21 @@ impl<St> Gateway<St> {
// Once this is a bit more mature, make this a commandline flag instead of a compile time
// flag
#[cfg(all(feature = "wireguard", target_os = "linux"))]
let _wg_api = self
.start_wireguard(shutdown.fork("wireguard"))
.await
.map_err(|source| GatewayError::StdError { source })?;
let wg_api = self.start_wireguard(shutdown.fork("wireguard")).await.ok();
#[cfg(all(feature = "wireguard", not(target_os = "linux")))]
self.start_wireguard(shutdown.fork("wireguard")).await;
info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!");
info!(
"Public key: {:?}",
self.identity_keypair.public_key().to_string()
);
if let Err(source) = shutdown.wait_for_shutdown().await {
// that's a nasty workaround, but anyhow errors are generally nicer, especially on exit
return Err(GatewayError::ShutdownFailure { source });
}
#[cfg(all(feature = "wireguard", target_os = "linux"))]
if let Some(wg_api) = wg_api {
defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&wg_api)?;
}
Ok(())
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ futures = { workspace = true }
humantime-serde = { workspace = true }
lazy_static = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
rand = "0.7.3"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sysinfo = "0.27.7"
+4 -2
View File
@@ -4,7 +4,7 @@
[package]
name = "nym-api"
license = "GPL-3.0"
version = "1.1.38"
version = "1.1.37"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"Jędrzej Stuczyński <andrew@nymtech.net>",
@@ -29,7 +29,8 @@ humantime-serde = { workspace = true }
k256 = { workspace = true, features = ["ecdsa-core"] } # needed for the Verifier trait; pull whatever version is used by other dependencies
log = { workspace = true }
pin-project = { workspace = true }
rand = { workspace = true }
rand = "0.8.5"
rand-07 = { package = "rand", version = "0.7.3" } # required for compatibility
reqwest = { workspace = true, features = ["json"] }
rocket = { workspace = true, features = ["json"] }
rocket_cors = { workspace = true }
@@ -119,5 +120,6 @@ tempfile = { workspace = true }
cw3 = { workspace = true }
cw-utils = { workspace = true }
rand_chacha = "0.3"
rand_chacha_02 = { package = "rand_chacha", version = "0.2" }
sha2 = "0.9"
-4
View File
@@ -27,10 +27,6 @@ nym-crypto = { path = "../../common/crypto", features = ["serde", "asymmetric"]
nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false }
[dev-dependencies]
serde_json.workspace = true
[features]
default = []
generate-ts = ["ts-rs", "nym-mixnet-contract-common/generate-ts"]
+7 -132
View File
@@ -420,110 +420,15 @@ where
Ok(time::serde::rfc3339::deserialize(deserializer).unwrap_or_else(|_| unix_epoch()))
}
pub(crate) mod overengineered_offset_date_time_serde {
use crate::models::unix_epoch;
use serde::de::Visitor;
use serde::ser::Error;
use serde::{Deserializer, Serialize, Serializer};
use std::fmt::Formatter;
use time::format_description::well_known::Rfc3339;
use time::format_description::{modifier, BorrowedFormatItem, Component};
use time::OffsetDateTime;
struct OffsetDateTimeVisitor;
// copied from time library because they keep it private -.-
const DEFAULT_OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Compound(DATE_FORMAT),
BorrowedFormatItem::Literal(b" "),
BorrowedFormatItem::Compound(TIME_FORMAT),
BorrowedFormatItem::Literal(b" "),
BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
];
const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
BorrowedFormatItem::Literal(b"-"),
BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
BorrowedFormatItem::Literal(b"-"),
BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
];
const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
BorrowedFormatItem::Literal(b"."),
BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
];
const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
BorrowedFormatItem::Component(Component::OffsetHour({
let mut m = modifier::OffsetHour::default();
m.sign_is_mandatory = true;
m
})),
BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::OffsetMinute(
modifier::OffsetMinute::default(),
)),
BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
BorrowedFormatItem::Literal(b":"),
BorrowedFormatItem::Component(Component::OffsetSecond(
modifier::OffsetSecond::default(),
)),
])),
])),
];
impl<'de> Visitor<'de> for OffsetDateTimeVisitor {
type Value = OffsetDateTime;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("an rfc3339 or human-readable `OffsetDateTime`")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
// first try rfc3339, if that fails use default human-readable impl from time,
// finally fallback to default unix epoch
Ok(OffsetDateTime::parse(v, &Rfc3339).unwrap_or_else(|_| {
OffsetDateTime::parse(v, &DEFAULT_OFFSET_DATE_TIME_FORMAT)
.unwrap_or_else(|_| unix_epoch())
}))
}
}
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(OffsetDateTimeVisitor)
}
pub(crate) fn serialize<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// serialize it with human-readable format for compatibility with eclipse and nutella clients
// in the future change it back to rfc3339
datetime
.format(&DEFAULT_OFFSET_DATE_TIME_FORMAT)
.map_err(S::Error::custom)?
.serialize(serializer)
}
}
// for all intents and purposes it's just OffsetDateTime, but we need JsonSchema...
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct OffsetDateTimeJsonSchemaWrapper(
#[serde(default = "unix_epoch", with = "overengineered_offset_date_time_serde")]
pub OffsetDateTime,
#[serde(
default = "unix_epoch",
serialize_with = "time::serde::rfc3339::serialize",
deserialize_with = "de_rfc3339_or_default"
)]
pub OffsetDateTime,
);
impl Default for OffsetDateTimeJsonSchemaWrapper {
@@ -694,33 +599,3 @@ pub struct PartialTestResult {
pub type MixnodeTestResultResponse = PaginatedResponse<PartialTestResult>;
pub type GatewayTestResultResponse = PaginatedResponse<PartialTestResult>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn offset_date_time_json_schema_wrapper_serde_backwards_compat() {
let mut dummy = OffsetDateTimeJsonSchemaWrapper::default();
dummy.0 += Duration::from_millis(1);
let ser = serde_json::to_string(&dummy).unwrap();
assert_eq!("\"1970-01-01 00:00:00.001 +00:00:00\"", ser);
let human_readable = "\"2024-05-23 07:41:02.756283766 +00:00:00\"";
let rfc3339 = "\"2002-10-02T15:00:00Z\"";
let rfc3339_offset = "\"2002-10-02T10:00:00-05:00\"";
let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(human_readable).unwrap();
assert_eq!(de.0.unix_timestamp(), 1716450062);
let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(rfc3339).unwrap();
assert_eq!(de.0.unix_timestamp(), 1033570800);
let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>(rfc3339_offset).unwrap();
assert_eq!(de.0.unix_timestamp(), 1033570800);
let de = serde_json::from_str::<OffsetDateTimeJsonSchemaWrapper>("\"nonsense\"").unwrap();
assert_eq!(de.0.unix_timestamp(), 0);
}
}
+12 -2
View File
@@ -27,6 +27,11 @@ pub fn test_rng(seed: [u8; 32]) -> ChaCha20Rng {
ChaCha20Rng::from_seed(seed)
}
pub fn test_rng_07(seed: [u8; 32]) -> rand_chacha_02::ChaCha20Rng {
use rand_chacha_02::rand_core::SeedableRng;
rand_chacha_02::ChaCha20Rng::from_seed(seed)
}
pub fn pseudorandom_account(rng: &mut ChaCha20Rng) -> AccountId {
let mut dummy_account_key_hash = [0u8; 32];
rng.fill_bytes(&mut dummy_account_key_hash);
@@ -37,8 +42,13 @@ pub fn dealer_fixture(mut rng: &mut ChaCha20Rng, id: NodeIndex) -> DealerDetails
// we might possibly need that private key later on
let keypair = DkgKeyPair::new(dkg::params(), &mut rng);
// lol, instantiate rng with an rng due to incompatibility, but even though it looks dodgy AF,
// it's 100% deterministic
let mut secondary_seed = [0u8; 32];
rng.fill_bytes(&mut secondary_seed);
let addr = pseudorandom_account(rng);
let identity_keypair = identity::KeyPair::new(&mut rng);
let identity_keypair = identity::KeyPair::new(&mut test_rng_07(secondary_seed));
let bte_public_key_with_proof = bs58::encode(&keypair.public_key().to_bytes()).into_string();
let port = 8080 + id;
@@ -146,7 +156,7 @@ impl TestingDkgControllerBuilder {
let mut secondary_seed = [0u8; 32];
rng.fill_bytes(&mut secondary_seed);
let identity_keypair = identity::KeyPair::new(&mut test_rng(secondary_seed));
let identity_keypair = identity::KeyPair::new(&mut test_rng_07(secondary_seed));
DealerDetails {
address: Addr::unchecked(address.as_ref()),
+3 -3
View File
@@ -49,8 +49,8 @@ use nym_validator_client::nyxd::Coin;
use nym_validator_client::nyxd::{
AccountId, Algorithm, Event, EventAttribute, ExecTxResult, Fee, Hash, TxResponse,
};
use rand::rngs::OsRng;
use rand::RngCore;
use rand_07::rngs::OsRng;
use rand_07::RngCore;
use rocket::http::Status;
use rocket::local::asynchronous::Client;
use std::collections::{BTreeMap, HashMap};
@@ -1336,7 +1336,7 @@ struct TestFixture {
impl TestFixture {
async fn new() -> Self {
let mut rng = crate::coconut::tests::fixtures::test_rng([69u8; 32]);
let mut rng = crate::coconut::tests::fixtures::test_rng_07([69u8; 32]);
let params = Parameters::new(4).unwrap();
let coconut_keypair = nym_coconut::ttp_keygen(&params, 1, 1).unwrap().remove(0);
let identity = identity::KeyPair::new(&mut rng);
+1 -1
View File
@@ -8,7 +8,7 @@ use nym_sphinx::{
acknowledgements::AckKey, addressing::clients::Recipient, preparer::MessagePreparer,
};
use nym_topology::NymTopology;
use rand::rngs::OsRng;
use rand_07::rngs::OsRng;
use std::time::Duration;
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(200);
+1 -1
View File
@@ -73,7 +73,7 @@ impl<'a> NetworkMonitorBuilder<'a> {
// TODO: those keys change constant throughout the whole execution of the monitor.
// and on top of that, they are used with ALL the gateways -> presumably this should change
// in the future
let mut rng = rand::rngs::OsRng;
let mut rng = rand_07::rngs::OsRng;
let identity_keypair = Arc::new(identity::KeyPair::new(&mut rng));
let encryption_keypair = Arc::new(encryption::KeyPair::new(&mut rng));
@@ -14,7 +14,7 @@ use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::params::{PacketSize, PacketType};
use nym_topology::{gateway, mix};
use rand::{rngs::ThreadRng, seq::SliceRandom, thread_rng, Rng};
use rand_07::{rngs::ThreadRng, seq::SliceRandom, thread_rng, Rng};
use std::collections::{HashMap, HashSet};
use std::fmt::{self, Display, Formatter};
+2 -1
View File
@@ -9,6 +9,7 @@ use crate::support::config::{
use anyhow::{Context, Result};
use nym_crypto::asymmetric::identity;
use rand::rngs::OsRng;
use rand_07::rngs::OsRng as OsRng07;
use std::{fs, io};
// TODO: once we upgrade ed25519 library, we could use the same rand library and use proper
@@ -19,7 +20,7 @@ fn init_identity_keys(config: &config::NymApiPaths) -> Result<()> {
&config.public_identity_key_file,
);
let mut rng = OsRng;
let mut rng = OsRng07;
let keypair = identity::KeyPair::new(&mut rng);
nym_pemstore::store_keypair(&keypair, &keypaths)
.context("failed to store identity keys of the nym api")?;
+8
View File
@@ -0,0 +1,8 @@
{
"extends": [
"@nymproject/eslint-config-react-typescript"
],
"parserOptions": {
"project": "./tsconfig.eslint.json"
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2
}
+7
View File
@@ -0,0 +1,7 @@
RPC_URL=
VALIDATOR_URL=
PREFIX=
MIXNET_CONTRACT_ADDRESS=
VESTING_CONTRACT_ADDRESS=
DENOM=
BLOCK_EXPLORER_URL=
View File
+40
View File
@@ -0,0 +1,40 @@
# Nym Browser Extension
The Nym browser extension lets you access your Nym wallet via the browser.
## Getting started
You will need:
- NodeJS (use `nvm install` to automatically install the correct version)
- `npm`
- `yarn`
> **Note**: This project is part of a mono repo, so you will need to build the shared packages before starting. And any time they change, you'll need to rebuild them.
From the [root of the repository](../README.md) run the following to build shared packages:
```
yarn
yarn build
```
From the `nym-browser-extension` directory of the `nym` monorepo, run:
`yarn dev` to run the extension in dev mode.
You can then open a browser to http://localhost:9000 and start development.
OR
`yarn build` to build the extension.
The extension will build to the `nym-browser-extension/dist` directory.
## Load extension
To load the extension into a Chrome browser
- Go to `settings > extensions > manage extensions`
- Select `Load unpacked`
- Select the `nym-browser-extension/dist`
+86
View File
@@ -0,0 +1,86 @@
{
"name": "@nym/browser-extension",
"version": "0.1.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "yarn webpack serve --config webpack.dev.js",
"build": "yarn preinstall && webpack build --progress --config webpack.prod.js",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"lint:ts": "tsc --noEmit",
"storybook": "start-storybook -p 6006",
"storybook:build": "build-storybook"
},
"dependencies": {
"@emotion/react": "^11.7.0",
"@emotion/styled": "^11.7.0",
"@hookform/resolvers": "^3.1.0",
"@mui/icons-material": "^5.11.11",
"@mui/material": "^5.11.15",
"@mui/system": "^5.11.15",
"@nymproject/mui-theme": "^1.0.0",
"@nymproject/nym-validator-client": ">=1.2.0-rc.0 || 1",
"@nymproject/react": "^1.0.0",
"@nymproject/types": "^1.0.0",
"@nymproject/extension-storage": ">=1.2.0-rc.0 || 1",
"@storybook/react": "^6.5.16",
"big.js": "^6.2.1",
"crypto-js": "^4.1.1",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.3",
"react-hook-form": "^7.43.9",
"react-router-dom": "^6.9.0",
"zod": "^3.21.4"
},
"devDependencies": {
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
"@svgr/webpack": "^6.1.1",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^14.0.0",
"@types/big.js": "^6.1.6",
"@types/crypto-js": "4.1.1",
"@types/jest": "^27.0.1",
"@types/node": "^18.16.1",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"copy-webpack-plugin": "^11.0.0",
"dotenv-webpack": "^8.0.1",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-storybook": "^0.5.12",
"favicons-webpack-plugin": "^5.0.2",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"prettier": "^2.8.7",
"react-refresh": "^0.14.0",
"react-refresh-typescript": "^2.0.8",
"style-loader": "^3.3.1",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.2",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"util": "^0.12.5",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.5.0",
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0"
}
}
+15
View File
@@ -0,0 +1,15 @@
import React from 'react';
import { NymBrowserExtThemeWithMode } from './theme/NymBrowserExtensionTheme';
import { AppRoutes } from './routes';
import { AppLayout } from './layouts/AppLayout';
import { AppProvider } from './context';
export const App = () => (
<NymBrowserExtThemeWithMode mode="light">
<AppProvider>
<AppLayout>
<AppRoutes />
</AppLayout>
</AppProvider>
</NymBrowserExtThemeWithMode>
);
@@ -0,0 +1,47 @@
import React from 'react';
import { Avatar, ListItem, ListItemAvatar, ListItemButton, ListItemText } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { useAppContext } from 'src/context';
import { AccountActions } from './Actions';
const AccountItem = ({
accountName,
disabled,
onSelect,
}: {
accountName: string;
disabled: boolean;
onSelect: () => void;
}) => (
<ListItem disableGutters disablePadding secondaryAction={<AccountActions accountName={accountName} />} divider>
<ListItemButton onClick={onSelect} disabled={disabled}>
<ListItemAvatar>
<Avatar>{accountName[0]}</Avatar>
</ListItemAvatar>
<ListItemText primary={accountName} secondary={disabled && '(Selected)'} />
</ListItemButton>
</ListItem>
);
export const AccountList = () => {
const navigate = useNavigate();
const { accounts, selectAccount, selectedAccount } = useAppContext();
const handleSelectAccount = async (accountName: string) => {
await selectAccount(accountName);
navigate('/user/balance');
};
return (
<>
{accounts.map((accountName) => (
<AccountItem
disabled={selectedAccount === accountName}
accountName={accountName}
key={accountName}
onSelect={() => handleSelectAccount(accountName)}
/>
))}
</>
);
};
@@ -0,0 +1,55 @@
import React from 'react';
import { IconButton, ListItemIcon, ListItemText, Menu, MenuItem } from '@mui/material';
import { MoreVert, VisibilityOutlined } from '@mui/icons-material';
import { useAppContext } from 'src/context';
type ActionType = {
title: string;
Icon: React.ReactNode;
onSelect: () => void;
};
const ActionItem = ({ action }: { action: ActionType }) => (
<MenuItem dense onClick={action.onSelect}>
<ListItemIcon>{action.Icon}</ListItemIcon>
<ListItemText>{action.title}</ListItemText>
</MenuItem>
);
export const AccountActions = ({ accountName }: { accountName: string }) => {
const { setShowSeedForAccount } = useAppContext();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const actions: Array<ActionType> = [
{
title: 'View seed phrase',
Icon: <VisibilityOutlined />,
onSelect: () => {
setShowSeedForAccount(accountName);
},
},
];
return (
<>
<IconButton onClick={handleClick}>
<MoreVert />
</IconButton>
<Menu anchorEl={anchorEl} id="account-menu" open={open} onClose={handleClose} onClick={handleClose}>
{actions.map((action) => (
<ActionItem action={action} key={action.title} />
))}
</Menu>
</>
);
};
@@ -0,0 +1,68 @@
import React, { useState } from 'react';
import { Box, Card, CardContent, Typography } from '@mui/material';
import { PasswordInput } from '@nymproject/react/textfields/Password';
import { ExtensionStorage } from '@nymproject/extension-storage';
import { Button, ConfirmationModal } from 'src/components/ui';
const ShowSeedButton = ({ handleShowSeedPhrase }: { handleShowSeedPhrase: () => void }) => (
<Button fullWidth variant="contained" onClick={handleShowSeedPhrase}>
Show seed phrase
</Button>
);
const DoneButton = ({ onDone }: { onDone: () => void }) => (
<Button fullWidth variant="contained" onClick={onDone}>
Done
</Button>
);
const Seed = ({ seed }: { seed: string }) => (
<Card>
<CardContent>
<Typography>{seed}</Typography>
</CardContent>
</Card>
);
export const ViewSeedPhrase = ({ accountName, onDone }: { accountName: string; onDone: () => void }) => {
const [seed, setSeed] = useState<string>();
const [password, setPassword] = useState('');
const [error, setError] = useState<string>();
const handleShowSeedPhrase = async () => {
try {
const storage = await new ExtensionStorage(password);
const accountSeed = await storage.read_mnemonic(accountName);
setSeed(accountSeed);
} catch (e) {
setError('Could not retrieve seed phrase. Please check your password');
}
};
return (
<ConfirmationModal
open
onClose={onDone}
title={seed ? 'Account seed phrase' : 'Password'}
subtitle={seed ? '' : 'Enter your account password'}
ConfirmButton={
seed ? <DoneButton onDone={onDone} /> : <ShowSeedButton handleShowSeedPhrase={handleShowSeedPhrase} />
}
>
{seed ? (
<Seed seed={seed} />
) : (
<Box sx={{ mt: 2 }}>
<PasswordInput
label="Password"
error={error}
password={password}
onUpdatePassword={(pw: string) => {
setPassword(pw);
}}
/>
</Box>
)}
</ConfirmationModal>
);
};
@@ -0,0 +1,3 @@
export * from './Accounts';
export * from './Actions';
export * from './ViewSeedPhrase';
@@ -0,0 +1,16 @@
import React from 'react';
import { Typography } from '@mui/material';
import { Stack } from '@mui/system';
import { ClientAddress } from '@nymproject/react/client-address/ClientAddress';
import { useAppContext } from 'src/context';
export const Address = () => {
const { client } = useAppContext();
return (
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Typography fontWeight={700}>Address</Typography>
<ClientAddress withCopy address={client?.address || ''} />
</Stack>
);
};
@@ -0,0 +1,23 @@
import React, { useEffect } from 'react';
import { Stack, Typography } from '@mui/material';
import { useAppContext } from 'src/context';
export const Balance = () => {
const { balance, fiatBalance, currency, getBalance } = useAppContext();
useEffect(() => {
getBalance();
}, []);
const fiat = fiatBalance ? `~ ${Intl.NumberFormat().format(fiatBalance)} ${currency.toUpperCase()}` : '-';
return (
<Stack alignItems="center" gap={1}>
<Typography sx={{ color: 'grey.600' }}>Available</Typography>
<Typography variant="h4" textAlign="center">
{balance} NYM
</Typography>
<Typography sx={{ color: 'grey.600' }}>{fiat}</Typography>
</Stack>
);
};
@@ -0,0 +1,6 @@
export * from './accounts';
export * from './address';
export * from './balance';
export * from './receive';
export * from './send';
export * from './ui';
@@ -0,0 +1,35 @@
import React from 'react';
import { Card, CardContent, Dialog, DialogContent, DialogTitle, IconButton, Stack, Typography } from '@mui/material';
import { QRCodeSVG } from 'qrcode.react';
import { useAppContext } from 'src/context';
import { ClientAddress } from '@nymproject/react/client-address/ClientAddress';
import { Close } from '@mui/icons-material';
export const ReceiveModal = ({ open, onClose }: { open: boolean; onClose: () => void }) => {
const { client } = useAppContext();
return (
<Dialog open={open} onClose={onClose} maxWidth="xl" fullWidth>
<DialogTitle>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight={700}>Receive</Typography>
<IconButton size="small" onClick={onClose} sx={{ padding: 0 }}>
<Close fontSize="small" />
</IconButton>
</Stack>
</DialogTitle>
<DialogContent>
<Stack gap={1} alignItems="center">
<Card elevation={3} sx={{ my: 2, width: 200 }}>
<CardContent sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<QRCodeSVG value={client?.address || ''} />
</CardContent>
</Card>
<Typography variant="body2" fontWeight={700}>
Your Nym address
</Typography>
<ClientAddress address={client?.address || ''} withCopy smallIcons />
</Stack>
</DialogContent>
</Dialog>
);
};
@@ -0,0 +1 @@
export * from './ReceiveModal';
@@ -0,0 +1,30 @@
import React from 'react';
import { Box, Typography } from '@mui/material';
import { Link } from '@nymproject/react/link/Link';
import { ConfirmationModal, Button } from 'src/components/ui';
export const SendConfirmationModal = ({
amount,
txUrl,
onConfirm,
}: {
amount: string;
txUrl: string;
onConfirm: () => void;
}) => (
<ConfirmationModal
open
fullWidth
title="You sent"
ConfirmButton={
<Button fullWidth variant="contained" size="large" onClick={onConfirm}>
Done
</Button>
}
>
<Box>
<Typography variant="h6">{amount}</Typography>
<Link href={txUrl} target="_blank" sx={{ ml: 1 }} text="View on blockchain" />
</Box>
</ConfirmationModal>
);
@@ -0,0 +1 @@
export * from './SendConfirmationModal';
@@ -0,0 +1,14 @@
import * as React from 'react';
import { AppBar as MUIAppBar } from '@mui/material/';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
export const AppBar = ({ Action }: { Action: React.ReactNode }) => (
<Box sx={{ flexGrow: 1 }}>
<MUIAppBar position="static" elevation={0} sx={{ bgcolor: 'rgba(103, 80, 164, 0.14)' }}>
<Toolbar variant="dense">{Action}</Toolbar>
</MUIAppBar>
</Box>
);
export default AppBar;
@@ -0,0 +1,23 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { ArrowBackIosRounded } from '@mui/icons-material';
import { IconButton } from '@mui/material';
export const BackButton = ({ onBack }: { onBack?: () => void }) => {
const navigate = useNavigate();
const handleClick = () => {
if (onBack) {
onBack();
} else {
navigate(-1);
}
return undefined;
};
return (
<IconButton size="small" onClick={handleClick}>
<ArrowBackIosRounded fontSize="small" />
</IconButton>
);
};
@@ -0,0 +1,6 @@
import React from 'react';
import { Button as MUIButton, ButtonProps } from '@mui/material';
export const Button = (props: ButtonProps) => (
<MUIButton {...props} disableElevation sx={{ textTransform: 'initial' }} />
);
@@ -0,0 +1,6 @@
import React from 'react';
import { NymLogoBW } from '@nymproject/react/logo/NymLogoBW';
export const Logo = ({ small }: { small?: boolean }) => (
<NymLogoBW width={small ? '37.5px' : '75px'} height={small ? '37.5px' : '75px'} />
);
@@ -0,0 +1,20 @@
import React from 'react';
import { Stack, Typography } from '@mui/material';
import { Logo } from '../Logo';
import { Title } from '../Title';
export const LogoWithText = ({
logoSmall,
title,
description,
}: {
logoSmall?: boolean;
title: string;
description?: string;
}) => (
<Stack alignItems="center" justifyContent="center" gap={3}>
<Logo small={logoSmall} />
<Title>{title}</Title>
<Typography sx={{ color: 'grey.700', textAlign: 'center' }}>{description}</Typography>
</Stack>
);
@@ -0,0 +1,55 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Drawer from '@mui/material/Drawer';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import { AccountBalanceWalletRounded, AccountCircleRounded, ArrowDownwardRounded } from '@mui/icons-material';
import { Link } from 'react-router-dom';
const menuSchema = [
{
title: 'Accounts',
Icon: <AccountCircleRounded />,
path: '/user/accounts',
},
{
title: 'Balance',
Icon: <AccountBalanceWalletRounded />,
path: '/user/balance',
},
{
title: 'Send',
Icon: <ArrowDownwardRounded />,
path: '/user/send',
},
];
export const MenuDrawer = ({ open, onClose }: { open: boolean; onClose: () => void }) => {
const list = () => (
<Box sx={{ width: 250 }} role="presentation" onClick={() => {}}>
<List>
{menuSchema.map(({ title, Icon, path }) => (
<Link to={path} style={{ textDecoration: 'none', color: 'unset' }} key={title}>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>{Icon}</ListItemIcon>
<ListItemText primary={title} />
</ListItemButton>
</ListItem>
</Link>
))}
</List>
</Box>
);
return (
<div>
<Drawer anchor="left" open={open} onClose={onClose}>
{list()}
</Drawer>
</div>
);
};
@@ -0,0 +1,74 @@
import React from 'react';
import {
Breakpoint,
Paper,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
SxProps,
Typography,
} from '@mui/material';
import { Button } from '../Button';
export interface ErrorModalProps {
open: boolean;
children?: React.ReactNode;
title: React.ReactNode | string;
subtitle?: React.ReactNode | string;
sx?: SxProps;
fullWidth?: boolean;
maxWidth?: Breakpoint;
backdropProps?: object;
onClose?: () => void;
}
export const ErrorModal = ({
open,
onClose,
children,
title,
subtitle,
sx,
fullWidth,
maxWidth,
backdropProps,
}: ErrorModalProps) => {
const Title = (
<DialogTitle id="responsive-dialog-title" sx={{ pb: 2 }}>
<Typography variant="body2" fontWeight={600}>
{title}
</Typography>
{subtitle &&
(typeof subtitle === 'string' ? (
<Typography fontWeight={400} variant="subtitle1" fontSize={12} sx={{ color: 'grey.400' }}>
{subtitle}
</Typography>
) : (
subtitle
))}
</DialogTitle>
);
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="responsive-dialog-title"
maxWidth={maxWidth || 'sm'}
sx={{ textAlign: 'center', ...sx }}
fullWidth={fullWidth}
BackdropProps={backdropProps}
PaperComponent={Paper}
PaperProps={{ elevation: 0 }}
>
{Title}
<DialogContent>{children}</DialogContent>
<DialogActions sx={{ px: 3, pb: 3 }}>
<Button variant="contained" size="large" fullWidth onClick={onClose}>
Close
</Button>
</DialogActions>
</Dialog>
);
};
@@ -0,0 +1,25 @@
import React from 'react';
import { Box, CircularProgress, Modal, Stack, Typography, SxProps } from '@mui/material';
const modalStyle: SxProps = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 300,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: '16px',
p: 4,
};
export const LoadingModal = ({ sx, backdropProps }: { sx?: SxProps; backdropProps?: object }) => (
<Modal open BackdropProps={backdropProps}>
<Box sx={{ border: (t) => `1px solid ${t.palette.grey[500]}`, ...modalStyle, ...sx }} textAlign="center">
<Stack spacing={4} direction="row" alignItems="center">
<CircularProgress />
<Typography sx={{ color: 'text.primary' }}>Please wait...</Typography>
</Stack>
</Box>
</Modal>
);
@@ -0,0 +1,71 @@
import React from 'react';
import {
Breakpoint,
Paper,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
SxProps,
Typography,
} from '@mui/material';
export interface ConfirmationModalProps {
open: boolean;
children?: React.ReactNode;
title: React.ReactNode | string;
subtitle?: React.ReactNode | string;
ConfirmButton: React.ReactNode;
sx?: SxProps;
fullWidth?: boolean;
maxWidth?: Breakpoint;
backdropProps?: object;
onClose?: () => void;
}
export const ConfirmationModal = ({
open,
onClose,
children,
title,
subtitle,
ConfirmButton,
sx,
fullWidth,
maxWidth,
backdropProps,
}: ConfirmationModalProps) => {
const Title = (
<DialogTitle id="responsive-dialog-title" sx={{ pb: 2 }}>
<Typography variant="body2" fontWeight={600}>
{title}
</Typography>
{subtitle &&
(typeof subtitle === 'string' ? (
<Typography fontWeight={400} variant="subtitle1" fontSize={12} sx={{ color: 'grey.400' }}>
{subtitle}
</Typography>
) : (
subtitle
))}
</DialogTitle>
);
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="responsive-dialog-title"
maxWidth={maxWidth || 'sm'}
sx={{ textAlign: 'center', ...sx }}
fullWidth={fullWidth}
BackdropProps={backdropProps}
PaperComponent={Paper}
PaperProps={{ elevation: 0 }}
>
{Title}
<DialogContent>{children}</DialogContent>
<DialogActions sx={{ px: 3, pb: 3 }}>{ConfirmButton}</DialogActions>
</Dialog>
);
};
@@ -0,0 +1,3 @@
export * from './Modal';
export * from './LoadingModal';
export * from './ErrorModal';

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