Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 190ddc0d7b | |||
| 7567b57553 | |||
| 3268aa63e6 | |||
| 132a8c66f6 | |||
| f932135799 | |||
| 3b8b29a0ab | |||
| cfec1781a8 | |||
| 03280cd9b4 | |||
| cd16239cf3 | |||
| 7fa5a778aa | |||
| 7609d6ae4d | |||
| fa02376403 | |||
| 68ebe93ba5 | |||
| 0fe5264231 | |||
| f6dffa2a38 | |||
| d86a393412 | |||
| 281de87871 | |||
| bc47fdfdfd | |||
| 05dd39699d | |||
| 5cf97977a1 | |||
| a47a10fdde | |||
| 2a8265371d | |||
| 0b7513ff55 | |||
| 312c51535f | |||
| 54fb9ebfab | |||
| 3ec9c4d8d7 | |||
| 6d0b899648 | |||
| bb5187eb0a | |||
| 558df0975b | |||
| 952fcdb2b3 | |||
| 7bc4a69a1c | |||
| dd1e46ec15 | |||
| 8c219f0603 | |||
| 8c0addb987 | |||
| fc53eec241 | |||
| 12649627a5 | |||
| 99684e79e4 | |||
| fc76c2d7a0 | |||
| 18f7ba92bb | |||
| 33339c085d | |||
| 863f329106 | |||
| 314a37cabe | |||
| 917f391948 | |||
| a4e674c98b |
Generated
+232
-54
@@ -1447,7 +1447,7 @@ checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"prost 0.11.9",
|
"prost 0.11.9",
|
||||||
"prost-types",
|
"prost-types",
|
||||||
"tonic",
|
"tonic 0.9.2",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1469,7 +1469,7 @@ dependencies = [
|
|||||||
"thread_local",
|
"thread_local",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic 0.9.2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -3580,6 +3580,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2 0.4.11",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -3634,6 +3635,19 @@ dependencies = [
|
|||||||
"tokio-io-timeout",
|
"tokio-io-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-timeout"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
|
||||||
|
dependencies = [
|
||||||
|
"hyper 1.6.0",
|
||||||
|
"hyper-util",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
@@ -5157,7 +5171,7 @@ dependencies = [
|
|||||||
"clap_complete_fig",
|
"clap_complete_fig",
|
||||||
"const-str",
|
"const-str",
|
||||||
"log",
|
"log",
|
||||||
"opentelemetry",
|
"opentelemetry 0.30.0",
|
||||||
"opentelemetry-jaeger",
|
"opentelemetry-jaeger",
|
||||||
"schemars 0.8.22",
|
"schemars 0.8.22",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -6001,6 +6015,10 @@ dependencies = [
|
|||||||
"nym-validator-client 0.1.0",
|
"nym-validator-client 0.1.0",
|
||||||
"nym-wireguard",
|
"nym-wireguard",
|
||||||
"nym-wireguard-types 0.1.0",
|
"nym-wireguard-types 0.1.0",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry-otlp",
|
||||||
|
"opentelemetry-stdout",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"sha2 0.10.9",
|
"sha2 0.10.9",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
@@ -6011,6 +6029,7 @@ dependencies = [
|
|||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-opentelemetry",
|
||||||
"url",
|
"url",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -6069,6 +6088,7 @@ dependencies = [
|
|||||||
"nym-sphinx 0.1.0",
|
"nym-sphinx 0.1.0",
|
||||||
"nym-statistics-common 0.1.0",
|
"nym-statistics-common 0.1.0",
|
||||||
"nym-task 0.1.0",
|
"nym-task 0.1.0",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -6620,6 +6640,7 @@ dependencies = [
|
|||||||
"cargo_metadata 0.19.2",
|
"cargo_metadata 0.19.2",
|
||||||
"celes",
|
"celes",
|
||||||
"chacha",
|
"chacha",
|
||||||
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
"criterion",
|
"criterion",
|
||||||
@@ -6666,6 +6687,11 @@ dependencies = [
|
|||||||
"nym-verloc",
|
"nym-verloc",
|
||||||
"nym-wireguard",
|
"nym-wireguard",
|
||||||
"nym-wireguard-types 0.1.0",
|
"nym-wireguard-types 0.1.0",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry-otlp",
|
||||||
|
"opentelemetry-semantic-conventions 0.30.0",
|
||||||
|
"opentelemetry-stdout",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -6679,7 +6705,10 @@ dependencies = [
|
|||||||
"toml 0.8.23",
|
"toml 0.8.23",
|
||||||
"tower-http 0.5.2",
|
"tower-http 0.5.2",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
"tracing-indicatif",
|
"tracing-indicatif",
|
||||||
|
"tracing-opentelemetry",
|
||||||
|
"tracing-serde",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url",
|
"url",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
@@ -6768,7 +6797,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nym-node-status-api"
|
name = "nym-node-status-api"
|
||||||
version = "3.2.6"
|
version = "3.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -6780,7 +6809,6 @@ dependencies = [
|
|||||||
"cosmwasm-std",
|
"cosmwasm-std",
|
||||||
"envy",
|
"envy",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"moka",
|
"moka",
|
||||||
"nym-bin-common 0.6.0 (git+https://github.com/nymtech/nym.git?branch=release/2025.11-cheddar)",
|
"nym-bin-common 0.6.0 (git+https://github.com/nymtech/nym.git?branch=release/2025.11-cheddar)",
|
||||||
@@ -7061,6 +7089,11 @@ dependencies = [
|
|||||||
"nym-task 0.1.0",
|
"nym-task 0.1.0",
|
||||||
"nym-topology 0.1.0",
|
"nym-topology 0.1.0",
|
||||||
"nym-validator-client 0.1.0",
|
"nym-validator-client 0.1.0",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry-otlp",
|
||||||
|
"opentelemetry-semantic-conventions 0.30.0",
|
||||||
|
"opentelemetry-stdout",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.12.22",
|
"reqwest 0.12.22",
|
||||||
@@ -7074,6 +7107,8 @@ dependencies = [
|
|||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml 0.8.23",
|
"toml 0.8.23",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-opentelemetry",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
@@ -8235,90 +8270,164 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry"
|
name = "opentelemetry"
|
||||||
version = "0.19.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f"
|
checksum = "1b69a91d4893e713e06f724597ad630f1fa76057a5e1026c0ca67054a9032a76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opentelemetry_api",
|
"futures-core",
|
||||||
"opentelemetry_sdk",
|
"futures-sink",
|
||||||
|
"js-sys",
|
||||||
|
"once_cell",
|
||||||
|
"pin-project-lite",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry"
|
||||||
|
version = "0.30.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"js-sys",
|
||||||
|
"pin-project-lite",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-http"
|
name = "opentelemetry-http"
|
||||||
version = "0.8.0"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a819b71d6530c4297b49b3cae2939ab3a8cc1b9f382826a1bc29dd0ca3864906"
|
checksum = "b0ba633e55c5ea6f431875ba55e71664f2fa5d3a90bd34ec9302eecc41c865dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"isahc",
|
"isahc",
|
||||||
"opentelemetry_api",
|
"opentelemetry 0.23.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry-http"
|
||||||
|
version = "0.30.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"http 1.3.1",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"reqwest 0.12.22",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-jaeger"
|
name = "opentelemetry-jaeger"
|
||||||
version = "0.18.0"
|
version = "0.22.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08e028dc9f4f304e9320ce38c80e7cf74067415b1ad5a8750a38bae54a4d450d"
|
checksum = "501b471b67b746d9a07d4c29f8be00f952d1a2eca356922ede0098cbaddff19f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"futures",
|
"futures-core",
|
||||||
"futures-executor",
|
"futures-util",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"isahc",
|
"isahc",
|
||||||
"once_cell",
|
"opentelemetry 0.23.0",
|
||||||
"opentelemetry",
|
"opentelemetry-http 0.12.0",
|
||||||
"opentelemetry-http",
|
"opentelemetry-semantic-conventions 0.15.0",
|
||||||
"opentelemetry-semantic-conventions",
|
"opentelemetry_sdk 0.23.0",
|
||||||
"thiserror 1.0.69",
|
|
||||||
"thrift",
|
"thrift",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-semantic-conventions"
|
name = "opentelemetry-otlp"
|
||||||
version = "0.11.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24e33428e6bf08c6f7fcea4ddb8e358fab0fe48ab877a87c70c6ebe20f673ce5"
|
checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opentelemetry",
|
"http 1.3.1",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry-http 0.30.0",
|
||||||
|
"opentelemetry-proto",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
|
"prost 0.13.5",
|
||||||
|
"reqwest 0.12.22",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tonic 0.13.1",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry_api"
|
name = "opentelemetry-proto"
|
||||||
version = "0.19.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2"
|
checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"opentelemetry 0.30.0",
|
||||||
"futures-channel",
|
"opentelemetry_sdk 0.30.0",
|
||||||
"futures-util",
|
"prost 0.13.5",
|
||||||
"indexmap 1.9.3",
|
"tonic 0.13.1",
|
||||||
"once_cell",
|
]
|
||||||
"pin-project-lite",
|
|
||||||
"thiserror 1.0.69",
|
[[package]]
|
||||||
"urlencoding",
|
name = "opentelemetry-semantic-conventions"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1869fb4bb9b35c5ba8a1e40c9b128a7b4c010d07091e864a29da19e4fe2ca4d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry-semantic-conventions"
|
||||||
|
version = "0.30.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83d059a296a47436748557a353c5e6c5705b9470ef6c95cfc52c21a8814ddac2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry-stdout"
|
||||||
|
version = "0.30.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "447191061af41c3943e082ea359ab8b64ff27d6d34d30d327df309ddef1eef6f"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry_sdk"
|
name = "opentelemetry_sdk"
|
||||||
version = "0.19.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1"
|
checksum = "ae312d58eaa90a82d2e627fd86e075cf5230b3f11794e2ed74199ebbe572d4fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"crossbeam-channel",
|
|
||||||
"dashmap",
|
|
||||||
"fnv",
|
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-executor",
|
"futures-executor",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"lazy_static",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry_api",
|
"opentelemetry 0.23.0",
|
||||||
|
"ordered-float 4.6.0",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry_sdk"
|
||||||
|
version = "0.30.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-util",
|
||||||
|
"opentelemetry 0.30.0",
|
||||||
|
"percent-encoding",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
]
|
]
|
||||||
@@ -8338,6 +8447,15 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "4.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -9255,6 +9373,7 @@ dependencies = [
|
|||||||
"async-compression",
|
"async-compression",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
@@ -11032,7 +11151,7 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
"integer-encoding",
|
"integer-encoding",
|
||||||
"log",
|
"log",
|
||||||
"ordered-float",
|
"ordered-float 2.10.1",
|
||||||
"threadpool",
|
"threadpool",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -11338,7 +11457,7 @@ dependencies = [
|
|||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
"hyper 0.14.32",
|
"hyper 0.14.32",
|
||||||
"hyper-timeout",
|
"hyper-timeout 0.4.1",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"prost 0.11.9",
|
"prost 0.11.9",
|
||||||
@@ -11350,6 +11469,34 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tonic"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bytes",
|
||||||
|
"http 1.3.1",
|
||||||
|
"http-body 1.0.1",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper 1.6.0",
|
||||||
|
"hyper-timeout 0.5.2",
|
||||||
|
"hyper-util",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"prost 0.13.5",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls 0.26.2",
|
||||||
|
"tokio-stream",
|
||||||
|
"tower 0.5.2",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"webpki-roots 0.26.11",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -11378,9 +11525,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"indexmap 2.10.0",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"slab",
|
||||||
"sync_wrapper 1.0.2",
|
"sync_wrapper 1.0.2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -11522,16 +11672,30 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-opentelemetry"
|
name = "tracing-opentelemetry"
|
||||||
version = "0.19.0"
|
version = "0.31.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00a39dcf9bfc1742fa4d6215253b33a6e474be78275884c216fc2a06267b3600"
|
checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry",
|
"opentelemetry 0.30.0",
|
||||||
|
"opentelemetry_sdk 0.30.0",
|
||||||
|
"smallvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log 0.1.4",
|
"tracing-log 0.2.0",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-serde"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -11544,12 +11708,15 @@ dependencies = [
|
|||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log 0.2.0",
|
"tracing-log 0.2.0",
|
||||||
|
"tracing-serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -11947,12 +12114,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "urlencoding"
|
|
||||||
version = "2.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf-8"
|
name = "utf-8"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@@ -13220,3 +13381,20 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zulip-client"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"itertools 0.14.0",
|
||||||
|
"nym-bin-common 0.6.0",
|
||||||
|
"nym-http-api-client 0.1.0",
|
||||||
|
"reqwest 0.12.22",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|||||||
+10
-4
@@ -99,7 +99,7 @@ members = [
|
|||||||
"common/wasm/storage",
|
"common/wasm/storage",
|
||||||
"common/wasm/utils",
|
"common/wasm/utils",
|
||||||
"common/wireguard",
|
"common/wireguard",
|
||||||
"common/wireguard-types",
|
"common/wireguard-types", "common/zulip-client",
|
||||||
"documentation/autodoc",
|
"documentation/autodoc",
|
||||||
"gateway",
|
"gateway",
|
||||||
"nym-api",
|
"nym-api",
|
||||||
@@ -281,8 +281,12 @@ nix = "0.27.1"
|
|||||||
notify = "5.1.0"
|
notify = "5.1.0"
|
||||||
okapi = "0.7.0"
|
okapi = "0.7.0"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
opentelemetry = "0.19.0"
|
opentelemetry = "0.30.0"
|
||||||
opentelemetry-jaeger = "0.18.0"
|
opentelemetry-otlp = "0.30.0"
|
||||||
|
opentelemetry-semantic-conventions = "0.30.0"
|
||||||
|
opentelemetry_sdk = "0.30.0"
|
||||||
|
opentelemetry-stdout = "0.30.0"
|
||||||
|
opentelemetry-jaeger = "0.22.0"
|
||||||
parking_lot = "0.12.3"
|
parking_lot = "0.12.3"
|
||||||
pem = "0.8"
|
pem = "0.8"
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
@@ -338,8 +342,10 @@ toml = "0.8.22"
|
|||||||
tower = "0.5.2"
|
tower = "0.5.2"
|
||||||
tower-http = "0.5.2"
|
tower-http = "0.5.2"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
|
tracing-core = "0.1.33"
|
||||||
tracing-log = "0.2"
|
tracing-log = "0.2"
|
||||||
tracing-opentelemetry = "0.19.0"
|
tracing-opentelemetry = "0.31.0"
|
||||||
|
tracing-serde = "0.2.0"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = "0.3.19"
|
||||||
tracing-tree = "0.2.2"
|
tracing-tree = "0.2.2"
|
||||||
tracing-indicatif = "0.3.9"
|
tracing-indicatif = "0.3.9"
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
find . -name "Cargo.toml" -not -path "./target/*" -exec grep -l "^name = " {} \; | xargs grep "^name = " | grep -v 'name = "nym-'
|
||||||
|
|
||||||
|
find . -name "Cargo.toml" \
|
||||||
|
-not -path "./nym-wallet/*" \
|
||||||
|
-not -path "./contracts/*" \
|
||||||
|
-not -path "./target/*" \
|
||||||
|
-not -name "./Cargo.toml" \
|
||||||
|
-exec sed -i 's/^version = ".*"/version.workspace = true/' {} \;
|
||||||
|
|
||||||
|
find . -name "Cargo.toml" -not -path "./target/*" -exec awk '/^\[package\]/{flag=1; next} flag && /^name = /{print FILENAME ":" $0; flag=0} /^\[/{flag=0}' {} \; | grep -v 'name = "nym-'
|
||||||
@@ -21,10 +21,10 @@ serde_json = { workspace = true, optional = true }
|
|||||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||||
tracing-tree = { workspace = true, optional = true }
|
tracing-tree = { workspace = true, optional = true }
|
||||||
tracing = { workspace = true, optional = true }
|
tracing = { workspace = true, optional = true }
|
||||||
opentelemetry-jaeger = { workspace = true, features = ["rt-tokio", "collector_client", "isahc_collector_client"], optional = true }
|
opentelemetry-jaeger = { workspace = true, features = ["tokio", "collector_client", "isahc_collector_client"], optional = true }
|
||||||
tracing-opentelemetry = { workspace = true, optional = true }
|
tracing-opentelemetry = { workspace = true, optional = true }
|
||||||
utoipa = { workspace = true, optional = true }
|
utoipa = { workspace = true, optional = true }
|
||||||
opentelemetry = { workspace = true, features = ["rt-tokio"], optional = true }
|
opentelemetry = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ pub trait MixnetClientStorage {
|
|||||||
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
|
fn gateway_details_store(&self) -> &Self::GatewaysDetailsStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Ephemeral {
|
pub struct Ephemeral {
|
||||||
key_store: InMemEphemeralKeys,
|
key_store: InMemEphemeralKeys,
|
||||||
reply_store: reply_storage::Empty,
|
reply_store: reply_storage::Empty,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ mod test;
|
|||||||
// use the old key after new one was issued.
|
// use the old key after new one was issued.
|
||||||
|
|
||||||
// Remember that Arc<T> has Deref implementation for T
|
// Remember that Arc<T> has Deref implementation for T
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ClientKeys {
|
pub struct ClientKeys {
|
||||||
/// identity key associated with the client instance.
|
/// identity key associated with the client instance.
|
||||||
identity_keypair: Arc<ed25519::KeyPair>,
|
identity_keypair: Arc<ed25519::KeyPair>,
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ impl KeyStore for OnDiskKeys {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct InMemEphemeralKeys {
|
pub struct InMemEphemeralKeys {
|
||||||
keys: Arc<Mutex<ClientKeys>>,
|
keys: Arc<Mutex<ClientKeys>>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ pub enum Ed25519RecoveryError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Keypair for usage in ed25519 EdDSA.
|
/// Keypair for usage in ed25519 EdDSA.
|
||||||
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
private_key: PrivateKey,
|
private_key: PrivateKey,
|
||||||
@@ -66,6 +66,12 @@ pub struct KeyPair {
|
|||||||
index: u32,
|
index: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for KeyPair {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
Display::fmt(&self.public_key.to_base58_string(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// All keys will always have an index field populated this is to prevent anyone from figuring out if
|
/// All keys will always have an index field populated this is to prevent anyone from figuring out if
|
||||||
/// the keys are derived or random, and alter their behaviour based on that.
|
/// the keys are derived or random, and alter their behaviour based on that.
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
|
|||||||
@@ -55,6 +55,12 @@ pub struct KeyPair {
|
|||||||
pub(crate) public_key: PublicKey,
|
pub(crate) public_key: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for KeyPair {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
Display::fmt(&self.public_key.to_base58_string(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
||||||
@@ -227,6 +233,12 @@ impl AsRef<[u8]> for PublicKey {
|
|||||||
#[derive(Zeroize, ZeroizeOnDrop)]
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct PrivateKey(x25519_dalek::StaticSecret);
|
pub struct PrivateKey(x25519_dalek::StaticSecret);
|
||||||
|
|
||||||
|
impl Debug for PrivateKey {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.to_base58_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for PrivateKey {
|
impl Display for PrivateKey {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.to_base58_string())
|
write!(f, "{}", self.to_base58_string())
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ serde = { workspace = true, features = ["derive"] }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tracing = { workspace = true, features = ["log"] }
|
|
||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
subtle = { workspace = true }
|
subtle = { workspace = true }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
@@ -34,6 +33,9 @@ nym-task = { path = "../task" }
|
|||||||
nym-credentials = { path = "../credentials" }
|
nym-credentials = { path = "../credentials" }
|
||||||
nym-credentials-interface = { path = "../credentials-interface" }
|
nym-credentials-interface = { path = "../credentials-interface" }
|
||||||
|
|
||||||
|
opentelemetry = { workspace = true, features = ["trace"] }
|
||||||
|
tracing = { workspace = true, features = ["std", "attributes", "tracing-attributes"] }
|
||||||
|
|
||||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["time"]
|
features = ["time"]
|
||||||
@@ -48,3 +50,4 @@ default-features = false
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nym-compact-ecash = { path = "../nym_offline_compact_ecash" } # we need specific imports in tests
|
nym-compact-ecash = { path = "../nym_offline_compact_ecash" } # we need specific imports in tests
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use rand::{thread_rng, CryptoRng, RngCore};
|
|||||||
use std::any::{type_name, Any};
|
use std::any::{type_name, Any};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::log::*;
|
use tracing::{error, trace};
|
||||||
use tungstenite::Message as WsMessage;
|
use tungstenite::Message as WsMessage;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ pub struct AuthenticateRequest {
|
|||||||
pub content: AuthenticateRequestContent,
|
pub content: AuthenticateRequestContent,
|
||||||
|
|
||||||
pub request_signature: ed25519::Signature,
|
pub request_signature: ed25519::Signature,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub debug_trace_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AuthenticateRequest {
|
impl AuthenticateRequest {
|
||||||
@@ -23,6 +26,7 @@ impl AuthenticateRequest {
|
|||||||
protocol_version: u8,
|
protocol_version: u8,
|
||||||
shared_key: &SharedGatewayKey,
|
shared_key: &SharedGatewayKey,
|
||||||
identity_keys: &ed25519::KeyPair,
|
identity_keys: &ed25519::KeyPair,
|
||||||
|
debug_trace_id: Option<String>,
|
||||||
) -> Result<AuthenticateRequest, GatewayRequestsError> {
|
) -> Result<AuthenticateRequest, GatewayRequestsError> {
|
||||||
let content = AuthenticateRequestContent::new(
|
let content = AuthenticateRequestContent::new(
|
||||||
protocol_version,
|
protocol_version,
|
||||||
@@ -35,6 +39,7 @@ impl AuthenticateRequest {
|
|||||||
Ok(AuthenticateRequest {
|
Ok(AuthenticateRequest {
|
||||||
content,
|
content,
|
||||||
request_signature,
|
request_signature,
|
||||||
|
debug_trace_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ use nym_credentials_interface::CredentialSpendingData;
|
|||||||
use nym_crypto::asymmetric::ed25519;
|
use nym_crypto::asymmetric::ed25519;
|
||||||
use nym_sphinx::DestinationAddressBytes;
|
use nym_sphinx::DestinationAddressBytes;
|
||||||
use nym_statistics_common::types::SessionType;
|
use nym_statistics_common::types::SessionType;
|
||||||
|
use opentelemetry::trace::TraceContextExt;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use tracing::{instrument, warn};
|
||||||
use tungstenite::Message;
|
use tungstenite::Message;
|
||||||
|
|
||||||
pub mod authenticate;
|
pub mod authenticate;
|
||||||
@@ -76,6 +78,10 @@ pub enum ClientControlRequest {
|
|||||||
address: String,
|
address: String,
|
||||||
enc_address: String,
|
enc_address: String,
|
||||||
iv: String,
|
iv: String,
|
||||||
|
/// this is a trace id that is used in testing and performance verification
|
||||||
|
/// in mainnet, this will always be set to None
|
||||||
|
#[serde(default)]
|
||||||
|
debug_trace_id: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
AuthenticateV2(Box<AuthenticateRequest>),
|
AuthenticateV2(Box<AuthenticateRequest>),
|
||||||
@@ -127,14 +133,24 @@ impl ClientControlRequest {
|
|||||||
let nonce = shared_key.random_nonce_or_iv();
|
let nonce = shared_key.random_nonce_or_iv();
|
||||||
let ciphertext = shared_key.encrypt_naive(address.as_bytes_ref(), Some(&nonce))?;
|
let ciphertext = shared_key.encrypt_naive(address.as_bytes_ref(), Some(&nonce))?;
|
||||||
|
|
||||||
|
let otel_context = opentelemetry::Context::current();
|
||||||
|
warn!("OTEL CONTEXT: {:?}", otel_context);
|
||||||
|
let span = otel_context.span();
|
||||||
|
let context = span.span_context();
|
||||||
|
let trace_id = context.trace_id();
|
||||||
|
warn!("TRACE_ID: {:?}", trace_id);
|
||||||
|
// panic!();
|
||||||
|
|
||||||
Ok(ClientControlRequest::Authenticate {
|
Ok(ClientControlRequest::Authenticate {
|
||||||
protocol_version,
|
protocol_version,
|
||||||
address: address.as_base58_string(),
|
address: address.as_base58_string(),
|
||||||
enc_address: bs58::encode(&ciphertext).into_string(),
|
enc_address: bs58::encode(&ciphertext).into_string(),
|
||||||
iv: bs58::encode(&nonce).into_string(),
|
iv: bs58::encode(&nonce).into_string(),
|
||||||
|
debug_trace_id: Some(trace_id.to_string()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
pub fn new_authenticate_v2(
|
pub fn new_authenticate_v2(
|
||||||
shared_key: &SharedGatewayKey,
|
shared_key: &SharedGatewayKey,
|
||||||
identity_keys: &ed25519::KeyPair,
|
identity_keys: &ed25519::KeyPair,
|
||||||
@@ -142,8 +158,21 @@ impl ClientControlRequest {
|
|||||||
// if we're using v2 authentication, we must announce at least that protocol version
|
// if we're using v2 authentication, we must announce at least that protocol version
|
||||||
let protocol_version = AUTHENTICATE_V2_PROTOCOL_VERSION;
|
let protocol_version = AUTHENTICATE_V2_PROTOCOL_VERSION;
|
||||||
|
|
||||||
|
let otel_context = opentelemetry::Context::current();
|
||||||
|
warn!("OTEL CONTEXT: {:?}", otel_context);
|
||||||
|
let span = otel_context.span();
|
||||||
|
let context = span.span_context();
|
||||||
|
let trace_id = context.trace_id();
|
||||||
|
warn!("TRACE_ID: {:?}", trace_id);
|
||||||
|
// panic!();
|
||||||
|
|
||||||
Ok(ClientControlRequest::AuthenticateV2(Box::new(
|
Ok(ClientControlRequest::AuthenticateV2(Box::new(
|
||||||
AuthenticateRequest::new(protocol_version, shared_key, identity_keys)?,
|
AuthenticateRequest::new(
|
||||||
|
protocol_version,
|
||||||
|
shared_key,
|
||||||
|
identity_keys,
|
||||||
|
Some(trace_id.to_string()),
|
||||||
|
)?,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
//! The resolver itself is the set combination of the google, cloudflare, and quad9 endpoints
|
//! The resolver itself is the set combination of the google, cloudflare, and quad9 endpoints
|
||||||
//! supporting DoH and DoT.
|
//! supporting DoH and DoT.
|
||||||
//!
|
//!
|
||||||
//! This resolver implements a fallback mechanism where, should the DNS-over-TLS resolution fail, a
|
//! This resolver supports a fallback mechanism where, should the DNS-over-TLS resolution fail, a
|
||||||
//! followup resolution will be done using the hosts configured default (e.g. `/etc/resolve.conf` on
|
//! followup resolution will be done using the hosts configured default (e.g. `/etc/resolve.conf` on
|
||||||
//! linux).
|
//! linux). This is disabled by default and can be enabled using [`enable_system_fallback`].
|
||||||
//!
|
//!
|
||||||
//! Requires the `dns-over-https-rustls`, `webpki-roots` feature for the
|
//! Requires the `dns-over-https-rustls`, `webpki-roots` feature for the
|
||||||
//! `hickory-resolver` crate
|
//! `hickory-resolver` crate
|
||||||
@@ -93,14 +93,14 @@ pub struct HickoryDnsResolver {
|
|||||||
// Tokio Runtime in initialization, so we must delay the actual
|
// Tokio Runtime in initialization, so we must delay the actual
|
||||||
// construction of the resolver.
|
// construction of the resolver.
|
||||||
state: Arc<OnceCell<TokioResolver>>,
|
state: Arc<OnceCell<TokioResolver>>,
|
||||||
fallback: Arc<OnceCell<TokioResolver>>,
|
fallback: Option<Arc<OnceCell<TokioResolver>>>,
|
||||||
dont_use_shared: bool,
|
dont_use_shared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolve for HickoryDnsResolver {
|
impl Resolve for HickoryDnsResolver {
|
||||||
fn resolve(&self, name: Name) -> Resolving {
|
fn resolve(&self, name: Name) -> Resolving {
|
||||||
let resolver = self.state.clone();
|
let resolver = self.state.clone();
|
||||||
let fallback = self.fallback.clone();
|
let maybe_fallback = self.fallback.clone();
|
||||||
let independent = self.dont_use_shared;
|
let independent = self.dont_use_shared;
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let resolver = resolver.get_or_try_init(|| {
|
let resolver = resolver.get_or_try_init(|| {
|
||||||
@@ -117,23 +117,30 @@ impl Resolve for HickoryDnsResolver {
|
|||||||
let lookup = match resolver.lookup_ip(name.as_str()).await {
|
let lookup = match resolver.lookup_ip(name.as_str()).await {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// on failure use the fall back system configured DNS resolver
|
if let Some(ref fallback) = maybe_fallback {
|
||||||
if !e.is_no_records_found() {
|
// on failure use the fall back system configured DNS resolver
|
||||||
warn!("primary DNS failed w/ error {e}: using system fallback");
|
if !e.is_no_records_found() {
|
||||||
}
|
warn!("primary DNS failed w/ error {e}: using system fallback");
|
||||||
let resolver = fallback.get_or_try_init(|| {
|
|
||||||
// using a closure here is slightly gross, but this makes sure that if the
|
|
||||||
// lazy-init returns an error it can be handled by the client
|
|
||||||
if independent {
|
|
||||||
new_resolver_system()
|
|
||||||
} else {
|
|
||||||
Ok(SHARED_RESOLVER
|
|
||||||
.fallback
|
|
||||||
.get_or_try_init(new_resolver_system)?
|
|
||||||
.clone())
|
|
||||||
}
|
}
|
||||||
})?;
|
let resolver = fallback.get_or_try_init(|| {
|
||||||
resolver.lookup_ip(name.as_str()).await?
|
// using a closure here is slightly gross, but this makes sure that if the
|
||||||
|
// lazy-init returns an error it can be handled by the client
|
||||||
|
if independent {
|
||||||
|
new_resolver_system()
|
||||||
|
} else {
|
||||||
|
Ok(SHARED_RESOLVER
|
||||||
|
.fallback
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(e)? // if the shared resolver has no fallback return the original error
|
||||||
|
.get_or_try_init(new_resolver_system)?
|
||||||
|
.clone())
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
resolver.lookup_ip(name.as_str()).await?
|
||||||
|
} else {
|
||||||
|
return Err(e.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,14 +169,17 @@ impl HickoryDnsResolver {
|
|||||||
let lookup = match resolver.lookup_ip(name).await {
|
let lookup = match resolver.lookup_ip(name).await {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// on failure use the fall back system configured DNS resolver
|
if let Some(ref fallback) = self.fallback {
|
||||||
if !e.is_no_records_found() {
|
// on failure use the fall back system configured DNS resolver
|
||||||
warn!("primary DNS failed w/ error {e}: using system fallback");
|
if !e.is_no_records_found() {
|
||||||
|
warn!("primary DNS failed w/ error {e}: using system fallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
let resolver = fallback.get_or_try_init(|| self.new_resolver_system())?;
|
||||||
|
resolver.lookup_ip(name).await?
|
||||||
|
} else {
|
||||||
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
let resolver = self
|
|
||||||
.fallback
|
|
||||||
.get_or_try_init(|| self.new_resolver_system())?;
|
|
||||||
resolver.lookup_ip(name).await?
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -193,15 +203,34 @@ impl HickoryDnsResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_resolver_system(&self) -> Result<TokioResolver, HickoryDnsError> {
|
fn new_resolver_system(&self) -> Result<TokioResolver, HickoryDnsError> {
|
||||||
if self.dont_use_shared {
|
if self.dont_use_shared || SHARED_RESOLVER.fallback.is_none() {
|
||||||
new_resolver_system()
|
new_resolver_system()
|
||||||
} else {
|
} else {
|
||||||
Ok(SHARED_RESOLVER
|
Ok(SHARED_RESOLVER
|
||||||
.fallback
|
.fallback
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
.get_or_try_init(new_resolver_system)?
|
.get_or_try_init(new_resolver_system)?
|
||||||
.clone())
|
.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable fallback to the system default resolver if the primary (DoX) resolver fails
|
||||||
|
pub fn enable_system_fallback(&mut self) -> Result<(), HickoryDnsError> {
|
||||||
|
self.fallback = Some(Default::default());
|
||||||
|
let _ = self
|
||||||
|
.fallback
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get_or_try_init(new_resolver_system)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable fallback resolution. If the primary resolver fails the error is
|
||||||
|
/// returned immediately
|
||||||
|
pub fn disable_system_fallback(&mut self) {
|
||||||
|
self.fallback = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new resolver with a custom DoT based configuration. The options are overridden to look
|
/// Create a new resolver with a custom DoT based configuration. The options are overridden to look
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub struct UserAgent {
|
|||||||
pub version: String,
|
pub version: String,
|
||||||
/// client platform
|
/// client platform
|
||||||
pub platform: String,
|
pub platform: String,
|
||||||
/// source commit version for the calling calling crate / subsystem
|
/// source commit version for the calling crate / subsystem
|
||||||
pub git_commit: String,
|
pub git_commit: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[derive(Zeroize, ZeroizeOnDrop)]
|
#[derive(Debug, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct AckKey(CipherKey<AckEncryptionAlgorithm>);
|
pub struct AckKey(CipherKey<AckEncryptionAlgorithm>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
[package]
|
||||||
|
name = "zulip-client"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
|
itertools = { workspace = true }
|
||||||
|
url = { workspace = true, features = ["serde"] }
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
|
nym-bin-common = { path = "../bin-common" }
|
||||||
|
nym-http-api-client = { path = "../http-api-client" }
|
||||||
|
reqwest = { workspace = true }
|
||||||
|
tracing = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = { workspace = true, features = ["full"] }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
//! An incomplete Zulip API Client
|
||||||
|
//!
|
||||||
|
//! Currently, it serves a single purpose: to send a message to a server,
|
||||||
|
//! however, it could very easily be extended with additional functionalities.
|
||||||
|
//!
|
||||||
|
//! ## Sending Direct Message
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! # use zulip_client::{Client, ZulipClientError};
|
||||||
|
//! # use zulip_client::message::DirectMessage;
|
||||||
|
//! # async fn try_send() -> Result<(), ZulipClientError> {
|
||||||
|
//! let api_key = "your-api-key";
|
||||||
|
//! let email = "associated-email-address";
|
||||||
|
//! let server = "https://server-address.com";
|
||||||
|
//! let client = Client::builder(email, api_key, server)?.build()?;
|
||||||
|
//! // send to userid 12
|
||||||
|
//! client.send_message((12u32, "hello world")).await?;
|
||||||
|
//! // more concrete typing
|
||||||
|
//! client.send_message(DirectMessage::new(12, "hello world2")).await?;
|
||||||
|
//! # Ok(())
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::error::ZulipClientError;
|
||||||
|
use crate::message::{SendMessageResponse, SendableMessage};
|
||||||
|
use nym_bin_common::bin_info;
|
||||||
|
use nym_http_api_client::UserAgent;
|
||||||
|
use reqwest::{header, Method, RequestBuilder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use tracing::trace;
|
||||||
|
use url::Url;
|
||||||
|
use zeroize::Zeroizing;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct ClientConfig {
|
||||||
|
pub user_email: String,
|
||||||
|
pub api_key: String,
|
||||||
|
// TODO: introduce validation
|
||||||
|
pub user_agent: Option<String>,
|
||||||
|
pub server_url: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Client {
|
||||||
|
server_url: Url,
|
||||||
|
|
||||||
|
api_key: Zeroizing<String>,
|
||||||
|
user_email: String,
|
||||||
|
|
||||||
|
inner_client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_user_agent() -> String {
|
||||||
|
UserAgent::from(bin_info!()).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
const MESSAGES_ENDPOINT: &'static str = "/api/v1/messages";
|
||||||
|
|
||||||
|
pub fn builder(
|
||||||
|
user_email: impl Into<String>,
|
||||||
|
api_key: impl Into<String>,
|
||||||
|
server_url: impl Into<String>,
|
||||||
|
) -> Result<ClientBuilder, ZulipClientError> {
|
||||||
|
ClientBuilder::new(user_email, api_key, server_url)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(config: ClientConfig) -> Result<Self, ZulipClientError> {
|
||||||
|
let builder = ClientBuilder::new(config.user_email, config.api_key, config.server_url)?;
|
||||||
|
match config.user_agent {
|
||||||
|
Some(user_agent) => builder.user_agent(user_agent).build(),
|
||||||
|
None => builder.build(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_message(
|
||||||
|
&self,
|
||||||
|
msg: impl Into<SendableMessage>,
|
||||||
|
) -> Result<SendMessageResponse, ZulipClientError> {
|
||||||
|
let url = format!("{}{}", self.server_url, Self::MESSAGES_ENDPOINT);
|
||||||
|
|
||||||
|
self.build_request(Method::POST, Self::MESSAGES_ENDPOINT)
|
||||||
|
.form(&msg.into())
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|source| ZulipClientError::RequestSendingFailure { source, url })?
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.map_err(|source| ZulipClientError::RequestDecodeFailure { source })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_request(&self, method: Method, endpoint: &'static str) -> RequestBuilder {
|
||||||
|
let url = format!("{}{endpoint}", self.server_url);
|
||||||
|
trace!("posting to {url}");
|
||||||
|
|
||||||
|
self.inner_client
|
||||||
|
.request(method, url)
|
||||||
|
.basic_auth(&self.user_email, Some(self.api_key.to_string()))
|
||||||
|
.header(header::CONTENT_TYPE, "application/x-www-form-urlencoded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ClientBuilder {
|
||||||
|
api_key: Zeroizing<String>,
|
||||||
|
user_email: String,
|
||||||
|
server_url: Url,
|
||||||
|
user_agent: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientBuilder {
|
||||||
|
pub fn new(
|
||||||
|
user_email: impl Into<String>,
|
||||||
|
api_key: impl Into<String>,
|
||||||
|
server_url: impl Into<String>,
|
||||||
|
) -> Result<Self, ZulipClientError> {
|
||||||
|
let server_url = server_url.into();
|
||||||
|
let parsed_url =
|
||||||
|
Url::from_str(&server_url).map_err(|source| ZulipClientError::MalformedServerUrl {
|
||||||
|
raw: server_url,
|
||||||
|
source,
|
||||||
|
})?;
|
||||||
|
Ok(ClientBuilder {
|
||||||
|
api_key: Zeroizing::new(api_key.into()),
|
||||||
|
user_email: user_email.into(),
|
||||||
|
server_url: parsed_url,
|
||||||
|
user_agent: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn user_agent(mut self, user_agent: impl Into<String>) -> Self {
|
||||||
|
self.user_agent = Some(user_agent.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<Client, ZulipClientError> {
|
||||||
|
let user_agent = self.user_agent.unwrap_or_else(default_user_agent);
|
||||||
|
Ok(Client {
|
||||||
|
api_key: self.api_key,
|
||||||
|
server_url: self.server_url,
|
||||||
|
user_email: self.user_email,
|
||||||
|
inner_client: reqwest::ClientBuilder::new()
|
||||||
|
.user_agent(user_agent)
|
||||||
|
.build()
|
||||||
|
.map_err(|source| ZulipClientError::ClientBuildFailure { source })?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum ZulipClientError {
|
||||||
|
#[error("failed to send request to {url}: {source}")]
|
||||||
|
RequestSendingFailure { url: String, source: reqwest::Error },
|
||||||
|
|
||||||
|
#[error("failed to decode received response: {source}")]
|
||||||
|
RequestDecodeFailure { source: reqwest::Error },
|
||||||
|
|
||||||
|
#[error("failed to build internal client: {source}")]
|
||||||
|
ClientBuildFailure { source: reqwest::Error },
|
||||||
|
|
||||||
|
#[error("provided url ({raw}) is malformed: {source}")]
|
||||||
|
MalformedServerUrl {
|
||||||
|
raw: String,
|
||||||
|
source: url::ParseError,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
pub mod client;
|
||||||
|
pub mod error;
|
||||||
|
pub mod message;
|
||||||
|
|
||||||
|
pub type Id = u32;
|
||||||
|
|
||||||
|
pub use client::{Client, ClientBuilder};
|
||||||
|
pub use error::ZulipClientError;
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::message::to::{ToChannel, ToDirect};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub mod to;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(tag = "result")]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum SendMessageResponse {
|
||||||
|
Success {
|
||||||
|
id: i64,
|
||||||
|
automatic_new_visibility_policy: Option<i64>,
|
||||||
|
msg: String,
|
||||||
|
},
|
||||||
|
Error {
|
||||||
|
code: String,
|
||||||
|
msg: String,
|
||||||
|
stream: Option<String>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum SendableMessageContent {
|
||||||
|
// old name: 'private'
|
||||||
|
Direct {
|
||||||
|
// internally this is a list
|
||||||
|
to: String,
|
||||||
|
content: String,
|
||||||
|
},
|
||||||
|
// alternative name: 'channel'
|
||||||
|
Stream {
|
||||||
|
to: String,
|
||||||
|
topic: Option<String>,
|
||||||
|
content: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct SendableMessage {
|
||||||
|
#[serde(flatten)]
|
||||||
|
content: SendableMessageContent,
|
||||||
|
|
||||||
|
/// For clients supporting local echo, the event queue ID for the client.
|
||||||
|
/// If passed, `local_id` is required. If the message is successfully sent,
|
||||||
|
/// the server will include `local_id` in the message event that the client with this `queue_id`
|
||||||
|
/// will receive notifying it of the new message via `GET /events`.
|
||||||
|
/// This lets the client know unambiguously that it should replace the locally echoed message,
|
||||||
|
/// rather than adding this new message
|
||||||
|
/// (which would be correct if the user had sent the new message from another device).
|
||||||
|
/// example: "fb67bf8a-c031-47cc-84cf-ed80accacda8"
|
||||||
|
queue_id: Option<String>,
|
||||||
|
|
||||||
|
/// For clients supporting local echo, a unique string-format identifier chosen freely by the client;
|
||||||
|
/// the server will pass it back to the client without inspecting it, as described in the `queue_id` description.
|
||||||
|
/// example: "100.01"
|
||||||
|
local_id: Option<String>,
|
||||||
|
|
||||||
|
/// Whether the message should be initially marked read by its sender.
|
||||||
|
/// If unspecified, the server uses a heuristic based on the client name.
|
||||||
|
read_by_sender: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendableMessage {
|
||||||
|
pub fn new(content: impl Into<SendableMessageContent>) -> Self {
|
||||||
|
SendableMessage {
|
||||||
|
content: content.into(),
|
||||||
|
queue_id: None,
|
||||||
|
local_id: None,
|
||||||
|
read_by_sender: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_queue(mut self, queue_id: impl Into<String>, local_id: impl Into<String>) -> Self {
|
||||||
|
self.queue_id = Some(queue_id.into());
|
||||||
|
self.local_id = Some(local_id.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn read_by_sender(mut self, read_by_sender: bool) -> Self {
|
||||||
|
self.read_by_sender = read_by_sender;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PrivateMessage = DirectMessage;
|
||||||
|
|
||||||
|
pub struct DirectMessage {
|
||||||
|
to: String,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirectMessage {
|
||||||
|
pub fn new(to: impl Into<ToDirect>, content: impl Into<String>) -> Self {
|
||||||
|
DirectMessage {
|
||||||
|
to: to.into().to_string(),
|
||||||
|
content: content.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ChannelMessage = StreamMessage;
|
||||||
|
pub struct StreamMessage {
|
||||||
|
to: String,
|
||||||
|
topic: Option<String>,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamMessage {
|
||||||
|
pub fn new(
|
||||||
|
to: impl Into<ToChannel>,
|
||||||
|
content: impl Into<String>,
|
||||||
|
topic: Option<String>,
|
||||||
|
) -> Self {
|
||||||
|
StreamMessage {
|
||||||
|
to: to.into().to_string(),
|
||||||
|
topic,
|
||||||
|
content: content.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn no_topic(to: impl Into<ToChannel>, content: impl Into<String>) -> Self {
|
||||||
|
Self::new(to, content, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_topic(mut self, topic: impl Into<String>) -> Self {
|
||||||
|
self.topic = Some(topic.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SendableMessageContent> for SendableMessage {
|
||||||
|
fn from(content: SendableMessageContent) -> Self {
|
||||||
|
SendableMessage::new(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DirectMessage> for SendableMessage {
|
||||||
|
fn from(msg: DirectMessage) -> Self {
|
||||||
|
SendableMessageContent::from(msg).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DirectMessage> for SendableMessageContent {
|
||||||
|
fn from(msg: DirectMessage) -> Self {
|
||||||
|
SendableMessageContent::Direct {
|
||||||
|
to: msg.to,
|
||||||
|
content: msg.content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> From<(T, S)> for DirectMessage
|
||||||
|
where
|
||||||
|
T: Into<ToDirect>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
fn from((to, content): (T, S)) -> Self {
|
||||||
|
DirectMessage::new(to, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> From<(T, S)> for SendableMessage
|
||||||
|
where
|
||||||
|
T: Into<ToDirect>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
fn from((to, content): (T, S)) -> Self {
|
||||||
|
DirectMessage::new(to, content).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StreamMessage> for SendableMessage {
|
||||||
|
fn from(msg: StreamMessage) -> Self {
|
||||||
|
SendableMessageContent::from(msg).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StreamMessage> for SendableMessageContent {
|
||||||
|
fn from(msg: StreamMessage) -> Self {
|
||||||
|
SendableMessageContent::Stream {
|
||||||
|
to: msg.to,
|
||||||
|
topic: msg.topic,
|
||||||
|
content: msg.content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> From<(T, S, Option<S>)> for StreamMessage
|
||||||
|
where
|
||||||
|
T: Into<ToChannel>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
fn from((to, content, topic): (T, S, Option<S>)) -> Self {
|
||||||
|
StreamMessage::new(to, content, topic.map(Into::into))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> From<(T, S, Option<S>)> for SendableMessage
|
||||||
|
where
|
||||||
|
T: Into<ToChannel>,
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
fn from(inner: (T, S, Option<S>)) -> Self {
|
||||||
|
StreamMessage::from(inner).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::Id;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
// from the docs:
|
||||||
|
// For channel messages, either the name or integer ID of the channel.
|
||||||
|
// For direct messages, either a list containing integer user IDs
|
||||||
|
// or a list containing string Zulip API email addresses.
|
||||||
|
pub enum ToDirect {
|
||||||
|
ByIds(Vec<Id>),
|
||||||
|
ByNames(Vec<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ToDirect {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ToDirect::ByIds(ids) => write!(f, "[{}]", ids.iter().join(",")),
|
||||||
|
ToDirect::ByNames(names) => {
|
||||||
|
write!(f, "[{}]", names.join(","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<String>> for ToDirect {
|
||||||
|
fn from(names: Vec<String>) -> Self {
|
||||||
|
ToDirect::ByNames(names)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[String]> for ToDirect {
|
||||||
|
fn from(names: &[String]) -> Self {
|
||||||
|
names.to_vec().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[&str]> for ToDirect {
|
||||||
|
fn from(names: &[&str]) -> Self {
|
||||||
|
names
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> From<&[&str; N]> for ToDirect {
|
||||||
|
fn from(names: &[&str; N]) -> Self {
|
||||||
|
names.as_slice().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<&str>> for ToDirect {
|
||||||
|
fn from(names: Vec<&str>) -> Self {
|
||||||
|
names.as_slice().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for ToDirect {
|
||||||
|
fn from(name: String) -> Self {
|
||||||
|
ToDirect::ByNames(vec![name])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for ToDirect {
|
||||||
|
fn from(name: &str) -> Self {
|
||||||
|
name.to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Id> for ToDirect {
|
||||||
|
fn from(id: Id) -> Self {
|
||||||
|
ToDirect::ByIds(vec![id])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&[Id]> for ToDirect {
|
||||||
|
fn from(ids: &[Id]) -> Self {
|
||||||
|
ids.to_vec().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> From<&[Id; N]> for ToDirect {
|
||||||
|
fn from(ids: &[Id; N]) -> Self {
|
||||||
|
ids.as_slice().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Id>> for ToDirect {
|
||||||
|
fn from(ids: Vec<Id>) -> Self {
|
||||||
|
ToDirect::ByIds(ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ToChannel {
|
||||||
|
ByName(String),
|
||||||
|
ById(Id),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ToChannel {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ToChannel::ByName(name) => name.fmt(f),
|
||||||
|
ToChannel::ById(id) => id.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for ToChannel {
|
||||||
|
fn from(name: String) -> Self {
|
||||||
|
ToChannel::ByName(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for ToChannel {
|
||||||
|
fn from(name: &str) -> Self {
|
||||||
|
name.to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Id> for ToChannel {
|
||||||
|
fn from(id: Id) -> Self {
|
||||||
|
ToChannel::ById(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,20 +7,32 @@ net.ipv6.conf.all.forwarding = 1
|
|||||||
net.ipv4.ip_forward = 1
|
net.ipv4.ip_forward = 1
|
||||||
IP forwarding configured successfully.
|
IP forwarding configured successfully.
|
||||||
Creating Nym exit policy chain...
|
Creating Nym exit policy chain...
|
||||||
Creating chain NYM-EXIT...
|
Chain NYM-EXIT already exists. Flushing it...
|
||||||
Creating chain NYM-EXIT in ip6tables...
|
Chain NYM-EXIT already exists in ip6tables. Flushing it...
|
||||||
Linking NYM-EXIT to FORWARD chain...
|
NYM-EXIT all opt -- in * out nymwg 0.0.0.0/0 -> 0.0.0.0/0
|
||||||
Linking NYM-EXIT to IPv6 FORWARD chain...
|
NYM-EXIT all opt in * out nymwg ::/0 -> ::/0
|
||||||
Setting up NAT rules...
|
Setting up NAT rules...
|
||||||
|
MASQUERADE all opt -- in * out ens3 0.0.0.0/0 -> 0.0.0.0/0
|
||||||
IPv4 NAT rule already exists.
|
IPv4 NAT rule already exists.
|
||||||
|
MASQUERADE all opt in * out ens3 ::/0 -> ::/0
|
||||||
IPv6 NAT rule already exists.
|
IPv6 NAT rule already exists.
|
||||||
|
ACCEPT all opt -- in nymwg out ens3 0.0.0.0/0 -> 0.0.0.0/0
|
||||||
|
ACCEPT all opt -- in ens3 out nymwg 0.0.0.0/0 -> 0.0.0.0/0 state RELATED,ESTABLISHED
|
||||||
|
ACCEPT all opt in nymwg out ens3 ::/0 -> ::/0
|
||||||
|
ACCEPT all opt in ens3 out nymwg ::/0 -> ::/0 state RELATED,ESTABLISHED
|
||||||
Configuring DNS and ICMP rules...
|
Configuring DNS and ICMP rules...
|
||||||
Added IPv6 ICMP rule (allow ping6).
|
ACCEPT icmp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 icmptype 8
|
||||||
Added IPv6 DNS rule (UDP).
|
ACCEPT icmp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 icmptype 0
|
||||||
Added IPv6 DNS rule (TCP).
|
ACCEPT icmpv6 opt in * out * ::/0 -> ::/0
|
||||||
|
ACCEPT udp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 udp dpt:53
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:53
|
||||||
|
ACCEPT udp opt in * out * ::/0 -> ::/0 udp dpt:53
|
||||||
|
ACCEPT tcp opt in * out * ::/0 -> ::/0 tcp dpt:53
|
||||||
Applying Spamhaus blocklist...
|
Applying Spamhaus blocklist...
|
||||||
Downloading exit policy from https://nymtech.net/.wellknown/network-requester/exit-policy.txt
|
Downloading exit policy from https://nymtech.net/.wellknown/network-requester/exit-policy.txt
|
||||||
Processing 429 blocklist rules...
|
Processing 429 blocklist rules...
|
||||||
|
REJECT all opt -- in * out * 0.0.0.0/0 -> 205.189.71.0/24 reject-with icmp-port-unreachable
|
||||||
|
REJECT all opt -- in * out * 0.0.0.0/0 -> 205.189.72.0/23 reject-with icmp-port-unreachable
|
||||||
Blocklist applied successfully.
|
Blocklist applied successfully.
|
||||||
Applying allowed ports...
|
Applying allowed ports...
|
||||||
Adding rules for SILC (Port: 706)
|
Adding rules for SILC (Port: 706)
|
||||||
@@ -103,6 +115,11 @@ Adding rules for POP3OverTLS (Port: 995)
|
|||||||
Added: NYM-EXIT tcp port 995
|
Added: NYM-EXIT tcp port 995
|
||||||
Added: NYM-EXIT udp port 995
|
Added: NYM-EXIT udp port 995
|
||||||
Added: NYM-EXIT udp port 995
|
Added: NYM-EXIT udp port 995
|
||||||
|
Adding rules for DarkFiTor (Port: 25551)
|
||||||
|
Added: NYM-EXIT tcp port 25551
|
||||||
|
Added: NYM-EXIT tcp port 25551
|
||||||
|
Added: NYM-EXIT udp port 25551
|
||||||
|
Added: NYM-EXIT udp port 25551
|
||||||
Adding rules for MMCC (Port: 5050)
|
Adding rules for MMCC (Port: 5050)
|
||||||
Added: NYM-EXIT tcp port 5050
|
Added: NYM-EXIT tcp port 5050
|
||||||
Added: NYM-EXIT tcp port 5050
|
Added: NYM-EXIT tcp port 5050
|
||||||
@@ -268,6 +285,11 @@ Adding rules for Mumble (Port: 64738)
|
|||||||
Added: NYM-EXIT tcp port 64738
|
Added: NYM-EXIT tcp port 64738
|
||||||
Added: NYM-EXIT udp port 64738
|
Added: NYM-EXIT udp port 64738
|
||||||
Added: NYM-EXIT udp port 64738
|
Added: NYM-EXIT udp port 64738
|
||||||
|
Adding rules for DarkFi (Port: 26661)
|
||||||
|
Added: NYM-EXIT tcp port 26661
|
||||||
|
Added: NYM-EXIT tcp port 26661
|
||||||
|
Added: NYM-EXIT udp port 26661
|
||||||
|
Added: NYM-EXIT udp port 26661
|
||||||
Adding rules for PPTP (Port: 1723)
|
Adding rules for PPTP (Port: 1723)
|
||||||
Added: NYM-EXIT tcp port 1723
|
Added: NYM-EXIT tcp port 1723
|
||||||
Added: NYM-EXIT tcp port 1723
|
Added: NYM-EXIT tcp port 1723
|
||||||
@@ -333,6 +355,11 @@ Adding rules for Kpasswd (Port: 464)
|
|||||||
Added: NYM-EXIT tcp port 464
|
Added: NYM-EXIT tcp port 464
|
||||||
Added: NYM-EXIT udp port 464
|
Added: NYM-EXIT udp port 464
|
||||||
Added: NYM-EXIT udp port 464
|
Added: NYM-EXIT udp port 464
|
||||||
|
Adding rules for MoneroRPC (Port: 18089)
|
||||||
|
Added: NYM-EXIT tcp port 18089
|
||||||
|
Added: NYM-EXIT tcp port 18089
|
||||||
|
Added: NYM-EXIT udp port 18089
|
||||||
|
Added: NYM-EXIT udp port 18089
|
||||||
Adding rules for RemoteHTTPS (Port: 981)
|
Adding rules for RemoteHTTPS (Port: 981)
|
||||||
Added: NYM-EXIT tcp port 981
|
Added: NYM-EXIT tcp port 981
|
||||||
Added: NYM-EXIT tcp port 981
|
Added: NYM-EXIT tcp port 981
|
||||||
@@ -398,6 +425,11 @@ Adding rules for GroupWise (Port: 1677)
|
|||||||
Added: NYM-EXIT tcp port 1677
|
Added: NYM-EXIT tcp port 1677
|
||||||
Added: NYM-EXIT udp port 1677
|
Added: NYM-EXIT udp port 1677
|
||||||
Added: NYM-EXIT udp port 1677
|
Added: NYM-EXIT udp port 1677
|
||||||
|
Adding rules for Monero (Port: 18080-18081)
|
||||||
|
Added: NYM-EXIT tcp port range 18080:18081
|
||||||
|
Added: NYM-EXIT tcp port range 18080:18081
|
||||||
|
Added: NYM-EXIT udp port range 18080:18081
|
||||||
|
Added: NYM-EXIT udp port range 18080:18081
|
||||||
Adding rules for EnsimControlPanel (Port: 19638)
|
Adding rules for EnsimControlPanel (Port: 19638)
|
||||||
Added: NYM-EXIT tcp port 19638
|
Added: NYM-EXIT tcp port 19638
|
||||||
Added: NYM-EXIT tcp port 19638
|
Added: NYM-EXIT tcp port 19638
|
||||||
|
|||||||
+779
-791
File diff suppressed because it is too large
Load Diff
@@ -2,41 +2,61 @@
|
|||||||
Running Nym Exit Policy Verification Tests...
|
Running Nym Exit Policy Verification Tests...
|
||||||
Testing Port Range Rules...
|
Testing Port Range Rules...
|
||||||
Testing FTP tcp port range 20-21
|
Testing FTP tcp port range 20-21
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:20:21
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 20:21
|
✓ Rule exists: NYM-EXIT tcp port range 20:21
|
||||||
Testing HTTP tcp port range 80-81
|
Testing HTTP tcp port range 80-81
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:80:81
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 80:81
|
✓ Rule exists: NYM-EXIT tcp port range 80:81
|
||||||
Testing CPanel tcp port range 2082-2083
|
Testing CPanel tcp port range 2082-2083
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:2082:2083
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 2082:2083
|
✓ Rule exists: NYM-EXIT tcp port range 2082:2083
|
||||||
Testing XMPP tcp port range 5222-5223
|
Testing XMPP tcp port range 5222-5223
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:5222:5223
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 5222:5223
|
✓ Rule exists: NYM-EXIT tcp port range 5222:5223
|
||||||
Testing Steam (sampling) tcp port range 27000-27050
|
Testing Steam (sampling) tcp port range 27000-27050
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:27000:27050
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 27000:27050
|
✓ Rule exists: NYM-EXIT tcp port range 27000:27050
|
||||||
Testing FTP over TLS tcp port range 989-990
|
Testing FTP over TLS tcp port range 989-990
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:989:990
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 989:990
|
✓ Rule exists: NYM-EXIT tcp port range 989:990
|
||||||
Testing RTP/VoIP tcp port range 5000-5005
|
Testing RTP/VoIP tcp port range 5000-5005
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:5000:5005
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 5000:5005
|
✓ Rule exists: NYM-EXIT tcp port range 5000:5005
|
||||||
Testing Simplify Media tcp port range 8087-8088
|
Testing Simplify Media tcp port range 8087-8088
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:8087:8088
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 8087:8088
|
✓ Rule exists: NYM-EXIT tcp port range 8087:8088
|
||||||
Testing Zcash tcp port range 8232-8233
|
Testing Zcash tcp port range 8232-8233
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:8232:8233
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 8232:8233
|
✓ Rule exists: NYM-EXIT tcp port range 8232:8233
|
||||||
Testing Bitcoin tcp port range 8332-8333
|
Testing Bitcoin tcp port range 8332-8333
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:8332:8333
|
||||||
✓ Rule exists: NYM-EXIT tcp port range 8332:8333
|
✓ Rule exists: NYM-EXIT tcp port range 8332:8333
|
||||||
|
Testing Monero tcp port range 18080-18081
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpts:18080:18081
|
||||||
|
✓ Rule exists: NYM-EXIT tcp port range 18080:18081
|
||||||
Test test_port_range_rules PASSED
|
Test test_port_range_rules PASSED
|
||||||
Testing Critical Service Rules...
|
Testing Critical Service Rules...
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:22
|
||||||
✓ Rule exists: NYM-EXIT tcp port 22
|
✓ Rule exists: NYM-EXIT tcp port 22
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:53
|
||||||
✓ Rule exists: NYM-EXIT tcp port 53
|
✓ Rule exists: NYM-EXIT tcp port 53
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:443
|
||||||
✓ Rule exists: NYM-EXIT tcp port 443
|
✓ Rule exists: NYM-EXIT tcp port 443
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:853
|
||||||
✓ Rule exists: NYM-EXIT tcp port 853
|
✓ Rule exists: NYM-EXIT tcp port 853
|
||||||
|
ACCEPT tcp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 tcp dpt:1194
|
||||||
✓ Rule exists: NYM-EXIT tcp port 1194
|
✓ Rule exists: NYM-EXIT tcp port 1194
|
||||||
|
ACCEPT udp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 udp dpt:53
|
||||||
✓ Rule exists: NYM-EXIT udp port 53
|
✓ Rule exists: NYM-EXIT udp port 53
|
||||||
|
ACCEPT udp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 udp dpt:123
|
||||||
✓ Rule exists: NYM-EXIT udp port 123
|
✓ Rule exists: NYM-EXIT udp port 123
|
||||||
|
ACCEPT udp opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0 udp dpt:1194
|
||||||
✓ Rule exists: NYM-EXIT udp port 1194
|
✓ Rule exists: NYM-EXIT udp port 1194
|
||||||
Relevant existing rules for HTTP (port 80):
|
Relevant existing rules for HTTP (port 80):
|
||||||
Test test_critical_services PASSED
|
Test test_critical_services PASSED
|
||||||
This test takes some time, do not quit the process
|
This test takes some time, do not quit the process
|
||||||
|
|
||||||
Testing Default Reject Rule...
|
Testing Default Reject Rule...
|
||||||
|
|
||||||
✓ Default REJECT rule exists
|
✓ Default REJECT rule exists
|
||||||
Test test_default_reject_rule PASSED
|
Test test_default_reject_rule PASSED
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
0.80%
|
0.73%
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
35.841
|
39.437
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Tuesday, July 22nd 2025, 11:37:27 UTC
|
Wednesday, July 30th 2025, 09:32:50 UTC
|
||||||
@@ -1,21 +1,44 @@
|
|||||||
| **ISP** | **Locations** | **Public IPv6** | **Crypto Payments** | **Comments** | **Last Updated** |
|
| **ISP** | **Locations** | **Public IPv6** | **Crypto Payments** | **Comments** | **Last Updated** |
|
||||||
|:------------------------------------------------|:---------------------------------------------------------------------------------------------------------|:-------------------------------------|:---------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------|
|
|:---------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------|:---------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------|
|
||||||
| [AlexHost](https://alexhost.com) | Moldova, Bulgaria, Sweden, Netherlands | Yes, on by default | Yes | They allow TOR Bridges, Relays. Exit nodes are only allowed on dedicated servers (prices start from 26 EUR) | 07/2024 |
|
| [AlexHost](https://alexhost.com) | Moldova, Bulgaria, Sweden, Netherlands | Yes, on by default | Yes | They allow TOR Bridges, Relays. Exit nodes are only allowed on dedicated servers (prices start from 26 EUR) | 07/2024 |
|
||||||
| [BitLaunch](https://bitlaunch.io) | Canada, USA, UK | No | Yes | Expensive. Digial Ocean through BitLanch has IPv6 | 05/2024 |
|
| [AmeriNoc](https://www.amerinoc.com) | USA | Yes | nan | nan | 07/2025 |
|
||||||
| [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 |
|
| [BitLaunch](https://bitlaunch.io) | Canada, USA, UK | No | Yes | Expensive. Digial Ocean through BitLanch has IPv6 | 05/2024 |
|
||||||
| [Flokinet](https://flokinet.is) | Netherlands, Iceland, Romania,France | Yes, needs a ticket and custom setup | yes, including XMR | Very slow customer support | 05/2024 |
|
| [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 |
|
||||||
| [HostSailor](https://hostsailor.com) | USA | Yes, based on ticket | Yes | The IPv6 setup needs custom research and is not documented | 05/2024 |
|
| [Colocall](https://www.colocall.net/) | Ukraine | Yes | nan | 07/2025 | nan |
|
||||||
| [Hostiko](https://hostiko.com.ua) | Ukraine, Germany | Yes, on by default | Yes | Ukrainian provider. They allow Exit nodes on Germany boxes but limit the bandwidth, you also have to restrict certain ports like 25 and 587. Make sure you open a ticket. | 07/2024 |
|
| [DataPacket](https://www.datapacket.com/pricing) | NL, GR, SK, BE, RO, HU, DK, IE, DE, UA, PT, GB, ES, FR, IT, NO, CZ, BG, SE, AT, PL, HR, CH, USA, CO, AR, PE, MX, CL, TR, ZA, NG, IL, HK, AU, SG, JP | Yes | nan | nan | 07/2025 |
|
||||||
| [Hostinger](https://hostinger.com) | France, Lithuania, India, USA, Brazil | Yes, out of the box | Yes | Crypto payments must be done per each server monthly or annually. | 05/2024 |
|
| [Dataclub](https://www.dataclub.eu/) | Latvia, Sweden, Netherlands | Yes | nan | nan | 07/2027 |
|
||||||
| [Hostslick](https://hostslick.com) | Netherlands, Germany | Yes, on by default | Yes | Good amount of bandwidth for the price. Make sure you open the ticket if you want to run Exit node | 07/2024 |
|
| [Flokinet](https://flokinet.is) | Netherlands, Iceland, Romania,France | Yes, needs a ticket and custom setup | yes, including XMR | Very slow customer support | 05/2024 |
|
||||||
| [Incognet](https://incognet.io) | Netherlands and USA | Yes, on by default | Yes | They allow Tor exit nodes but you must adhere to their rules https://incognet.io/tor-exits | 07/2024 |
|
| [FranTech](https://my.frantech.ca) | USA | Yes | nan | nan | 07/2025 |
|
||||||
| [IsHosting](https://ishosting.com/en) | Brazil, Netherlands | Yes, based on ticket | Yes | Expensive | 05/2024 |
|
| [Fsit](https://www.fsit.com/server/vps-vserver-kvm) | Swiss | Yes | Yes | nan | 07/2025 |
|
||||||
| [Linode](https://linode.com) | USA, Canada, Japan, India, Indonesia, Sweden, Netherlands, Germany, Brazil, France, UK, Australia, Italy | Yes out of the box | No, only through [BitLAunch](https://bitlaunch.io) | IPv6 sometimes need to be re-added in Networking tab, no reboot needed | 05/2024 |
|
| [HostSailor](https://hostsailor.com) | USA | Yes, based on ticket | Yes | The IPv6 setup needs custom research and is not documented | 05/2024 |
|
||||||
| [LiteServer](https://liteserver.nl) | Netherlands | Yes, on by default | Yes | Very reliable Dutch provider. They do allow Relay nodes but for Exit nodes you need to contact them. Always check T&C https://liteserver.nl/legal | 07/2024 |
|
| [Hostiko](https://hostiko.com.ua) | Ukraine, Germany | Yes, on by default | Yes | Ukrainian provider. They allow Exit nodes on Germany boxes but limit the bandwidth, you also have to restrict certain ports like 25 and 587. Make sure you open a ticket. | 07/2024 |
|
||||||
| [Mevspace](https://mevspace.com) | Poland | Yes, on by default | Yes | Flexible Polish providers with 3 DCs in Poland. They do allow Tor Exit nodes but you may need a dedicated server for this. Make sure you open a ticket to check. As of today's date, they have 48h for 1 EUR tariff | 07/2024 |
|
| [Hostinger](https://hostinger.com) | France, Lithuania, India, USA, Brazil | Yes, out of the box | Yes | Not fast enough, Crypto payments must be done per each server monthly or annually. | 07/2025 |
|
||||||
| [Misaka](https://www.misaka.io/) | South Africa | Yes, native support | No | Very Expensive | 05/2024 |
|
| [Hostroyale](https://hostroyale.com/hosting/dedicated-server/) | Various countries with different pricing | nan | Yes | nan | 07/2025 |
|
||||||
| [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 |
|
| [Hostslick](https://hostslick.com) | Netherlands, Germany | Yes, on by default | Yes | Good amount of bandwidth for the price. Make sure you open the ticket if you want to run Exit node | 07/2024 |
|
||||||
| [RDP](https://rdp.sh) | Netherlands, USA, Poland | Yes, on by default | Yes | German provider. Exit nodes are allowed, policy is here https://rdp.sh/docs/faq/tor ports 25,465,587 must be closed. Make sure you open a ticket before running an exit node. | 07/2024 |
|
| [Incognet](https://incognet.io) | Netherlands and USA | Yes, on by default | Yes | They allow Tor exit nodes but you must adhere to their rules https://incognet.io/tor-exits | 07/2024 |
|
||||||
| [TerraHost](https://terrahost.no) | Norway | Yes, on by default | Yes | Very reliable Norwegian provider. Only allow exit nodes on Dedicated servers subject to certain caveats (you must open a ticket). Always check T&C https://terrahost.no/avtalebetingelser | 07/2024 |
|
| [Incognet](https://incognet.io/kansas-city-dedicated-servers) | USA, Netherlands | Yes | nan | nan | 07/2025 |
|
||||||
| [iHostArt](https://ihostart.com) | Romania | Yes, on by default | Yes | Super permissive provider. They do allow Tor Exit/Relay/Bridge. Pro-free speech etc. Recently, IPv6 geolocation was set to North Korea, so be aware. | 07/2024 |
|
| [Ionos](https://www.ionos.com/servers/amd-servers) | US, DE, UK, ESP, FR | nan | No | nan | 07/2025 |
|
||||||
| [vSys Host](https://vsys.host) | Ukraine, Netherlands, USA | Yes, on by default | Yes | Pretty permissive provider registered in Ukraine. Should allow Relay/Exit nodes but nothing in T&C, so better double check. | 07/2024 |
|
| [IsHosting](https://ishosting.com/en) | Brazil, Netherlands | Yes, based on ticket | Yes | Expensive | 05/2024 |
|
||||||
|
| [Leaseweb](https://www.leaseweb.com/en/configure/vc/product/entityKey/DEDSER02_NEW_ORDER_BUSINESS_R740XD-24SFF-6134) | US, NL, DE, UK, CA, SG, JP, AUS, HK | nan | No | KYC mandatory | 07/2025 |
|
||||||
|
| [Linode](https://linode.com) | USA, Canada, Japan, India, Indonesia, Sweden, Netherlands, Germany, Brazil, France, UK, Australia, Italy | Yes out of the box | No, only through [BitLAunch](https://bitlaunch.io) | IPv6 sometimes need to be re-added in Networking tab, no reboot needed | 05/2024 |
|
||||||
|
| [LiteServer](https://liteserver.nl) | Netherlands | Yes, on by default | Yes | Very reliable Dutch provider. They do allow Relay nodes but for Exit nodes you need to contact them. Always check T&C https://liteserver.nl/legal | 07/2024 |
|
||||||
|
| [Lowendbox](https://lowendbox.com/category/dedicated-servers) | | | | Just an aggregator with good offers | 07/2025 |
|
||||||
|
| [M247](https://m247.com/eu/services/host/dedicated-servers/) | UK, Austria, Br, Sw, Jp, Poland, Fr, USA, Netherlands | Yes | No | nan | 07/2025 |
|
||||||
|
| [Mebilcom](https://www.melbicom.net/dedicatedserver/) | NL, US, DE, UAE, NG, ESP, IN, IT, FR, LT, SG, BG, LV, PL | nan | No | nan | 07/2025 |
|
||||||
|
| [Mevspace](https://mevspace.com) | Poland | Yes, on by default | Yes | Flexible Polish providers with 3 DCs in Poland. They do allow Tor Exit nodes but you may need a dedicated server for this. Make sure you open a ticket to check. As of today's date, they have 48h for 1 EUR tariff | 07/2024 |
|
||||||
|
| [Misaka](https://www.misaka.io/) | South Africa | Yes, native support | No | Very Expensive | 05/2024 |
|
||||||
|
| [NiceVPS](https://nicevps.net/) | Netherlands | Yes | nan | nan | 07/2025 |
|
||||||
|
| [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 |
|
||||||
|
| [OVH](https://us.ovhcloud.com/bare-metal/rise/rise-3/) | USA, DE, FR, UK, PL, CA | | No | Not all locations always available | 07/2025 |
|
||||||
|
| [Oneprovider](https://oneprovider.com/en/dedicated-servers/ipv6) | PL, FR, NL, UA, US, BG, RO, DK, ESP, NO, CZ, RS, IE, IT, UK, HU, CH, SK, AT, BE, BA, HK, JP, SG, LU, AU, SWE, UAE, BR, CR, MX, GR, CL, MA, AR | Yes | No | nan | 07/2025 |
|
||||||
|
| [PrivateLayer](https://privatelayer.com) | Swiss | Yes | Yes | Slow customer response | 07/2025 |
|
||||||
|
| [Privex](https://www.privex.io/tor-exit-policy/) | USA, Germany, Sweden | Yes | Yes | nan | 07/2025 |
|
||||||
|
| [Psychz](https://www.psychz.net) | US, UK, Brazil, Japan, Russia, South Africa and many more | Yes | nan | nan | 07/2025 |
|
||||||
|
| [RDP](https://rdp.sh) | Netherlands, USA, Poland | Yes, on by default | Yes | German provider. Exit nodes are allowed, policy is here https://rdp.sh/docs/faq/tor ports 25,465,587 must be closed. Make sure you open a ticket before running an exit node. | 07/2024 |
|
||||||
|
| [Servermania](https://www.servermania.com/dedicated-servers-hosting.htm) | USA, Canada | nan | No | nan | 07/2025 |
|
||||||
|
| [Svea](https://svea.net/vps) | Sweden | Yes | nan | nan | 07/2025 |
|
||||||
|
| [TerraHost](https://terrahost.no) | Norway | Yes, on by default | Yes | Very reliable Norwegian provider. Only allow exit nodes on Dedicated servers subject to certain caveats (you must open a ticket). Always check T&C https://terrahost.no/avtalebetingelser | 07/2024 |
|
||||||
|
| [Thundervm](https://thundervm.com/en/hosting/dedicated-server) | USA, UK, France, Italy, Switzerland, Netherlands | nan | Yes | | 07/2025 |
|
||||||
|
| [Zenlayer](https://www.zenlayer.com/bare-metal/) | [advertised over 50 locations](50+ https://www.zenlayer.com/global-network) | nan | nan | nan | 07/2025 |
|
||||||
|
| [iHostArt](https://ihostart.com) | Romania | Yes, on by default | Yes | Super permissive provider. They do allow Tor Exit/Relay/Bridge. Pro-free speech etc. Recently, IPv6 geolocation was set to North Korea, so be aware. | 07/2024 |
|
||||||
|
| [vSys Host](https://vsys.host) | Ukraine, Netherlands, USA | Yes, on by default | Yes | Pretty permissive provider registered in Ukraine. Should allow Relay/Exit nodes but nothing in T&C, so better double check. | 07/2024 |
|
||||||
|
|||||||
@@ -1,26 +1,43 @@
|
|||||||
**ISP**,**Locations**,**Public IPv6**,**Crypto Payments**,**Comments**,**Last Updated**
|
**ISP**,**Locations**,**Public IPv6**,**Crypto Payments**,**Comments**,**Last Updated**
|
||||||
[Flokinet](https://flokinet.is),"Netherlands, Iceland, Romania,France","Yes, needs a ticket and custom setup","yes, including XMR","Very slow customer support","05/2024"
|
[Flokinet](https://flokinet.is),"Netherlands, Iceland, Romania,France","Yes, needs a ticket and custom setup","yes, including XMR",Very slow customer support,05/2024
|
||||||
[BitLaunch](https://bitlaunch.io),"Canada, USA, UK","No","Yes","Expensive. Digial Ocean through BitLanch has IPv6","05/2024"
|
[BitLaunch](https://bitlaunch.io),"Canada, USA, UK",No,Yes,Expensive. Digial Ocean through BitLanch has IPv6,05/2024
|
||||||
[Hostinger](https://hostinger.com),"France, Lithuania, India, USA, Brazil","Yes, out of the box","Yes","Crypto payments must be done per each server monthly or annually.","05/2024"
|
[Hostinger](https://hostinger.com),"France, Lithuania, India, USA, Brazil","Yes, out of the box",Yes,"Not fast enough, Crypto payments must be done per each server monthly or annually.",07/2025
|
||||||
[Linode](https://linode.com),"USA, Canada, Japan, India, Indonesia, Sweden, Netherlands, Germany, Brazil, France, UK, Australia, Italy","Yes out of the box","No, only through [BitLAunch](https://bitlaunch.io)","IPv6 sometimes need to be re-added in Networking tab, no reboot needed","05/2024"
|
[Linode](https://linode.com),"USA, Canada, Japan, India, Indonesia, Sweden, Netherlands, Germany, Brazil, France, UK, Australia, Italy",Yes out of the box,"No, only through [BitLAunch](https://bitlaunch.io)","IPv6 sometimes need to be re-added in Networking tab, no reboot needed",05/2024
|
||||||
[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"
|
[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
|
||||||
[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"
|
[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"
|
[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"
|
[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"
|
[IsHosting](https://ishosting.com/en),"Brazil, Netherlands","Yes, based on ticket",Yes,Expensive,05/2024
|
||||||
[AlexHost](https://alexhost.com),"Moldova, Bulgaria, Sweden, Netherlands","Yes, on by default","Yes","They allow TOR Bridges, Relays. Exit nodes are only allowed on dedicated servers (prices start from 26 EUR)","07/2024"
|
[AlexHost](https://alexhost.com),"Moldova, Bulgaria, Sweden, Netherlands","Yes, on by default",Yes,"They allow TOR Bridges, Relays. Exit nodes are only allowed on dedicated servers (prices start from 26 EUR)",07/2024
|
||||||
[iHostArt](https://ihostart.com),"Romania","Yes, on by default","Yes","Super permissive provider. They do allow Tor Exit/Relay/Bridge. Pro-free speech etc. Recently, IPv6 geolocation was set to North Korea, so be aware.","07/2024"
|
[iHostArt](https://ihostart.com),Romania,"Yes, on by default",Yes,"Super permissive provider. They do allow Tor Exit/Relay/Bridge. Pro-free speech etc. Recently, IPv6 geolocation was set to North Korea, so be aware.",07/2024
|
||||||
[Incognet](https://incognet.io),"Netherlands and USA","Yes, on by default","Yes","They allow Tor exit nodes but you must adhere to their rules https://incognet.io/tor-exits","07/2024"
|
[Incognet](https://incognet.io),Netherlands and USA,"Yes, on by default",Yes,They allow Tor exit nodes but you must adhere to their rules https://incognet.io/tor-exits,07/2024
|
||||||
[vSys Host](https://vsys.host),"Ukraine, Netherlands, USA","Yes, on by default","Yes","Pretty permissive provider registered in Ukraine. Should allow Relay/Exit nodes but nothing in T&C, so better double check.","07/2024"
|
[vSys Host](https://vsys.host),"Ukraine, Netherlands, USA","Yes, on by default",Yes,"Pretty permissive provider registered in Ukraine. Should allow Relay/Exit nodes but nothing in T&C, so better double check.",07/2024
|
||||||
[LiteServer](https://liteserver.nl),"Netherlands","Yes, on by default","Yes","Very reliable Dutch provider. They do allow Relay nodes but for Exit nodes you need to contact them. Always check T&C https://liteserver.nl/legal","07/2024"
|
[LiteServer](https://liteserver.nl),Netherlands,"Yes, on by default",Yes,Very reliable Dutch provider. They do allow Relay nodes but for Exit nodes you need to contact them. Always check T&C https://liteserver.nl/legal,07/2024
|
||||||
[TerraHost](https://terrahost.no),"Norway","Yes, on by default","Yes","Very reliable Norwegian provider. Only allow exit nodes on Dedicated servers subject to certain caveats (you must open a ticket). Always check T&C https://terrahost.no/avtalebetingelser","07/2024"
|
[TerraHost](https://terrahost.no),Norway,"Yes, on by default",Yes,Very reliable Norwegian provider. Only allow exit nodes on Dedicated servers subject to certain caveats (you must open a ticket). Always check T&C https://terrahost.no/avtalebetingelser,07/2024
|
||||||
[Mevspace](https://mevspace.com),"Poland","Yes, on by default","Yes","Flexible Polish providers with 3 DCs in Poland. They do allow Tor Exit nodes but you may need a dedicated server for this. Make sure you open a ticket to check. As of today's date, they have 48h for 1 EUR tariff","07/2024"
|
[Mevspace](https://mevspace.com),Poland,"Yes, on by default",Yes,"Flexible Polish providers with 3 DCs in Poland. They do allow Tor Exit nodes but you may need a dedicated server for this. Make sure you open a ticket to check. As of today's date, they have 48h for 1 EUR tariff",07/2024
|
||||||
[Hostiko](https://hostiko.com.ua),"Ukraine, Germany","Yes, on by default","Yes","Ukrainian provider. They allow Exit nodes on Germany boxes but limit the bandwidth, you also have to restrict certain ports like 25 and 587. Make sure you open a ticket.","07/2024"
|
[Hostiko](https://hostiko.com.ua),"Ukraine, Germany","Yes, on by default",Yes,"Ukrainian provider. They allow Exit nodes on Germany boxes but limit the bandwidth, you also have to restrict certain ports like 25 and 587. Make sure you open a ticket.",07/2024
|
||||||
[Hostslick](https://hostslick.com),"Netherlands, Germany","Yes, on by default","Yes","Good amount of bandwidth for the price. Make sure you open the ticket if you want to run Exit node","07/2024"
|
[Hostslick](https://hostslick.com),"Netherlands, Germany","Yes, on by default",Yes,Good amount of bandwidth for the price. Make sure you open the ticket if you want to run Exit node,07/2024
|
||||||
[RDP](https://rdp.sh),"Netherlands, USA, Poland","Yes, on by default","Yes","German provider. Exit nodes are allowed, policy is here https://rdp.sh/docs/faq/tor ports 25,465,587 must be closed. Make sure you open a ticket before running an exit node.","07/2024"
|
[RDP](https://rdp.sh),"Netherlands, USA, Poland","Yes, on by default",Yes,"German provider. Exit nodes are allowed, policy is here https://rdp.sh/docs/faq/tor ports 25,465,587 must be closed. Make sure you open a ticket before running an exit node.",07/2024
|
||||||
|
[Lowendbox](https://lowendbox.com/category/dedicated-servers), , , ,Just an aggregator with good offers,07/2025
|
||||||
|
[Thundervm](https://thundervm.com/en/hosting/dedicated-server),"USA, UK, France, Italy, Switzerland, Netherlands",,Yes, ,07/2025
|
||||||
|
[OVH](https://us.ovhcloud.com/bare-metal/rise/rise-3/),"USA, DE, FR, UK, PL, CA", ,No,Not all locations always available,07/2025
|
||||||
|
[Mebilcom](https://www.melbicom.net/dedicatedserver/),"NL, US, DE, UAE, NG, ESP, IN, IT, FR, LT, SG, BG, LV, PL",,No,,07/2025
|
||||||
|
[Servermania](https://www.servermania.com/dedicated-servers-hosting.htm),"USA, Canada",,No,,07/2025
|
||||||
|
[Oneprovider](https://oneprovider.com/en/dedicated-servers/ipv6),"PL, FR, NL, UA, US, BG, RO, DK, ESP, NO, CZ, RS, IE, IT, UK, HU, CH, SK, AT, BE, BA, HK, JP, SG, LU, AU, SWE, UAE, BR, CR, MX, GR, CL, MA, AR",Yes,No,,07/2025
|
||||||
|
[Ionos](https://www.ionos.com/servers/amd-servers),"US, DE, UK, ESP, FR",,No,,07/2025
|
||||||
|
[Leaseweb](https://www.leaseweb.com/en/configure/vc/product/entityKey/DEDSER02_NEW_ORDER_BUSINESS_R740XD-24SFF-6134),"US, NL, DE, UK, CA, SG, JP, AUS, HK",,No,KYC mandatory,07/2025
|
||||||
|
[M247](https://m247.com/eu/services/host/dedicated-servers/),"UK, Austria, Br, Sw, Jp, Poland, Fr, USA, Netherlands",Yes,No,,07/2025
|
||||||
|
[Hostroyale](https://hostroyale.com/hosting/dedicated-server/),Various countries with different pricing,, Yes,,07/2025
|
||||||
|
[DataPacket](https://www.datapacket.com/pricing),"NL, GR, SK, BE, RO, HU, DK, IE, DE, UA, PT, GB, ES, FR, IT, NO, CZ, BG, SE, AT, PL, HR, CH, USA, CO, AR, PE, MX, CL, TR, ZA, NG, IL, HK, AU, SG, JP",Yes,,,07/2025
|
||||||
|
[Zenlayer](https://www.zenlayer.com/bare-metal/), [advertised over 50 locations](50+ https://www.zenlayer.com/global-network),,,,07/2025
|
||||||
|
[PrivateLayer](https://privatelayer.com),Swiss,Yes,Yes,Slow customer response,07/2025
|
||||||
|
[AmeriNoc](https://www.amerinoc.com),USA,Yes,,,07/2025
|
||||||
|
[Colocall](https://www.colocall.net/),Ukraine,Yes,,07/2025,
|
||||||
|
[Incognet](https://incognet.io/kansas-city-dedicated-servers),"USA, Netherlands",Yes,,,07/2025
|
||||||
|
[FranTech](https://my.frantech.ca),USA,Yes,,,07/2025
|
||||||
|
[Psychz](https://www.psychz.net),"US, UK, Brazil, Japan, Russia, South Africa and many more",Yes,,,07/2025
|
||||||
|
[Fsit](https://www.fsit.com/server/vps-vserver-kvm),Swiss,Yes,Yes,,07/2025
|
||||||
|
[NiceVPS](https://nicevps.net/),Netherlands,Yes,,,07/2025
|
||||||
|
[Dataclub](https://www.dataclub.eu/),"Latvia, Sweden, Netherlands",Yes,,,07/2027
|
||||||
|
[Privex](https://www.privex.io/tor-exit-policy/),"USA, Germany, Sweden",Yes,Yes,,07/2025
|
||||||
|
[Svea](https://svea.net/vps),Sweden,Yes,,,07/2025
|
||||||
|
|||||||
|
@@ -24,25 +24,23 @@ Write a message to your provider telling them about your intention to run a `nym
|
|||||||
</AccordionTemplate>
|
</AccordionTemplate>
|
||||||
|
|
||||||
#### Join Operators Legal Forum
|
#### Join Operators Legal Forum
|
||||||
This [Matrix channel]((https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org&via=matrix.su4ka.icu)) is the best place to ask questions and share your experience with others. You can share screen prints of abuse reports and ask for support.
|
This [Matrix channel]((https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org&via=matrix.su4ka.icu)) is the best place to ask questions and share your experience with others. You can share screen prints of abuse reports and ask for support.
|
||||||
|
|
||||||
#### Join Operators Legal Clinic
|
#### Join Operators Legal Clinic
|
||||||
Do you have any questions directed for lawyers? Come and chat with Nym COO Alexis Roussel, every Wednesday 14:30 UTC for 60min in our [Operator Legal Forum channel on Matrix](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org&via=matrix.su4ka.icu).
|
Do you have any questions directed for lawyers? Come and chat with Nym COO Alexis Roussel, every Wednesday 14:30 UTC for 60min in our [Operator Legal Forum channel on Matrix](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org&via=matrix.su4ka.icu).
|
||||||
|
|
||||||
#### Use a friendly provider
|
#### Use a friendly provider
|
||||||
Nym operators community shares their experience with different ISPs on [this page](isp-list). At the same time, consider to move away from these provides:
|
Nym operators community shares their experience with different ISPs on [this page](isp-list). At the same time, consider to move away from these provides:
|
||||||
|
|
||||||
- Servinga / VPS2day (AS39378)
|
- Servinga / VPS2day (AS39378)
|
||||||
- Frantech / Ponynet / BuyVM (AS53667)
|
- Frantech / Ponynet / BuyVM (AS53667)
|
||||||
- OVH SAS / OVHcloud (AS16276)
|
|
||||||
- Online S.A.S. / Scaleway (AS12876)
|
- Online S.A.S. / Scaleway (AS12876)
|
||||||
- Hetzner Online GmbH (AS24940)
|
- Hetzner Online GmbH (AS24940)
|
||||||
- IONOS SE (AS8560)
|
|
||||||
- Psychz Networks (AS40676)
|
|
||||||
- 1337 Services GmbH / RDP.sh (AS210558)
|
- 1337 Services GmbH / RDP.sh (AS210558)
|
||||||
|
- Stark Industries Solutions Ltd. / PQ.Hosting / The.Hosting / UFO-AS (AS44477 / ASN 33993)
|
||||||
|
|
||||||
#### Backup your nodes
|
#### Backup your nodes
|
||||||
Your only way to restore your node is when you have an access to `.nym` directory locally. Follow [node](../nodes/maintenance#backup-a-node) and [proxy configuration](../nodes/maintenance#backup-proxy-configuration) backup guides to be able to [restore your node](../nodes/maintenance#restoring-a-node) on another machine later on, without losing your delegation.
|
Your only way to restore your node is when you have an access to `.nym` directory locally. Follow [node](../nodes/maintenance#backup-a-node) and [proxy configuration](../nodes/maintenance#backup-proxy-configuration) backup guides to be able to [restore your node](../nodes/maintenance#restoring-a-node) on another machine later on, without losing your delegation.
|
||||||
|
|
||||||
#### Use `nym-exit` prefix on your landing page URL
|
#### Use `nym-exit` prefix on your landing page URL
|
||||||
We would like to ask operators to use [reverse proxy](../nodes/nym-node/configuration/proxy-configuration) with a [landing page](landing-pages). When assigning a domain please use a common convention with `nym-exit` in the beginning of the the page URL as this will create a reputation and reference. The entire address should have this new format:
|
We would like to ask operators to use [reverse proxy](../nodes/nym-node/configuration/proxy-configuration) with a [landing page](landing-pages). When assigning a domain please use a common convention with `nym-exit` in the beginning of the the page URL as this will create a reputation and reference. The entire address should have this new format:
|
||||||
@@ -69,10 +67,10 @@ nym-exit.mysquad.org
|
|||||||
**The `NYM-EXIT` part in the beginning is what's important.**
|
**The `NYM-EXIT` part in the beginning is what's important.**
|
||||||
|
|
||||||
#### Chose the right TLD
|
#### Chose the right TLD
|
||||||
When registering a domain, check [Top Level Domain (TLD)](https://www.techopedia.com/definition/1348/top-level-domain-tld) terms and conditions. For example `.icu` is a no go. Having a wrong TLD may lead to your domain being taken away from you when facing a DMCA report.
|
When registering a domain, check [Top Level Domain (TLD)](https://www.techopedia.com/definition/1348/top-level-domain-tld) terms and conditions. For example `.icu` is a no go. Having a wrong TLD may lead to your domain being taken away from you when facing a DMCA report.
|
||||||
|
|
||||||
#### Respond to abuse reports
|
#### Respond to abuse reports
|
||||||
Make sure to read notifications from your account provider and if you receive an abuse report, respond to it in time. Here is a template explaining the essential legal background of Nym Node Exit Gateway. Don't forget to adjust the variables.
|
Make sure to read notifications from your account provider and if you receive an abuse report, respond to it in time. Here is a template explaining the essential legal background of Nym Node Exit Gateway. Don't forget to adjust the variables.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<AccordionTemplate name="Email template: responding to DMCA take-down notices">
|
<AccordionTemplate name="Email template: responding to DMCA take-down notices">
|
||||||
@@ -81,4 +79,3 @@ Make sure to read notifications from your account provider and if you receive an
|
|||||||
|
|
||||||
#### Help us to improve these pages
|
#### Help us to improve these pages
|
||||||
Add your findings by opening a [Pull Request](add-content).
|
Add your findings by opening a [Pull Request](add-content).
|
||||||
|
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ The exit policy is same for all NRs, the content is shaped by an offchain govern
|
|||||||
|
|
||||||
There is a caveat though. NR is only routing TCP streams and therefore any other type of routing is *not* filtered thorugh the exit policy. To ensure that Nym Nodes follow the same exit policy when routing IP packets through wireguard and don't act as open proxies, the operators have to set up these rules via IP tables rules.
|
There is a caveat though. NR is only routing TCP streams and therefore any other type of routing is *not* filtered thorugh the exit policy. To ensure that Nym Nodes follow the same exit policy when routing IP packets through wireguard and don't act as open proxies, the operators have to set up these rules via IP tables rules.
|
||||||
|
|
||||||
**Follow these steps, using a [setup script]i(https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/wireguard-exit-policy/wireguard-exit-policy-manager.sh) and [testing scripts](https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/wireguard-exit-policy/exit-policy-tests.sh) written by Nym quality assurance team, to setup exit policy for wireguard:**
|
**Follow these steps, using a [setup script](https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/wireguard-exit-policy/wireguard-exit-policy-manager.sh) and [testing scripts](https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/wireguard-exit-policy/exit-policy-tests.sh) written by Nym quality assurance team, to setup exit policy for wireguard:**
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import { AccordionTemplate } from 'components/accordion-template.tsx';
|
|||||||
|
|
||||||
> Nym has two main codebases:
|
> Nym has two main codebases:
|
||||||
> - the [Nym platform](https://github.com/nymtech/nym), written in Rust. This contains all of our code except for the validators.
|
> - the [Nym platform](https://github.com/nymtech/nym), written in Rust. This contains all of our code except for the validators.
|
||||||
> - the [Nym validators](https://github.com/nymtech/nyxd), written in Go & maintained as a no-modification fork of [wasmd](https://github.com/CosmWasm/wasmd)
|
> - the [Nym validators](https://github.com/nymtech/nyxd), written in Go & maintained as fork of [wasmd](https://github.com/CosmWasm/wasmd)
|
||||||
|
|
||||||
The validator is a Go application which implements it's functionalities using [Cosmos SDK](https://v1.cosmos.network/sdk). The underlying state-replication engine is powered by [CometBFT](https://cometbft.com/), where the consensus mechanism is based on the [Tendermint Consensus Algorithm](https://arxiv.org/abs/1807.04938). Finally, a [CosmWasm](https://cosmwasm.com) smart contract module controls crucial mixnet functionalities like decentralised directory service, node bonding, and delegated mixnet staking.
|
The validator is a Go application which implements it's functionalities using [Cosmos SDK](https://v1.cosmos.network/sdk). The underlying state-replication engine is powered by [CometBFT](https://cometbft.com/), where the consensus mechanism is based on the [Tendermint Consensus Algorithm](https://arxiv.org/abs/1807.04938). Finally, a [CosmWasm](https://cosmwasm.com) smart contract module controls crucial mixnet functionalities like decentralised directory service, node bonding, and delegated mixnet staking.
|
||||||
|
|
||||||
<Callout type="info" emoji="ℹ️">
|
<Callout type="info" emoji="ℹ️">
|
||||||
We are currently running mainnet with a closed set of reputable validators. To ensure decentralisation of Nyx chain, we are working on a mechanism to onboard new validators to the network. To join the waitlist, please drop an email to `validators [at] nymtech.net` with details of your setup, experience and any other relevent information
|
At present, our mainnet operates with a select group of reputed validators. We are not accepting new validators at this time. Any updates or changes to this policy will be promptly announced.
|
||||||
</Callout>
|
</Callout>
|
||||||
|
|
||||||
## Building your validator
|
## Building your validator
|
||||||
@@ -52,7 +52,7 @@ pacman -S git gcc jq
|
|||||||
- First remove any existing old Go installation and extract the archive you just downloaded into /usr/local:
|
- First remove any existing old Go installation and extract the archive you just downloaded into /usr/local:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.10.linux-amd64.tar.gz
|
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.11.linux-amd64.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
- Then add /usr/local/go/bin to the PATH environment variable
|
- Then add /usr/local/go/bin to the PATH environment variable
|
||||||
@@ -69,14 +69,14 @@ go version
|
|||||||
|
|
||||||
- Should return something like:
|
- Should return something like:
|
||||||
```sh
|
```sh
|
||||||
go version go1.20.10 linux/amd64
|
go version go1.23.11 linux/amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
### Download a precompiled validator binary
|
### Download a precompiled validator binary
|
||||||
|
|
||||||
You can find pre-compiled binaries for Ubuntu `22.04` and `20.04` [here](https://github.com/nymtech/nyxd/releases).
|
You can find pre-compiled binaries for Ubuntu `22.04` and `24.04` [here](https://github.com/nymtech/nyxd/releases).
|
||||||
|
|
||||||
### Manually compiling your validator binary
|
### Manually compiling your validator binary
|
||||||
|
|
||||||
@@ -109,8 +109,9 @@ Usage:
|
|||||||
nyxd [command]
|
nyxd [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
|
comet CometBFT subcommands
|
||||||
completion Generate the autocompletion script for the specified shell
|
completion Generate the autocompletion script for the specified shell
|
||||||
config Create or query an application CLI configuration file
|
config Utilities for managing application configuration
|
||||||
debug Tool for helping with debugging your application
|
debug Tool for helping with debugging your application
|
||||||
export Export state to JSON
|
export Export state to JSON
|
||||||
genesis Application's genesis-related subcommands
|
genesis Application's genesis-related subcommands
|
||||||
@@ -119,20 +120,20 @@ Available Commands:
|
|||||||
keys Manage your application's keys
|
keys Manage your application's keys
|
||||||
prune Prune app history states by keeping the recent heights and deleting old heights
|
prune Prune app history states by keeping the recent heights and deleting old heights
|
||||||
query Querying subcommands
|
query Querying subcommands
|
||||||
rollback rollback cosmos-sdk and tendermint state by one height
|
rollback rollback Cosmos SDK and CometBFT state by one height
|
||||||
rosetta spin up a rosetta server
|
snapshots Manage local snapshots
|
||||||
start Run the full node
|
start Run the full node
|
||||||
status Query remote node for status
|
status Query remote node for status
|
||||||
tendermint Tendermint subcommands
|
|
||||||
testnet subcommands for starting or configuring local testnets
|
testnet subcommands for starting or configuring local testnets
|
||||||
tx Transactions subcommands
|
tx Transactions subcommands
|
||||||
version Print the application binary version information
|
version Print the application binary version information
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for nyxd
|
-h, --help help for nyxd
|
||||||
--home string directory for config and data
|
--home string directory for config and data (default "/Users/neo/.nyxd")
|
||||||
--log_format string The logging format (json|plain) (default "plain")
|
--log_format string The logging format (json|plain) (default "plain")
|
||||||
--log_level string The logging level (trace|debug|info|warn|error|fatal|panic) (default "info")
|
--log_level string The logging level (trace|debug|info|warn|error|fatal|panic|disabled or '*:<level>,<key>:<level>') (default "info")
|
||||||
|
--log_no_color Disable colored logs
|
||||||
--trace print out full stack trace on errors
|
--trace print out full stack trace on errors
|
||||||
|
|
||||||
Use "nyxd [command] --help" for more information about a command.
|
Use "nyxd [command] --help" for more information about a command.
|
||||||
@@ -180,8 +181,9 @@ Usage:
|
|||||||
nyxd [command]
|
nyxd [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
|
comet CometBFT subcommands
|
||||||
completion Generate the autocompletion script for the specified shell
|
completion Generate the autocompletion script for the specified shell
|
||||||
config Create or query an application CLI configuration file
|
config Utilities for managing application configuration
|
||||||
debug Tool for helping with debugging your application
|
debug Tool for helping with debugging your application
|
||||||
export Export state to JSON
|
export Export state to JSON
|
||||||
genesis Application's genesis-related subcommands
|
genesis Application's genesis-related subcommands
|
||||||
@@ -190,20 +192,20 @@ Available Commands:
|
|||||||
keys Manage your application's keys
|
keys Manage your application's keys
|
||||||
prune Prune app history states by keeping the recent heights and deleting old heights
|
prune Prune app history states by keeping the recent heights and deleting old heights
|
||||||
query Querying subcommands
|
query Querying subcommands
|
||||||
rollback rollback cosmos-sdk and tendermint state by one height
|
rollback rollback Cosmos SDK and CometBFT state by one height
|
||||||
rosetta spin up a rosetta server
|
snapshots Manage local snapshots
|
||||||
start Run the full node
|
start Run the full node
|
||||||
status Query remote node for status
|
status Query remote node for status
|
||||||
tendermint Tendermint subcommands
|
|
||||||
testnet subcommands for starting or configuring local testnets
|
testnet subcommands for starting or configuring local testnets
|
||||||
tx Transactions subcommands
|
tx Transactions subcommands
|
||||||
version Print the application binary version information
|
version Print the application binary version information
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for nyxd
|
-h, --help help for nyxd
|
||||||
--home string directory for config and data
|
--home string directory for config and data (default "/Users/neo/.nyxd")
|
||||||
--log_format string The logging format (json|plain) (default "plain")
|
--log_format string The logging format (json|plain) (default "plain")
|
||||||
--log_level string The logging level (trace|debug|info|warn|error|fatal|panic) (default "info")
|
--log_level string The logging level (trace|debug|info|warn|error|fatal|panic|disabled or '*:<level>,<key>:<level>') (default "info")
|
||||||
|
--log_no_color Disable colored logs
|
||||||
--trace print out full stack trace on errors
|
--trace print out full stack trace on errors
|
||||||
|
|
||||||
Use "nyxd [command] --help" for more information about a command.
|
Use "nyxd [command] --help" for more information about a command.
|
||||||
@@ -246,7 +248,7 @@ You can use the following command to download them for the correct network:
|
|||||||
wget -O $HOME/.nyxd/config/genesis.json https://nymtech.net/genesis/genesis.json
|
wget -O $HOME/.nyxd/config/genesis.json https://nymtech.net/genesis/genesis.json
|
||||||
|
|
||||||
# Sandbox testnet
|
# Sandbox testnet
|
||||||
curl https://rpc.sandbox.nymtech.net/snapshots/genesis.json | jq '.result.genesis' > $HOME/.nyxd/config/genesis.json
|
curl https://rpc.sandbox.nymtech.net/genesis | jq '.result.genesis' > $HOME/.nyxd/config/genesis.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### `config.toml` configuration
|
### `config.toml` configuration
|
||||||
@@ -512,7 +514,7 @@ nyxd tx slashing unjail
|
|||||||
--from="KEYRING_NAME"
|
--from="KEYRING_NAME"
|
||||||
--chain-id=nyx
|
--chain-id=nyx
|
||||||
--gas=auto
|
--gas=auto
|
||||||
--gas-adjustment=1.4
|
--gas-adjustment=1.5
|
||||||
--gas-prices=0.025unyx
|
--gas-prices=0.025unyx
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -523,7 +525,7 @@ nyxd tx slashing unjail
|
|||||||
--from="KEYRING_NAME"
|
--from="KEYRING_NAME"
|
||||||
--chain-id=sandbox
|
--chain-id=sandbox
|
||||||
--gas=auto
|
--gas=auto
|
||||||
--gas-adjustment=1.4
|
--gas-adjustment=1.5
|
||||||
--gas-prices=0.025unyx
|
--gas-prices=0.025unyx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+21
-1
@@ -40,7 +40,7 @@ tokio = { workspace = true, features = [
|
|||||||
tokio-stream = { workspace = true, features = ["fs"] }
|
tokio-stream = { workspace = true, features = ["fs"] }
|
||||||
tokio-tungstenite = { workspace = true }
|
tokio-tungstenite = { workspace = true }
|
||||||
tokio-util = { workspace = true, features = ["codec"] }
|
tokio-util = { workspace = true, features = ["codec"] }
|
||||||
tracing = { workspace = true }
|
#tracing = { workspace = true }
|
||||||
url = { workspace = true, features = ["serde"] }
|
url = { workspace = true, features = ["serde"] }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|
||||||
@@ -72,6 +72,26 @@ nym-wireguard = { path = "../common/wireguard" }
|
|||||||
nym-wireguard-types = { path = "../common/wireguard-types", default-features = false }
|
nym-wireguard-types = { path = "../common/wireguard-types", default-features = false }
|
||||||
|
|
||||||
defguard_wireguard_rs = { workspace = true }
|
defguard_wireguard_rs = { workspace = true }
|
||||||
|
opentelemetry = { workspace = true, features = ["trace"] }
|
||||||
|
|
||||||
|
tracing = { workspace = true, features = [
|
||||||
|
"std",
|
||||||
|
"attributes",
|
||||||
|
"tracing-attributes",
|
||||||
|
] }
|
||||||
|
tracing-opentelemetry = { workspace = true }
|
||||||
|
opentelemetry_sdk = { version = "0.30.0", default-features = false, features = [
|
||||||
|
"trace",
|
||||||
|
"rt-tokio",
|
||||||
|
"experimental_metrics_custom_reader",
|
||||||
|
] }
|
||||||
|
opentelemetry-otlp = { workspace = true, features = [
|
||||||
|
"metrics",
|
||||||
|
"grpc-tonic",
|
||||||
|
"tls",
|
||||||
|
"tls-webpki-roots",
|
||||||
|
] }
|
||||||
|
opentelemetry-stdout = { workspace = true, features = ["trace", "metrics"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ use nym_gateway_storage::traits::SharedKeyGatewayStorage;
|
|||||||
use nym_node_metrics::events::MetricsEvent;
|
use nym_node_metrics::events::MetricsEvent;
|
||||||
use nym_sphinx::DestinationAddressBytes;
|
use nym_sphinx::DestinationAddressBytes;
|
||||||
use nym_task::TaskClient;
|
use nym_task::TaskClient;
|
||||||
|
use opentelemetry::trace::TraceContextExt;
|
||||||
|
use opentelemetry_sdk::trace::{IdGenerator, RandomIdGenerator};
|
||||||
use rand::CryptoRng;
|
use rand::CryptoRng;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -41,7 +43,8 @@ use time::OffsetDateTime;
|
|||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::time::timeout;
|
use tokio::time::timeout;
|
||||||
use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError};
|
use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError};
|
||||||
use tracing::*;
|
use tracing::{debug, error, info, info_span, instrument, warn};
|
||||||
|
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub(crate) enum InitialAuthenticationError {
|
pub(crate) enum InitialAuthenticationError {
|
||||||
@@ -854,6 +857,92 @@ impl<R, S> FreshHandler<R, S> {
|
|||||||
S: AsyncRead + AsyncWrite + Unpin + Send,
|
S: AsyncRead + AsyncWrite + Unpin + Send,
|
||||||
R: CryptoRng + RngCore + Send,
|
R: CryptoRng + RngCore + Send,
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
┌───────────────────────────────────────────────────────┐
|
||||||
|
│ Incoming Request │
|
||||||
|
│ trace_id: "abc123..." (from client) │
|
||||||
|
└────────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────────────────────────┐
|
||||||
|
│ 1. Create SpanContext │
|
||||||
|
│ ┌─────────────────────────────────────────────┐ │
|
||||||
|
│ │ SpanContext::new( │ │
|
||||||
|
│ │ trace_id: "abc123..." (preserved) │ │
|
||||||
|
│ │ span_id: "new_random_id" │ │
|
||||||
|
│ │ is_remote: true │ │
|
||||||
|
│ │ ) │ │
|
||||||
|
│ └─────────────────────────────────────────────┘ │
|
||||||
|
└────────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────────────────────────┐
|
||||||
|
│ 2. Convert to Context │
|
||||||
|
│ Context::current().with_remote_span_context(...) │
|
||||||
|
└────────────────────────┬──────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────────────────────────┐
|
||||||
|
│ 3. Create & Configure Span │
|
||||||
|
│ span = info_span!("authenticate_v1") │
|
||||||
|
│ span.set_parent(context) // Before entering │
|
||||||
|
└────────────────────────┬─────────────────────────────-┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────────────────────────┐
|
||||||
|
│ 4. Enter Span │
|
||||||
|
│ let _enter = span.enter() │
|
||||||
|
│ // All child spans inherit trace_id "abc123..." │
|
||||||
|
└───────────────────────────────────────────────────────┘
|
||||||
|
*/
|
||||||
|
let span = if let ClientControlRequest::AuthenticateV2(ref auth_req) = request {
|
||||||
|
if let Some(ref trace_id) = auth_req.debug_trace_id {
|
||||||
|
warn!("RAW TRACE ID: {trace_id:?}");
|
||||||
|
let trace_id = opentelemetry::trace::TraceId::from_hex(&trace_id)
|
||||||
|
.expect("Invalid trace ID format");
|
||||||
|
warn!("🫂TraceID: {trace_id}🫂");
|
||||||
|
|
||||||
|
// We don't need to try and preserve the SpanID, just the TraceID (right?) so
|
||||||
|
// just making a new SpanID for the moment
|
||||||
|
let id_generator = RandomIdGenerator::default();
|
||||||
|
let span_id = id_generator.new_span_id();
|
||||||
|
|
||||||
|
let span_context = opentelemetry::trace::SpanContext::new(
|
||||||
|
trace_id,
|
||||||
|
span_id,
|
||||||
|
opentelemetry::trace::TraceFlags::SAMPLED,
|
||||||
|
true, // is_remote = true since this comes from another service
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let remote_context =
|
||||||
|
opentelemetry::Context::current().with_remote_span_context(span_context);
|
||||||
|
|
||||||
|
let _context_guard = remote_context.clone().attach();
|
||||||
|
let span = info_span!(
|
||||||
|
"authenticate_v2",
|
||||||
|
trace_id = %trace_id
|
||||||
|
);
|
||||||
|
span.set_parent(remote_context.clone());
|
||||||
|
|
||||||
|
Some(span)
|
||||||
|
} else {
|
||||||
|
warn!("AuthenticateV2 request but no trace_id provided");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Not an AuthenticateV2 request");
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Probably a nicer way to do this but for now just match
|
||||||
|
let _guard = match &span {
|
||||||
|
Some(s) => {
|
||||||
|
warn!("ENTERED SPAN");
|
||||||
|
Some(s.enter())
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
warn!("COULDN'T ENTER SPAN");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// we can handle stateless client requests without prior authentication, like `ClientControlRequest::SupportedProtocol`
|
// we can handle stateless client requests without prior authentication, like `ClientControlRequest::SupportedProtocol`
|
||||||
let auth_result = match request {
|
let auth_result = match request {
|
||||||
ClientControlRequest::Authenticate {
|
ClientControlRequest::Authenticate {
|
||||||
@@ -861,6 +950,7 @@ impl<R, S> FreshHandler<R, S> {
|
|||||||
address,
|
address,
|
||||||
enc_address,
|
enc_address,
|
||||||
iv,
|
iv,
|
||||||
|
debug_trace_id: _,
|
||||||
} => {
|
} => {
|
||||||
self.handle_legacy_authenticate(protocol_version, address, enc_address, iv)
|
self.handle_legacy_authenticate(protocol_version, address, enc_address, iv)
|
||||||
.await
|
.await
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT\n date_utc as \"date_utc!\",\n SUM(total_stake) as \"total_stake!: i64\",\n SUM(packets_received) as \"total_packets_received!: i64\",\n SUM(packets_sent) as \"total_packets_sent!: i64\",\n SUM(packets_dropped) as \"total_packets_dropped!: i64\"\n FROM (\n SELECT\n date_utc,\n n.total_stake,\n n.packets_received,\n n.packets_sent,\n n.packets_dropped\n FROM nym_node_daily_mixing_stats n\n UNION ALL\n SELECT\n m.date_utc,\n m.total_stake,\n m.packets_received,\n m.packets_sent,\n m.packets_dropped\n FROM mixnode_daily_stats m\n LEFT JOIN nym_node_daily_mixing_stats ON m.mix_id = nym_node_daily_mixing_stats.node_id\n WHERE nym_node_daily_mixing_stats.node_id IS NULL\n )\n GROUP BY date_utc\n ORDER BY date_utc ASC\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "date_utc!",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "total_stake!: i64",
|
||||||
|
"type_info": "Numeric"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "total_packets_received!: i64",
|
||||||
|
"type_info": "Int8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "total_packets_sent!: i64",
|
||||||
|
"type_info": "Int8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "total_packets_dropped!: i64",
|
||||||
|
"type_info": "Int8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "124d45b9604439584650f401607c46bdbd162c7c689f74fe9ddfdfd48f5ddc07"
|
||||||
|
}
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT\n date_utc as \"date_utc!\",\n SUM(total_stake)::BIGINT as \"total_stake!: i64\",\n SUM(packets_received)::BIGINT as \"total_packets_received!: i64\",\n SUM(packets_sent)::BIGINT as \"total_packets_sent!: i64\",\n SUM(packets_dropped)::BIGINT as \"total_packets_dropped!: i64\"\n FROM (\n SELECT\n date_utc,\n n.total_stake,\n n.packets_received,\n n.packets_sent,\n n.packets_dropped\n FROM nym_node_daily_mixing_stats n\n UNION ALL\n SELECT\n m.date_utc,\n m.total_stake,\n m.packets_received,\n m.packets_sent,\n m.packets_dropped\n FROM mixnode_daily_stats m\n LEFT JOIN nym_node_daily_mixing_stats ON m.mix_id = nym_node_daily_mixing_stats.node_id\n WHERE nym_node_daily_mixing_stats.node_id IS NULL\n )\n GROUP BY date_utc\n ORDER BY date_utc ASC\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "date_utc!",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "total_stake!: i64",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "total_packets_received!: i64",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "total_packets_sent!: i64",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "total_packets_dropped!: i64",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "a19da2073bc691fe5cd2119a9527c16d6a8806ba50dcb759ac705b1a19288ca9"
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "nym-node-status-api"
|
name = "nym-node-status-api"
|
||||||
version = "3.2.6"
|
version = "3.2.2"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
@@ -22,7 +22,6 @@ clap = { workspace = true, features = ["cargo", "derive", "env", "string"] }
|
|||||||
cosmwasm-std = { workspace = true }
|
cosmwasm-std = { workspace = true }
|
||||||
envy = { workspace = true }
|
envy = { workspace = true }
|
||||||
futures-util = { workspace = true }
|
futures-util = { workspace = true }
|
||||||
hex = { workspace = true }
|
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
moka = { workspace = true, features = ["future"] }
|
moka = { workspace = true, features = ["future"] }
|
||||||
# TODO dz had to switch to cheddar versions because develop is ahead of current
|
# TODO dz had to switch to cheddar versions because develop is ahead of current
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ pub(crate) async fn get_all_mixnodes(pool: &DbPool) -> anyhow::Result<Vec<Mixnod
|
|||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sqlite")]
|
|
||||||
pub(crate) async fn get_daily_stats(pool: &DbPool) -> anyhow::Result<Vec<DailyStats>> {
|
pub(crate) async fn get_daily_stats(pool: &DbPool) -> anyhow::Result<Vec<DailyStats>> {
|
||||||
let mut conn = pool.acquire().await?;
|
let mut conn = pool.acquire().await?;
|
||||||
let items = sqlx::query_as!(
|
let items = sqlx::query_as!(
|
||||||
@@ -143,48 +142,6 @@ pub(crate) async fn get_daily_stats(pool: &DbPool) -> anyhow::Result<Vec<DailySt
|
|||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "pg")]
|
|
||||||
pub(crate) async fn get_daily_stats(pool: &DbPool) -> anyhow::Result<Vec<DailyStats>> {
|
|
||||||
let mut conn = pool.acquire().await?;
|
|
||||||
let items = sqlx::query_as!(
|
|
||||||
DailyStats,
|
|
||||||
r#"
|
|
||||||
SELECT
|
|
||||||
date_utc as "date_utc!",
|
|
||||||
SUM(total_stake)::BIGINT as "total_stake!: i64",
|
|
||||||
SUM(packets_received)::BIGINT as "total_packets_received!: i64",
|
|
||||||
SUM(packets_sent)::BIGINT as "total_packets_sent!: i64",
|
|
||||||
SUM(packets_dropped)::BIGINT as "total_packets_dropped!: i64"
|
|
||||||
FROM (
|
|
||||||
SELECT
|
|
||||||
date_utc,
|
|
||||||
n.total_stake,
|
|
||||||
n.packets_received,
|
|
||||||
n.packets_sent,
|
|
||||||
n.packets_dropped
|
|
||||||
FROM nym_node_daily_mixing_stats n
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
m.date_utc,
|
|
||||||
m.total_stake,
|
|
||||||
m.packets_received,
|
|
||||||
m.packets_sent,
|
|
||||||
m.packets_dropped
|
|
||||||
FROM mixnode_daily_stats m
|
|
||||||
LEFT JOIN nym_node_daily_mixing_stats ON m.mix_id = nym_node_daily_mixing_stats.node_id
|
|
||||||
WHERE nym_node_daily_mixing_stats.node_id IS NULL
|
|
||||||
)
|
|
||||||
GROUP BY date_utc
|
|
||||||
ORDER BY date_utc ASC
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.fetch(&mut *conn)
|
|
||||||
.try_collect::<Vec<DailyStats>>()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn get_bonded_mix_ids(pool: &DbPool) -> anyhow::Result<HashSet<i64>> {
|
pub(crate) async fn get_bonded_mix_ids(pool: &DbPool) -> anyhow::Result<HashSet<i64>> {
|
||||||
let mut conn = pool.acquire().await?;
|
let mut conn = pool.acquire().await?;
|
||||||
let items = crate::db::query(
|
let items = crate::db::query(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use tower_http::cors::CorsLayer;
|
|||||||
use utoipa::OpenApi;
|
use utoipa::OpenApi;
|
||||||
use utoipa_swagger_ui::SwaggerUi;
|
use utoipa_swagger_ui::SwaggerUi;
|
||||||
|
|
||||||
use crate::http::{middleware, server::HttpServer, state::AppState};
|
use crate::http::{server::HttpServer, state::AppState};
|
||||||
|
|
||||||
pub(crate) mod dvpn;
|
pub(crate) mod dvpn;
|
||||||
pub(crate) mod gateways;
|
pub(crate) mod gateways;
|
||||||
@@ -63,23 +63,17 @@ impl RouterBuilder {
|
|||||||
|
|
||||||
pub(crate) fn with_state(self, state: AppState) -> RouterWithState {
|
pub(crate) fn with_state(self, state: AppState) -> RouterWithState {
|
||||||
RouterWithState {
|
RouterWithState {
|
||||||
router: self.finalize_routes(state),
|
router: self.finalize_routes().with_state(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_routes(self, state: AppState) -> Router {
|
fn finalize_routes(self) -> Router<AppState> {
|
||||||
// layers added later wrap earlier layers
|
// layers added later wrap earlier layers
|
||||||
self.unfinished_router
|
self.unfinished_router
|
||||||
// Add response headers middleware
|
|
||||||
.layer(axum::middleware::from_fn_with_state(
|
|
||||||
state.clone(),
|
|
||||||
middleware::add_response_headers,
|
|
||||||
))
|
|
||||||
// CORS layer needs to wrap other API layers
|
// CORS layer needs to wrap other API layers
|
||||||
.layer(setup_cors())
|
.layer(setup_cors())
|
||||||
// logger should be outermost layer
|
// logger should be outermost layer
|
||||||
.layer(axum::middleware::from_fn(log_request_debug))
|
.layer(axum::middleware::from_fn(log_request_debug))
|
||||||
.with_state(state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,4 +127,12 @@ mod tests {
|
|||||||
let _test_router = unfinished_router;
|
let _test_router = unfinished_router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_router_builder_finalize() {
|
||||||
|
let router_builder = RouterBuilder::with_default_routes();
|
||||||
|
let finalized = router_builder.finalize_routes();
|
||||||
|
|
||||||
|
// This tests that finalize_routes produces a valid Router
|
||||||
|
let _router = finalized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ fn authenticate(request: &impl VerifiableRequest, state: &AppState) -> HttpResul
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
static FRESHNESS_CUTOFF: time::Duration = time::Duration::minutes(5);
|
static FRESHNESS_CUTOFF: time::Duration = time::Duration::minutes(2);
|
||||||
|
|
||||||
fn is_fresh(request_time: &i64) -> HttpResult<()> {
|
fn is_fresh(request_time: &i64) -> HttpResult<()> {
|
||||||
// if a request took longer than N minutes to reach NS API, something is very wrong
|
// if a request took longer than N minutes to reach NS API, something is very wrong
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
use axum::{
|
|
||||||
extract::{Request, State},
|
|
||||||
http::{HeaderName, HeaderValue},
|
|
||||||
middleware::Next,
|
|
||||||
response::Response,
|
|
||||||
};
|
|
||||||
use time::OffsetDateTime;
|
|
||||||
|
|
||||||
use crate::http::state::AppState;
|
|
||||||
|
|
||||||
pub async fn add_response_headers(
|
|
||||||
State(state): State<AppState>,
|
|
||||||
request: Request,
|
|
||||||
next: Next,
|
|
||||||
) -> Response {
|
|
||||||
let mut response = next.run(request).await;
|
|
||||||
|
|
||||||
let headers = response.headers_mut();
|
|
||||||
|
|
||||||
// Add timestamp header (RFC3339 format)
|
|
||||||
let timestamp = OffsetDateTime::now_utc()
|
|
||||||
.format(&time::format_description::well_known::Rfc3339)
|
|
||||||
.unwrap_or_else(|_| "unknown".to_string());
|
|
||||||
if let Ok(value) = HeaderValue::from_str(×tamp) {
|
|
||||||
headers.insert(HeaderName::from_static("x-response-timestamp"), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add instance ID header
|
|
||||||
if let Ok(value) = HeaderValue::from_str(state.instance_id()) {
|
|
||||||
headers.insert(HeaderName::from_static("x-instance-id"), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
response
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ use utoipa::ToSchema;
|
|||||||
pub(crate) mod api;
|
pub(crate) mod api;
|
||||||
pub(crate) mod api_docs;
|
pub(crate) mod api_docs;
|
||||||
pub(crate) mod error;
|
pub(crate) mod error;
|
||||||
pub(crate) mod middleware;
|
|
||||||
pub(crate) mod models;
|
pub(crate) mod models;
|
||||||
pub(crate) mod server;
|
pub(crate) mod server;
|
||||||
pub(crate) mod state;
|
pub(crate) mod state;
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ pub(crate) struct AppState {
|
|||||||
node_geocache: NodeGeoCache,
|
node_geocache: NodeGeoCache,
|
||||||
node_delegations: Arc<RwLock<DelegationsCache>>,
|
node_delegations: Arc<RwLock<DelegationsCache>>,
|
||||||
bin_info: BinaryInfo,
|
bin_info: BinaryInfo,
|
||||||
instance_id: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -54,7 +53,6 @@ impl AppState {
|
|||||||
node_geocache,
|
node_geocache,
|
||||||
node_delegations,
|
node_delegations,
|
||||||
bin_info: BinaryInfo::new(),
|
bin_info: BinaryInfo::new(),
|
||||||
instance_id: generate_instance_id(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,10 +94,6 @@ impl AppState {
|
|||||||
pub(crate) fn build_information(&self) -> &BinaryBuildInformationOwned {
|
pub(crate) fn build_information(&self) -> &BinaryBuildInformationOwned {
|
||||||
&self.bin_info.build_info
|
&self.bin_info.build_info
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn instance_id(&self) -> &str {
|
|
||||||
&self.instance_id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GATEWAYS_LIST_KEY: &str = "gateways";
|
static GATEWAYS_LIST_KEY: &str = "gateways";
|
||||||
@@ -505,10 +499,7 @@ impl HttpCache {
|
|||||||
None => {
|
None => {
|
||||||
let new_node_stats = crate::db::queries::get_daily_stats(db)
|
let new_node_stats = crate::db::queries::get_daily_stats(db)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_default()
|
||||||
tracing::error!("Failed to get daily stats from database: {}", e);
|
|
||||||
vec![]
|
|
||||||
})
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.rev()
|
.rev()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@@ -707,14 +698,3 @@ impl BinaryInfo {
|
|||||||
pub(crate) struct HealthInfo {
|
pub(crate) struct HealthInfo {
|
||||||
pub(crate) uptime: i64,
|
pub(crate) uptime: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_instance_id() -> String {
|
|
||||||
use rand::Rng;
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
let random_bytes: [u8; 16] = rng.gen();
|
|
||||||
format!(
|
|
||||||
"ns-api-{}-{}",
|
|
||||||
hex::encode(&random_bytes[..8]),
|
|
||||||
std::process::id()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
+14
-1
@@ -35,7 +35,7 @@ serde_json.workspace = true
|
|||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracing-indicatif = { workspace = true }
|
tracing-indicatif = { workspace = true }
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber = { workspace = true, features = ["json", "fmt"] }
|
||||||
tokio = { workspace = true, features = ["macros", "sync", "rt-multi-thread"] }
|
tokio = { workspace = true, features = ["macros", "sync", "rt-multi-thread"] }
|
||||||
tokio-util = { workspace = true, features = ["codec"] }
|
tokio-util = { workspace = true, features = ["codec"] }
|
||||||
toml = { workspace = true }
|
toml = { workspace = true }
|
||||||
@@ -114,6 +114,19 @@ blake2 = "=0.8.1"
|
|||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
hkdf = { workspace = true }
|
hkdf = { workspace = true }
|
||||||
|
|
||||||
|
# signoz
|
||||||
|
opentelemetry = { workspace = true }
|
||||||
|
opentelemetry_sdk = { workspace = true }
|
||||||
|
tracing-core = { workspace = true }
|
||||||
|
tracing-opentelemetry = { workspace = true }
|
||||||
|
tracing-serde = { workspace = true }
|
||||||
|
opentelemetry-otlp = { version = "0.30.0" }
|
||||||
|
opentelemetry-semantic-conventions = { workspace = true, features = [
|
||||||
|
"semconv_experimental",
|
||||||
|
] }
|
||||||
|
opentelemetry-stdout = { workspace = true, features = ["trace", "metrics"] }
|
||||||
|
chrono = { workspace = true }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "benchmarks"
|
name = "benchmarks"
|
||||||
harness = false
|
harness = false
|
||||||
|
|||||||
+68
-16
@@ -6,11 +6,13 @@ use crate::cli::commands::{
|
|||||||
test_throughput,
|
test_throughput,
|
||||||
};
|
};
|
||||||
use crate::env::vars::{NYMNODE_CONFIG_ENV_FILE_ARG, NYMNODE_NO_BANNER_ARG};
|
use crate::env::vars::{NYMNODE_CONFIG_ENV_FILE_ARG, NYMNODE_NO_BANNER_ARG};
|
||||||
use crate::logging::setup_tracing_logger;
|
use crate::error::NymNodeError;
|
||||||
|
use crate::logging::{setup_no_otel_logger, setup_tracing_logger};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use nym_bin_common::bin_info;
|
use nym_bin_common::bin_info;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
pub(crate) mod commands;
|
pub(crate) mod commands;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
@@ -53,28 +55,73 @@ impl Cli {
|
|||||||
.block_on(fut))
|
.block_on(fut))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
pub(crate) fn execute(self) -> anyhow::Result<()> {
|
pub(crate) fn execute(self) -> anyhow::Result<()> {
|
||||||
// NOTE: `test_throughput` sets up its own logger as it has to include additional layers
|
|
||||||
if !matches!(self.command, Commands::TestThroughput(..)) {
|
|
||||||
setup_tracing_logger()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.command {
|
match self.command {
|
||||||
Commands::BuildInfo(args) => build_info::execute(args)?,
|
// Sync commands get logger w. no OTEL
|
||||||
Commands::BondingInformation(args) => {
|
Commands::BuildInfo(args) => {
|
||||||
{ Self::execute_async(bonding_information::execute(args))? }?
|
setup_no_otel_logger()?;
|
||||||
|
build_info::execute(args)?
|
||||||
}
|
}
|
||||||
Commands::NodeDetails(args) => { Self::execute_async(node_details::execute(args))? }?,
|
Commands::Migrate(args) => {
|
||||||
Commands::Run(args) => { Self::execute_async(run::execute(*args))? }?,
|
setup_no_otel_logger()?;
|
||||||
Commands::Migrate(args) => migrate::execute(*args)?,
|
migrate::execute(*args)?
|
||||||
Commands::Sign(args) => { Self::execute_async(sign::execute(args))? }?,
|
|
||||||
Commands::TestThroughput(args) => test_throughput::execute(args)?,
|
|
||||||
Commands::UnsafeResetSphinxKeys(args) => {
|
|
||||||
{ Self::execute_async(reset_sphinx_keys::execute(args))? }?
|
|
||||||
}
|
}
|
||||||
|
Commands::TestThroughput(args) => {
|
||||||
|
// Has its own logging setup
|
||||||
|
test_throughput::execute(args)?
|
||||||
|
}
|
||||||
|
// SigNoz/OTEL run in async context
|
||||||
|
Commands::BondingInformation(args) => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
bonding_information::execute(args).await
|
||||||
|
})??,
|
||||||
|
Commands::NodeDetails(args) => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
node_details::execute(args).await
|
||||||
|
})??,
|
||||||
|
Commands::Run(args) => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
run::execute(*args).await
|
||||||
|
})??,
|
||||||
|
Commands::Sign(args) => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
sign::execute(args).await
|
||||||
|
})??,
|
||||||
|
Commands::UnsafeResetSphinxKeys(args) => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
reset_sphinx_keys::execute(args).await
|
||||||
|
})??,
|
||||||
|
Commands::TestTracing => Self::execute_async(async move {
|
||||||
|
setup_tracing_logger().map_err(NymNodeError::TracingSetupFailure)?;
|
||||||
|
Ok::<(), crate::error::NymNodeError>(())
|
||||||
|
})??,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub(crate) fn execute(self) -> anyhow::Result<()> {
|
||||||
|
// // NOTE: `test_throughput` sets up its own logger as it has to include additional layers
|
||||||
|
// // if !matches!(self.command, Commands::TestThroughput(..)) {
|
||||||
|
// // setup_tracing_logger()?;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// match self.command {
|
||||||
|
// Commands::BuildInfo(args) => build_info::execute(args)?,
|
||||||
|
// Commands::BondingInformation(args) => {
|
||||||
|
// { Self::execute_async(bonding_information::execute(args))? }?
|
||||||
|
// }
|
||||||
|
// Commands::NodeDetails(args) => { Self::execute_async(node_details::execute(args))? }?,
|
||||||
|
// Commands::Run(args) => { Self::execute_async(run::execute(*args))? }?,
|
||||||
|
// Commands::Migrate(args) => migrate::execute(*args)?,
|
||||||
|
// Commands::Sign(args) => { Self::execute_async(sign::execute(args))? }?,
|
||||||
|
// Commands::TestThroughput(args) => test_throughput::execute(args)?,
|
||||||
|
// Commands::UnsafeResetSphinxKeys(args) => {
|
||||||
|
// { Self::execute_async(reset_sphinx_keys::execute(args))? }?
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
@@ -104,6 +151,11 @@ pub(crate) enum Commands {
|
|||||||
/// was running on this machine in mixnet mode
|
/// was running on this machine in mixnet mode
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
TestThroughput(test_throughput::Args),
|
TestThroughput(test_throughput::Args),
|
||||||
|
|
||||||
|
/// Test local tracing for instrumentation and
|
||||||
|
/// TraceID aligmnet
|
||||||
|
// TODO this needs to just start and then wait for the shutdown signal - grab from run()
|
||||||
|
TestTracing,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ pub enum KeyIOFailure {
|
|||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum NymNodeError {
|
pub enum NymNodeError {
|
||||||
|
#[error("Failed to setup tracing logger")]
|
||||||
|
TracingSetupFailure(#[source] anyhow::Error),
|
||||||
|
|
||||||
#[error("this binary version no longer supports migration from legacy mixnodes and gateways")]
|
#[error("this binary version no longer supports migration from legacy mixnodes and gateways")]
|
||||||
UnsupportedMigration,
|
UnsupportedMigration,
|
||||||
|
|
||||||
|
|||||||
+135
-4
@@ -2,9 +2,27 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use nym_bin_common::logging::{default_tracing_env_filter, default_tracing_fmt_layer};
|
use nym_bin_common::logging::{default_tracing_env_filter, default_tracing_fmt_layer};
|
||||||
|
use tracing::{info, warn};
|
||||||
use tracing_subscriber::filter::Directive;
|
use tracing_subscriber::filter::Directive;
|
||||||
use tracing_subscriber::layer::SubscriberExt;
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
|
use tracing_subscriber::{fmt, Layer};
|
||||||
|
|
||||||
|
// Signoz
|
||||||
|
use crate::trace_id_format::TraceIdFormat;
|
||||||
|
use opentelemetry::trace::TracerProvider;
|
||||||
|
use opentelemetry::{global, KeyValue};
|
||||||
|
use opentelemetry_otlp::tonic_types::metadata::MetadataMap;
|
||||||
|
use opentelemetry_otlp::tonic_types::transport::ClientTlsConfig;
|
||||||
|
use opentelemetry_otlp::{WithExportConfig, WithTonicConfig};
|
||||||
|
use opentelemetry_sdk::metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider};
|
||||||
|
use opentelemetry_sdk::trace::{RandomIdGenerator, SdkTracerProvider};
|
||||||
|
use opentelemetry_sdk::{trace::Sampler, Resource};
|
||||||
|
use opentelemetry_semantic_conventions::resource::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_VERSION};
|
||||||
|
use opentelemetry_semantic_conventions::SCHEMA_URL;
|
||||||
|
use tracing_core::Level;
|
||||||
|
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
||||||
|
use tracing_subscriber::fmt::format::FmtSpan;
|
||||||
|
|
||||||
pub(crate) fn granual_filtered_env() -> anyhow::Result<tracing_subscriber::filter::EnvFilter> {
|
pub(crate) fn granual_filtered_env() -> anyhow::Result<tracing_subscriber::filter::EnvFilter> {
|
||||||
fn directive_checked(directive: impl Into<String>) -> anyhow::Result<Directive> {
|
fn directive_checked(directive: impl Into<String>) -> anyhow::Result<Directive> {
|
||||||
@@ -13,7 +31,6 @@ pub(crate) fn granual_filtered_env() -> anyhow::Result<tracing_subscriber::filte
|
|||||||
|
|
||||||
let mut filter = default_tracing_env_filter();
|
let mut filter = default_tracing_env_filter();
|
||||||
|
|
||||||
// these crates are more granularly filtered
|
|
||||||
let filter_crates = ["defguard_wireguard_rs"];
|
let filter_crates = ["defguard_wireguard_rs"];
|
||||||
for crate_name in filter_crates {
|
for crate_name in filter_crates {
|
||||||
filter = filter.add_directive(directive_checked(format!("{crate_name}=warn"))?);
|
filter = filter.add_directive(directive_checked(format!("{crate_name}=warn"))?);
|
||||||
@@ -22,13 +39,127 @@ pub(crate) fn granual_filtered_env() -> anyhow::Result<tracing_subscriber::filte
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_tracing_logger() -> anyhow::Result<impl SubscriberExt> {
|
pub(crate) fn build_tracing_logger() -> anyhow::Result<impl SubscriberExt> {
|
||||||
Ok(tracing_subscriber::registry()
|
let key = std::env::var("SIGNOZ_INGESTION_KEY").expect("SIGNOZ_INGESTION_KEY not set");
|
||||||
.with(default_tracing_fmt_layer(std::io::stderr))
|
println!("SIGNOZ_INGESTION_KEY = {}", key);
|
||||||
.with(granual_filtered_env()?))
|
let mut metadata = MetadataMap::new();
|
||||||
|
metadata.insert(
|
||||||
|
"signoz-ingestion-key",
|
||||||
|
key.parse().expect("Could not parse key"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let tracer_provider = init_tracer_provider(metadata)?;
|
||||||
|
let meter_provider = init_meter_provider()?;
|
||||||
|
let tracer = tracer_provider.tracer("tracing-otel-subscriber");
|
||||||
|
|
||||||
|
let fmt_layer = fmt::layer()
|
||||||
|
.json()
|
||||||
|
.with_writer(std::io::stderr)
|
||||||
|
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
||||||
|
.with_span_list(false)
|
||||||
|
.with_current_span(true)
|
||||||
|
.event_format(TraceIdFormat);
|
||||||
|
|
||||||
|
let registry = tracing_subscriber::registry()
|
||||||
|
.with(fmt_layer)
|
||||||
|
.with(granual_filtered_env()?)
|
||||||
|
.with(tracing_subscriber::filter::LevelFilter::from_level(
|
||||||
|
Level::DEBUG,
|
||||||
|
))
|
||||||
|
.with(MetricsLayer::new(meter_provider))
|
||||||
|
.with(OpenTelemetryLayer::new(tracer));
|
||||||
|
|
||||||
|
Ok(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn setup_tracing_logger() -> anyhow::Result<()> {
|
pub(crate) fn setup_tracing_logger() -> anyhow::Result<()> {
|
||||||
build_tracing_logger()?.init();
|
build_tracing_logger()?.init();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called outside of the async context where we can't use OTEL
|
||||||
|
pub(crate) fn setup_no_otel_logger() -> anyhow::Result<()> {
|
||||||
|
// Only set up if not already initialized
|
||||||
|
if tracing::dispatcher::has_been_set() {
|
||||||
|
// It shouldn't be - this is really checking that it is torn down between async command executions
|
||||||
|
return Err(anyhow::anyhow!("Tracing logger already initialised"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let registry = tracing_subscriber::registry()
|
||||||
|
.with(default_tracing_fmt_layer(std::io::stderr))
|
||||||
|
.with(granual_filtered_env()?)
|
||||||
|
.with(tracing_subscriber::filter::LevelFilter::from_level(
|
||||||
|
Level::INFO,
|
||||||
|
));
|
||||||
|
|
||||||
|
registry
|
||||||
|
.try_init()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to set tracing subscriber: {}", e))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signoz/OTEL
|
||||||
|
fn resource() -> Resource {
|
||||||
|
Resource::builder()
|
||||||
|
.with_service_name("nym-node")
|
||||||
|
.with_schema_url(
|
||||||
|
[
|
||||||
|
KeyValue::new(SERVICE_VERSION, env!("CARGO_PKG_VERSION")),
|
||||||
|
KeyValue::new(DEPLOYMENT_ENVIRONMENT_NAME, "develop"),
|
||||||
|
],
|
||||||
|
SCHEMA_URL,
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_tracer_provider(metadata: MetadataMap) -> anyhow::Result<SdkTracerProvider> {
|
||||||
|
let endpoint = std::env::var("SIGNOZ_ENDPOINT").expect("SIGNOZ_ENDPOINT not set");
|
||||||
|
info!("SIGNOZ_ENDPOINT = {}", endpoint);
|
||||||
|
|
||||||
|
let mut exporter_builder = opentelemetry_otlp::SpanExporter::builder()
|
||||||
|
.with_tonic()
|
||||||
|
.with_metadata(metadata)
|
||||||
|
.with_endpoint(&endpoint);
|
||||||
|
|
||||||
|
if endpoint.starts_with("https://") {
|
||||||
|
exporter_builder =
|
||||||
|
exporter_builder.with_tls_config(ClientTlsConfig::new().with_enabled_roots());
|
||||||
|
}
|
||||||
|
|
||||||
|
let exporter = exporter_builder.build()?;
|
||||||
|
|
||||||
|
let tracer = SdkTracerProvider::builder()
|
||||||
|
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(
|
||||||
|
1.0,
|
||||||
|
))))
|
||||||
|
.with_id_generator(RandomIdGenerator::default())
|
||||||
|
.with_resource(resource())
|
||||||
|
.with_batch_exporter(exporter)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Ok(tracer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_meter_provider() -> anyhow::Result<SdkMeterProvider> {
|
||||||
|
let exporter = opentelemetry_otlp::MetricExporter::builder()
|
||||||
|
.with_tonic()
|
||||||
|
.with_temporality(opentelemetry_sdk::metrics::Temporality::default())
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let reader = PeriodicReader::builder(exporter)
|
||||||
|
.with_interval(std::time::Duration::from_secs(30))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let stdout_reader =
|
||||||
|
PeriodicReader::builder(opentelemetry_stdout::MetricExporter::default()).build();
|
||||||
|
|
||||||
|
let meter_provider = MeterProviderBuilder::default()
|
||||||
|
.with_resource(resource())
|
||||||
|
.with_reader(reader)
|
||||||
|
.with_reader(stdout_reader)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
global::set_meter_provider(meter_provider.clone());
|
||||||
|
|
||||||
|
Ok(meter_provider)
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub(crate) mod error;
|
|||||||
mod logging;
|
mod logging;
|
||||||
pub(crate) mod node;
|
pub(crate) mod node;
|
||||||
pub(crate) mod throughput_tester;
|
pub(crate) mod throughput_tester;
|
||||||
|
mod trace_id_format;
|
||||||
pub(crate) mod wireguard;
|
pub(crate) mod wireguard;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
use chrono::Utc;
|
||||||
|
use opentelemetry::trace::TraceContextExt;
|
||||||
|
use opentelemetry::{SpanId, TraceId};
|
||||||
|
use serde::ser::{SerializeMap, Serializer as _};
|
||||||
|
use std::io;
|
||||||
|
use tracing::{Event, Subscriber};
|
||||||
|
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||||
|
use tracing_serde::fields::AsMap;
|
||||||
|
use tracing_serde::AsSerde;
|
||||||
|
use tracing_subscriber::fmt::format::Writer;
|
||||||
|
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
|
||||||
|
use tracing_subscriber::registry::LookupSpan;
|
||||||
|
|
||||||
|
pub struct WriteAdaptor<'a> {
|
||||||
|
fmt_write: &'a mut dyn std::fmt::Write,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> WriteAdaptor<'a> {
|
||||||
|
pub fn new(fmt_write: &'a mut dyn std::fmt::Write) -> Self {
|
||||||
|
Self { fmt_write }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> io::Write for WriteAdaptor<'a> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
let s =
|
||||||
|
std::str::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
self.fmt_write
|
||||||
|
.write_str(s)
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
|
||||||
|
Ok(s.as_bytes().len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TraceIdFormat;
|
||||||
|
|
||||||
|
impl<S, N> FormatEvent<S, N> for TraceIdFormat
|
||||||
|
where
|
||||||
|
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
|
||||||
|
N: for<'writer> FormatFields<'writer> + 'static,
|
||||||
|
{
|
||||||
|
fn format_event(
|
||||||
|
&self,
|
||||||
|
_ctx: &FmtContext<'_, S, N>,
|
||||||
|
mut writer: Writer<'_>,
|
||||||
|
event: &Event<'_>,
|
||||||
|
) -> std::fmt::Result
|
||||||
|
where
|
||||||
|
S: Subscriber + for<'a> LookupSpan<'a>,
|
||||||
|
{
|
||||||
|
let meta = event.metadata();
|
||||||
|
|
||||||
|
let mut visit = || {
|
||||||
|
let mut serializer = serde_json::Serializer::new(WriteAdaptor::new(&mut writer));
|
||||||
|
let mut serializer = serializer.serialize_map(None)?;
|
||||||
|
serializer.serialize_entry("timestamp", &Utc::now().to_rfc3339())?;
|
||||||
|
serializer.serialize_entry("level", &meta.level().as_serde())?;
|
||||||
|
serializer.serialize_entry("fields", &event.field_map())?;
|
||||||
|
serializer.serialize_entry("target", meta.target())?;
|
||||||
|
|
||||||
|
let current_span = tracing::Span::current();
|
||||||
|
let context = current_span.context();
|
||||||
|
let span_ref = context.span();
|
||||||
|
let span_context = span_ref.span_context();
|
||||||
|
|
||||||
|
let trace_id = span_context.trace_id();
|
||||||
|
if trace_id != TraceId::INVALID {
|
||||||
|
serializer.serialize_entry("trace_id", &trace_id.to_string())?;
|
||||||
|
|
||||||
|
let span_id = span_context.span_id();
|
||||||
|
if span_id != SpanId::INVALID {
|
||||||
|
serializer.serialize_entry("span_id", &span_id.to_string())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer.end()
|
||||||
|
};
|
||||||
|
|
||||||
|
visit().map_err(|_| std::fmt::Error)?;
|
||||||
|
writeln!(writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ test_port_range_rules() {
|
|||||||
"8087-8088:tcp:Simplify Media"
|
"8087-8088:tcp:Simplify Media"
|
||||||
"8232-8233:tcp:Zcash"
|
"8232-8233:tcp:Zcash"
|
||||||
"8332-8333:tcp:Bitcoin"
|
"8332-8333:tcp:Bitcoin"
|
||||||
|
"18080-18081:tcp:Monero"
|
||||||
)
|
)
|
||||||
|
|
||||||
local total_failures=0
|
local total_failures=0
|
||||||
@@ -148,7 +149,7 @@ test_critical_services() {
|
|||||||
# Verify default reject rule exists
|
# Verify default reject rule exists
|
||||||
test_default_reject_rule() {
|
test_default_reject_rule() {
|
||||||
echo -e "${YELLOW}This test takes some time, do not quit the process${NC}"
|
echo -e "${YELLOW}This test takes some time, do not quit the process${NC}"
|
||||||
echo
|
echo
|
||||||
echo -e "${YELLOW}Testing Default Reject Rule...${NC}"
|
echo -e "${YELLOW}Testing Default Reject Rule...${NC}"
|
||||||
|
|
||||||
# Try different patterns to detect the reject rule
|
# Try different patterns to detect the reject rule
|
||||||
@@ -236,4 +237,4 @@ if [[ $EUID -ne 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Run the tests
|
# Run the tests
|
||||||
run_all_tests "$@"
|
run_all_tests "$@"
|
||||||
|
|||||||
@@ -357,9 +357,13 @@ apply_port_allowlist() {
|
|||||||
["Lightning"]="9735"
|
["Lightning"]="9735"
|
||||||
["NDMP"]="10000"
|
["NDMP"]="10000"
|
||||||
["OpenPGP"]="11371"
|
["OpenPGP"]="11371"
|
||||||
|
["Monero"]="18080-18081"
|
||||||
|
["MoneroRPC"]="18089"
|
||||||
["GoogleVoice"]="19294"
|
["GoogleVoice"]="19294"
|
||||||
["EnsimControlPanel"]="19638"
|
["EnsimControlPanel"]="19638"
|
||||||
|
["DarkFiTor"]="25551"
|
||||||
["Minecraft"]="25565"
|
["Minecraft"]="25565"
|
||||||
|
["DarkFi"]="26661"
|
||||||
["Steam"]="27000-27050"
|
["Steam"]="27000-27050"
|
||||||
["ElectrumSSL"]="50002"
|
["ElectrumSSL"]="50002"
|
||||||
["MOSH"]="60000-61000"
|
["MOSH"]="60000-61000"
|
||||||
@@ -672,4 +676,4 @@ main() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
@@ -70,10 +70,18 @@ tokio-util.workspace = true
|
|||||||
uuid = { workspace = true, features = ["v4", "serde"] }
|
uuid = { workspace = true, features = ["v4", "serde"] }
|
||||||
bincode = { workspace = true }
|
bincode = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
tracing.workspace = true
|
#tracing.workspace = true
|
||||||
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
#tracing-subscriber = { workspace = true, features = ["env-filter", "registry", "std"] }
|
||||||
dirs.workspace = true
|
dirs.workspace = true
|
||||||
|
|
||||||
|
opentelemetry = { workspace = true }
|
||||||
|
opentelemetry_sdk = { workspace = true }
|
||||||
|
|
||||||
|
tracing = { workspace = true, features = ["std"] }
|
||||||
|
tracing-subscriber = { workspace = true, features = ["registry", "std"] }
|
||||||
|
tracing-core = { workspace = true }
|
||||||
|
tracing-opentelemetry = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
dotenvy = { workspace = true }
|
dotenvy = { workspace = true }
|
||||||
@@ -83,6 +91,11 @@ tokio = { workspace = true, features = ["full"] }
|
|||||||
time = { workspace = true }
|
time = { workspace = true }
|
||||||
nym-bin-common = { path = "../../../common/bin-common", features = ["basic_tracing"] }
|
nym-bin-common = { path = "../../../common/bin-common", features = ["basic_tracing"] }
|
||||||
|
|
||||||
|
opentelemetry-semantic-conventions = { workspace = true, features = ["semconv_experimental"] }
|
||||||
|
opentelemetry-otlp = { workspace = true, features = ["metrics", "grpc-tonic", "tls",
|
||||||
|
"tls-webpki-roots", ] }
|
||||||
|
opentelemetry-stdout = { workspace = true, features = ["trace", "metrics"] }
|
||||||
|
|
||||||
# extra dependencies for libp2p examples
|
# extra dependencies for libp2p examples
|
||||||
#libp2p = { git = "https://github.com/ChainSafe/rust-libp2p.git", rev = "e3440d25681df380c9f0f8cfdcfd5ecc0a4f2fb6", features = [ "identify", "macros", "ping", "tokio", "tcp", "dns", "websocket", "noise", "mplex", "yamux", "gossipsub" ]}
|
#libp2p = { git = "https://github.com/ChainSafe/rust-libp2p.git", rev = "e3440d25681df380c9f0f8cfdcfd5ecc0a4f2fb6", features = [ "identify", "macros", "ping", "tokio", "tcp", "dns", "websocket", "noise", "mplex", "yamux", "gossipsub" ]}
|
||||||
tokio-stream = { workspace = true }
|
tokio-stream = { workspace = true }
|
||||||
@@ -92,3 +105,4 @@ hex = { workspace = true }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
libp2p-vanilla = []
|
libp2p-vanilla = []
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,208 @@
|
|||||||
|
use dotenvy::dotenv;
|
||||||
use nym_sdk::mixnet::{
|
use nym_sdk::mixnet::{
|
||||||
AnonymousSenderTag, MixnetClientBuilder, MixnetMessageSender, ReconstructedMessage,
|
AnonymousSenderTag, MixnetClientBuilder, MixnetMessageSender, ReconstructedMessage,
|
||||||
StoragePaths,
|
StoragePaths,
|
||||||
};
|
};
|
||||||
|
use opentelemetry::trace::TraceContextExt;
|
||||||
|
use opentelemetry::trace::Tracer;
|
||||||
|
use opentelemetry::trace::TracerProvider;
|
||||||
|
use opentelemetry::Context;
|
||||||
|
use opentelemetry::{global, KeyValue};
|
||||||
|
use opentelemetry_otlp::tonic_types::metadata::MetadataMap;
|
||||||
|
use opentelemetry_otlp::tonic_types::transport::ClientTlsConfig;
|
||||||
|
use opentelemetry_otlp::{WithExportConfig, WithTonicConfig};
|
||||||
|
use opentelemetry_sdk::metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider};
|
||||||
|
use opentelemetry_sdk::trace::IdGenerator;
|
||||||
|
use opentelemetry_sdk::trace::{RandomIdGenerator, SdkTracerProvider};
|
||||||
|
use opentelemetry_sdk::{trace::Sampler, Resource};
|
||||||
|
use opentelemetry_semantic_conventions::{
|
||||||
|
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_VERSION},
|
||||||
|
SCHEMA_URL,
|
||||||
|
};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
use tracing::info_span;
|
||||||
|
use tracing::instrument;
|
||||||
|
use tracing::{info, warn};
|
||||||
|
use tracing_core::Level;
|
||||||
|
use tracing_opentelemetry::{MetricsLayer, OpenTelemetryLayer};
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
fn resource() -> Resource {
|
||||||
async fn main() {
|
Resource::builder()
|
||||||
nym_bin_common::logging::setup_tracing_logger();
|
.with_service_name("sdk-example-surb-reply")
|
||||||
|
.with_schema_url(
|
||||||
|
[
|
||||||
|
KeyValue::new(SERVICE_VERSION, env!("CARGO_PKG_VERSION")),
|
||||||
|
KeyValue::new(DEPLOYMENT_ENVIRONMENT_NAME, "develop"),
|
||||||
|
],
|
||||||
|
SCHEMA_URL,
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
// Specify some config options
|
fn init_tracer_provider(metadata: MetadataMap) -> anyhow::Result<SdkTracerProvider> {
|
||||||
let config_dir: PathBuf = TempDir::new().unwrap().path().to_path_buf();
|
let endpoint = std::env::var("SIGNOZ_ENDPOINT").expect("SIGNOZ_ENDPOINT not set");
|
||||||
let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap();
|
println!("SIGNOZ_ENDPOINT = {}", endpoint);
|
||||||
|
|
||||||
// Create the client with a storage backend, and enable it by giving it some paths. If keys
|
// Configure OTLP exporter with metadata
|
||||||
// exists at these paths, they will be loaded, otherwise they will be generated.
|
let mut exporter_builder = opentelemetry_otlp::SpanExporter::builder()
|
||||||
let client = MixnetClientBuilder::new_with_default_storage(storage_paths)
|
.with_tonic()
|
||||||
.await
|
.with_metadata(metadata)
|
||||||
.unwrap()
|
.with_endpoint(&endpoint);
|
||||||
|
|
||||||
|
// Try with TLS - seems to work
|
||||||
|
if endpoint.starts_with("https://") {
|
||||||
|
exporter_builder =
|
||||||
|
exporter_builder.with_tls_config(ClientTlsConfig::new().with_enabled_roots());
|
||||||
|
}
|
||||||
|
|
||||||
|
let exporter = exporter_builder.build()?;
|
||||||
|
|
||||||
|
let tracer = SdkTracerProvider::builder()
|
||||||
|
// Customize sampling strategy
|
||||||
|
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(
|
||||||
|
1.0,
|
||||||
|
))))
|
||||||
|
// If export trace to AWS X-Ray, you can use XrayIdGenerator
|
||||||
|
.with_id_generator(RandomIdGenerator::default())
|
||||||
|
.with_resource(resource())
|
||||||
|
.with_batch_exporter(exporter)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// We set this in meter provider but didn't in here
|
||||||
|
// :facepalm:
|
||||||
|
global::set_tracer_provider(tracer.clone());
|
||||||
|
|
||||||
|
Ok(tracer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_meter_provider() -> SdkMeterProvider {
|
||||||
|
let exporter = opentelemetry_otlp::MetricExporter::builder()
|
||||||
|
.with_tonic()
|
||||||
|
.with_temporality(opentelemetry_sdk::metrics::Temporality::default())
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let reader = PeriodicReader::builder(exporter)
|
||||||
|
.with_interval(std::time::Duration::from_secs(30))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// For debugging in development
|
||||||
|
let stdout_reader =
|
||||||
|
PeriodicReader::builder(opentelemetry_stdout::MetricExporter::default()).build();
|
||||||
|
|
||||||
|
let meter_provider = MeterProviderBuilder::default()
|
||||||
|
.with_resource(resource())
|
||||||
|
.with_reader(reader)
|
||||||
|
.with_reader(stdout_reader)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
global::set_meter_provider(meter_provider.clone());
|
||||||
|
|
||||||
|
meter_provider
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_tracing_subscriber(metadata: MetadataMap) -> OtelGuard {
|
||||||
|
let tracer_provider = init_tracer_provider(metadata).expect("Initializing tracer failed");
|
||||||
|
let meter_provider = init_meter_provider();
|
||||||
|
|
||||||
|
let tracer = tracer_provider.tracer("tracing-otel-subscriber");
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
// The global level filter prevents the exporter network stack
|
||||||
|
// from reentering the globally installed OpenTelemetryLayer with
|
||||||
|
// its own spans while exporting, as the libraries should not use
|
||||||
|
// tracing levels below DEBUG. If the OpenTelemetry layer needs to
|
||||||
|
// trace spans and events with higher verbosity levels, consider using
|
||||||
|
// per-layer filtering to target the telemetry layer specifically,
|
||||||
|
// e.g. by target matching.
|
||||||
|
.with(tracing_subscriber::filter::LevelFilter::from_level(
|
||||||
|
Level::DEBUG,
|
||||||
|
))
|
||||||
|
.with(tracing_subscriber::fmt::layer())
|
||||||
|
.with(MetricsLayer::new(meter_provider.clone()))
|
||||||
|
.with(OpenTelemetryLayer::new(tracer))
|
||||||
|
.init();
|
||||||
|
|
||||||
|
OtelGuard {
|
||||||
|
tracer_provider,
|
||||||
|
meter_provider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OtelGuard {
|
||||||
|
tracer_provider: SdkTracerProvider,
|
||||||
|
meter_provider: SdkMeterProvider,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OtelGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Err(err) = self.tracer_provider.shutdown() {
|
||||||
|
eprintln!("{err:?}");
|
||||||
|
}
|
||||||
|
if let Err(err) = self.meter_provider.shutdown() {
|
||||||
|
eprintln!("{err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
#[instrument]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
// nym_bin_common::logging::setup_tracing_logger();
|
||||||
|
|
||||||
|
dotenv().ok();
|
||||||
|
let key = std::env::var("SIGNOZ_INGESTION_KEY").expect("SIGNOZ_INGESTION_KEY not set");
|
||||||
|
println!("SIGNOZ_INGESTION_KEY = {}", key);
|
||||||
|
|
||||||
|
let mut metadata = MetadataMap::new();
|
||||||
|
metadata.insert("signoz-ingestion-key", key.parse()?);
|
||||||
|
|
||||||
|
let _guard = init_tracing_subscriber(metadata);
|
||||||
|
let tracer = global::tracer("sdk-example-surb-reply");
|
||||||
|
let span = tracer.start("test_span");
|
||||||
|
let cx = Context::current_with_span(span);
|
||||||
|
let _guard = cx.clone().attach();
|
||||||
|
|
||||||
|
let trace_id = cx.span().span_context().trace_id();
|
||||||
|
warn!("Main TRACE_ID: {:?}", trace_id);
|
||||||
|
|
||||||
|
let span = info_span!(
|
||||||
|
"surb_reply_example_session",
|
||||||
|
trace_id = %trace_id.to_string()
|
||||||
|
);
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
|
let otel_context = opentelemetry::Context::current();
|
||||||
|
warn!("OTEL CONTEXT: {:?}", otel_context);
|
||||||
|
let span = otel_context.span();
|
||||||
|
let context = span.span_context();
|
||||||
|
let trace_id = context.trace_id();
|
||||||
|
warn!("TRACE_ID: {:?}", trace_id);
|
||||||
|
// panic!();
|
||||||
|
|
||||||
|
// Specify some config options
|
||||||
|
// let config_dir: PathBuf = TempDir::new().unwrap().path().to_path_buf();
|
||||||
|
// let storage_paths = StoragePaths::new_from_dir(&config_dir).unwrap();
|
||||||
|
|
||||||
|
// Create the client with a storage backend, and enable it by giving it some paths. If keys
|
||||||
|
// exists at these paths, they will be loaded, otherwise they will be generated.
|
||||||
|
// let client = MixnetClientBuilder::new_with_default_storage(storage_paths)
|
||||||
|
// .await
|
||||||
|
// .unwrap()
|
||||||
|
// .build()
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
let client_builder = MixnetClientBuilder::new_ephemeral();
|
||||||
|
let mixnet_client = client_builder
|
||||||
|
.request_gateway("BAF2aYpzcK9KbSS3Y7EdLisxiogkTr88FXkdL8EDNigH".to_string())
|
||||||
|
.with_ignore_epoch_roles(true)
|
||||||
|
.with_extended_topology(true)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
// Now we connect to the mixnet, using keys now stored in the paths provided.
|
// Now we connect to the mixnet, using keys now stored in the paths provided.
|
||||||
let mut client = client.connect_to_mixnet().await.unwrap();
|
let mut client = mixnet_client.connect_to_mixnet().await.unwrap();
|
||||||
|
|
||||||
// Be able to get our client address
|
// Be able to get our client address
|
||||||
let our_address = client.nym_address();
|
let our_address = client.nym_address();
|
||||||
@@ -69,4 +249,6 @@ async fn main() {
|
|||||||
client
|
client
|
||||||
.on_messages(|msg| println!("\nReceived: {}", String::from_utf8_lossy(&msg.message)))
|
.on_messages(|msg| println!("\nReceived: {}", String::from_utf8_lossy(&msg.message)))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,6 +396,21 @@ where
|
|||||||
derivation_material: Option<DerivationMaterial>,
|
derivation_material: Option<DerivationMaterial>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S> std::fmt::Debug for DisconnectedMixnetClient<S>
|
||||||
|
where
|
||||||
|
S: MixnetClientStorage + Clone + 'static,
|
||||||
|
S::ReplyStore: Send + Sync,
|
||||||
|
S::GatewaysDetailsStore: Sync,
|
||||||
|
<S::ReplyStore as ReplyStorageBackend>::StorageError: Sync + Send,
|
||||||
|
<S::CredentialStore as CredentialStorage>::StorageError: Send + Sync,
|
||||||
|
<S::KeyStore as KeyStore>::StorageError: Send + Sync,
|
||||||
|
<S::GatewaysDetailsStore as GatewaysDetailsStore>::StorageError: Send + Sync,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("DisconnectedMixnetClient").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S> DisconnectedMixnetClient<S>
|
impl<S> DisconnectedMixnetClient<S>
|
||||||
where
|
where
|
||||||
S: MixnetClientStorage + Clone + 'static,
|
S: MixnetClientStorage + Clone + 'static,
|
||||||
@@ -474,6 +489,7 @@ where
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
async fn setup_client_keys(&self) -> Result<()> {
|
async fn setup_client_keys(&self) -> Result<()> {
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let key_store = self.storage.key_store();
|
let key_store = self.storage.key_store();
|
||||||
@@ -571,6 +587,7 @@ where
|
|||||||
///
|
///
|
||||||
/// This function will return an error if you try to re-register when in an already registered
|
/// This function will return an error if you try to re-register when in an already registered
|
||||||
/// state.
|
/// state.
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn setup_gateway(&mut self) -> Result<()> {
|
pub async fn setup_gateway(&mut self) -> Result<()> {
|
||||||
if !matches!(self.state, BuilderState::New) {
|
if !matches!(self.state, BuilderState::New) {
|
||||||
return Err(Error::ReregisteringGatewayNotSupported);
|
return Err(Error::ReregisteringGatewayNotSupported);
|
||||||
@@ -661,6 +678,7 @@ where
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
async fn connect_to_mixnet_common(mut self) -> Result<(BaseClient, Recipient)> {
|
async fn connect_to_mixnet_common(mut self) -> Result<(BaseClient, Recipient)> {
|
||||||
self.setup_client_keys().await?;
|
self.setup_client_keys().await?;
|
||||||
self.setup_gateway().await?;
|
self.setup_gateway().await?;
|
||||||
@@ -811,6 +829,7 @@ where
|
|||||||
/// let client = client.connect_to_mixnet().await.unwrap();
|
/// let client = client.connect_to_mixnet().await.unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn connect_to_mixnet(self) -> Result<MixnetClient> {
|
pub async fn connect_to_mixnet(self) -> Result<MixnetClient> {
|
||||||
if self.socks5_config.is_some() {
|
if self.socks5_config.is_some() {
|
||||||
return Err(Error::Socks5Config { set: true });
|
return Err(Error::Socks5Config { set: true });
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use url::Url;
|
|||||||
const DEFAULT_SDK_CLIENT_ID: &str = "_default-nym-sdk-client";
|
const DEFAULT_SDK_CLIENT_ID: &str = "_default-nym-sdk-client";
|
||||||
|
|
||||||
/// Config struct for [`crate::mixnet::MixnetClient`]
|
/// Config struct for [`crate::mixnet::MixnetClient`]
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// If the user has explicitly specified a gateway.
|
/// If the user has explicitly specified a gateway.
|
||||||
pub user_chosen_gateway: Option<String>,
|
pub user_chosen_gateway: Option<String>,
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ use nym_task::{
|
|||||||
TaskHandle,
|
TaskHandle,
|
||||||
};
|
};
|
||||||
use nym_topology::{NymRouteProvider, NymTopology};
|
use nym_topology::{NymRouteProvider, NymTopology};
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
@@ -64,6 +66,14 @@ pub struct MixnetClient {
|
|||||||
pub(crate) remember_me: RememberMe,
|
pub(crate) remember_me: RememberMe,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for MixnetClient {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("MixnetClient")
|
||||||
|
.field("address", &self.nym_address)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MixnetClient {
|
impl MixnetClient {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
@@ -194,7 +204,15 @@ impl MixnetClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for messages from the mixnet
|
/// Wait for messages from the mixnet
|
||||||
|
#[tracing::instrument]
|
||||||
pub async fn wait_for_messages(&mut self) -> Option<Vec<ReconstructedMessage>> {
|
pub async fn wait_for_messages(&mut self) -> Option<Vec<ReconstructedMessage>> {
|
||||||
|
let span = tracing::info_span!(
|
||||||
|
"wait_for_messages",
|
||||||
|
"address = {}",
|
||||||
|
self.nym_address.to_string()
|
||||||
|
);
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
self.reconstructed_receiver.next().await
|
self.reconstructed_receiver.next().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ pub trait MixnetMessageSender {
|
|||||||
where
|
where
|
||||||
M: AsRef<[u8]> + Send,
|
M: AsRef<[u8]> + Send,
|
||||||
{
|
{
|
||||||
|
let span = tracing::info_span!("send_message", "address = {}", address.to_string());
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
let lane = TransmissionLane::General;
|
let lane = TransmissionLane::General;
|
||||||
let input_msg = match surbs {
|
let input_msg = match surbs {
|
||||||
IncludedSurbs::Amount(surbs) => InputMessage::new_anonymous(
|
IncludedSurbs::Amount(surbs) => InputMessage::new_anonymous(
|
||||||
@@ -107,6 +110,13 @@ pub trait MixnetMessageSender {
|
|||||||
where
|
where
|
||||||
M: AsRef<[u8]> + Send,
|
M: AsRef<[u8]> + Send,
|
||||||
{
|
{
|
||||||
|
let span = tracing::info_span!(
|
||||||
|
"send_reply",
|
||||||
|
"recipient_tag = {}",
|
||||||
|
recipient_tag.to_string()
|
||||||
|
);
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
let lane = TransmissionLane::General;
|
let lane = TransmissionLane::General;
|
||||||
let input_msg = InputMessage::new_reply(
|
let input_msg = InputMessage::new_reply(
|
||||||
recipient_tag,
|
recipient_tag,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
.env
|
||||||
Reference in New Issue
Block a user