Compare commits

..

1 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 47fd5697ed [DO NOT MERGE] added admin-specific mixnet contract methods for adding nodes
only to be used on separate -VDnet
2024-03-13 10:43:13 +00:00
119 changed files with 940 additions and 15925 deletions
+10 -19
View File
@@ -23973,14 +23973,10 @@ function getBinInfo(path) {
let mode = external_fs_.statSync(path).mode
external_fs_.chmodSync(path, mode | 0o111)
const cmd = `${path} build-info --output=json`;
console.log(`🚚 Running ${cmd}... (for max of 3 seconds, then SIGTERM)`);
const raw = (0,external_child_process_namespaceObject.execSync)(cmd, { stdio: 'pipe', encoding: "utf8", timeout: 3000 });
const raw = (0,external_child_process_namespaceObject.execSync)(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" });
const parsed = JSON.parse(raw)
console.log(` ✅ ok`);
return parsed
} catch (_) {
console.log(` ❌ failed`);
return undefined
}
}
@@ -23990,11 +23986,8 @@ async function run(assets, algorithm, filename, cache) {
console.warn("cache is set to 'false', but we we no longer support it")
}
const directory = external_path_.join(process.env.RUNNER_TEMP || '.tmp', process.env.GITHUB_RUN_ID || '');
console.log('Temporary directory: ', directory);
try {
external_fs_.mkdirSync(directory, { recursive: true });
external_fs_.mkdirSync('.tmp');
} catch(e) {
// ignore
}
@@ -24009,13 +24002,13 @@ async function run(assets, algorithm, filename, cache) {
let sig = null;
// cache in `${WORKING_DIR}/.tmp/`
const cacheFilename = external_path_.join(directory, `${asset.name}`);
const cacheFilename = external_path_.resolve(`.tmp/${asset.name}`);
if(!external_fs_.existsSync(cacheFilename)) {
console.log(`⬇️ Downloading ${asset.browser_download_url}... to ${cacheFilename} [${numAwaiting} of ${assets.length}]`);
console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`);
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
external_fs_.writeFileSync(cacheFilename, buffer);
} else {
console.log(`💾 Loading from ${cacheFilename}`);
console.log(`Loading from ${cacheFilename}`);
buffer = Buffer.from(external_fs_.readFileSync(cacheFilename));
// console.log('Reading signature from content');
@@ -24100,7 +24093,6 @@ async function run(assets, algorithm, filename, cache) {
}
}
}
console.log(`Completed hashing ${assets.length} files`);
return hashes;
}
@@ -24130,8 +24122,8 @@ async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algo
let releases;
if(cache) {
const cacheFilename = __nccwpck_require__.ab + "releases.json";
if(!external_fs_.existsSync(__nccwpck_require__.ab + "releases.json")) {
const cacheFilename = external_path_.resolve(`.tmp/releases.json`);
if(!external_fs_.existsSync(cacheFilename)) {
releases = await octokit.paginate(
octokit.rest.repos.listReleases,
{
@@ -24141,10 +24133,10 @@ async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algo
},
(response) => response.data
);
external_fs_.writeFileSync(__nccwpck_require__.ab + "releases.json", JSON.stringify(releases, null, 2));
external_fs_.writeFileSync(cacheFilename, JSON.stringify(releases, null, 2));
} else {
console.log('Loading releases from cache...');
releases = JSON.parse(external_fs_.readFileSync(__nccwpck_require__.ab + "releases.json"));
releases = JSON.parse(external_fs_.readFileSync(cacheFilename));
}
} else {
releases = await octokit.paginate(
@@ -24180,10 +24172,9 @@ async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algo
releasesToProcess.forEach(release => {
const {tag_name, name} = release;
const matches = tag_name.match(/(\S+)-v([0-9]+\.[0-9]+(\.\S+)?)/);
const matches = tag_name.match(/(\S+)-v([0-9]+\.[0-9]+\.\S+)/);
if(!matches || matches.length < 2) {
console.warn('Could not match version structure in tag name = ', tag_name);
return;
}
@@ -11,14 +11,10 @@ function getBinInfo(path) {
let mode = fs.statSync(path).mode
fs.chmodSync(path, mode | 0o111)
const cmd = `${path} build-info --output=json`;
console.log(`🚚 Running ${cmd}... (for max of 3 seconds, then SIGTERM)`);
const raw = execSync(cmd, { stdio: 'pipe', encoding: "utf8", timeout: 3000 });
const raw = execSync(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" });
const parsed = JSON.parse(raw)
console.log(` ✅ ok`);
return parsed
} catch (_) {
console.log(` ❌ failed`);
return undefined
}
}
@@ -28,11 +24,8 @@ async function run(assets, algorithm, filename, cache) {
console.warn("cache is set to 'false', but we we no longer support it")
}
const directory = path.join(process.env.RUNNER_TEMP || '.tmp', process.env.GITHUB_RUN_ID || '');
console.log('Temporary directory: ', directory);
try {
fs.mkdirSync(directory, { recursive: true });
fs.mkdirSync('.tmp');
} catch(e) {
// ignore
}
@@ -47,13 +40,13 @@ async function run(assets, algorithm, filename, cache) {
let sig = null;
// cache in `${WORKING_DIR}/.tmp/`
const cacheFilename = path.join(directory, `${asset.name}`);
const cacheFilename = path.resolve(`.tmp/${asset.name}`);
if(!fs.existsSync(cacheFilename)) {
console.log(`⬇️ Downloading ${asset.browser_download_url}... to ${cacheFilename} [${numAwaiting} of ${assets.length}]`);
console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`);
buffer = Buffer.from(await fetch(asset.browser_download_url).then(res => res.arrayBuffer()));
fs.writeFileSync(cacheFilename, buffer);
} else {
console.log(`💾 Loading from ${cacheFilename}`);
console.log(`Loading from ${cacheFilename}`);
buffer = Buffer.from(fs.readFileSync(cacheFilename));
// console.log('Reading signature from content');
@@ -138,7 +131,6 @@ async function run(assets, algorithm, filename, cache) {
}
}
}
console.log(`Completed hashing ${assets.length} files`);
return hashes;
}
@@ -218,10 +210,9 @@ export async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrI
releasesToProcess.forEach(release => {
const {tag_name, name} = release;
const matches = tag_name.match(/(\S+)-v([0-9]+\.[0-9]+(\.\S+)?)/);
const matches = tag_name.match(/(\S+)-v([0-9]+\.[0-9]+\.\S+)/);
if(!matches || matches.length < 2) {
console.warn('Could not match version structure in tag name = ', tag_name);
return;
}
@@ -1,11 +1,6 @@
import {createHashesFromReleaseTagOrNameOrId} from './create-hashes.mjs';
const cache = true;
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-binaries-v2024.1-marabou', cache, upload: false});
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-vpn-desktop-v0.0.8', cache, upload: false, repo: 'nym-vpn-client'});
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 119065724, cache: true, upload: false});
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: '119065724', cache: true, upload: false});
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-connect-v1.1.19-snickers', cache: true, upload: false});
// await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'Nym Connect v1.1.19-snickers', cache: true, upload: false});
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 119065724, cache: true, upload: false});
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: '119065724', cache: true, upload: false});
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'nym-connect-v1.1.19-snickers', cache: true, upload: false});
await createHashesFromReleaseTagOrNameOrId({releaseTagOrNameOrId: 'Nym Connect v1.1.19-snickers', cache: true, upload: false});
+6 -3
View File
@@ -8,8 +8,8 @@ on:
required: true
type: string
workflow_dispatch:
inputs:
release_tag:
release_tag:
tag:
description: 'Release tag'
required: true
type: string
@@ -24,7 +24,10 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 18
- uses: nymtech/nym/.github/actions/nym-hash-releases@develop
- name: Install packages
run: cd ./.github/actions/nym-hash-releases && npm i
- uses: ./.github/actions/nym-hash-releases
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Generated
+70 -167
View File
@@ -557,9 +557,9 @@ dependencies = [
"bitflags 1.3.2",
"bytes",
"futures-util",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"http",
"http-body",
"hyper",
"itoa",
"matchit",
"memchr",
@@ -587,8 +587,8 @@ dependencies = [
"async-trait",
"bytes",
"futures-util",
"http 0.2.9",
"http-body 0.4.5",
"http",
"http-body",
"mime",
"rustversion",
"tower-layer",
@@ -1429,6 +1429,14 @@ dependencies = [
"thiserror",
]
[[package]]
name = "cpu-cycles"
version = "0.1.0"
dependencies = [
"cfg-if",
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.2.9"
@@ -1908,12 +1916,12 @@ dependencies = [
[[package]]
name = "darling"
version = "0.20.5"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
dependencies = [
"darling_core 0.20.5",
"darling_macro 0.20.5",
"darling_core 0.20.3",
"darling_macro 0.20.3",
]
[[package]]
@@ -1946,9 +1954,9 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.20.5"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
dependencies = [
"fnv",
"ident_case",
@@ -1982,11 +1990,11 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.20.5"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core 0.20.5",
"darling_core 0.20.3",
"quote",
"syn 2.0.38",
]
@@ -3011,7 +3019,7 @@ dependencies = [
"futures-core",
"futures-sink",
"gloo-utils",
"http 0.2.9",
"http",
"js-sys",
"pin-project",
"serde",
@@ -3080,7 +3088,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.9",
"http",
"indexmap 1.9.3",
"slab",
"tokio",
@@ -3290,17 +3298,6 @@ dependencies = [
"itoa",
]
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-api-client"
version = "0.1.0"
@@ -3322,30 +3319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http 0.2.9",
"pin-project-lite 0.2.13",
]
[[package]]
name = "http-body"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [
"bytes",
"http 1.1.0",
]
[[package]]
name = "http-body-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [
"bytes",
"futures-core",
"http 1.1.0",
"http-body 1.0.0",
"http",
"pin-project-lite 0.2.13",
]
@@ -3413,8 +3387,8 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http 0.2.9",
"http-body 0.4.5",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
@@ -3426,25 +3400,6 @@ dependencies = [
"want",
]
[[package]]
name = "hyper"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.1.0",
"http-body 1.0.0",
"httparse",
"httpdate",
"itoa",
"pin-project-lite 0.2.13",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-rustls"
version = "0.24.1"
@@ -3452,8 +3407,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
dependencies = [
"futures-util",
"http 0.2.9",
"hyper 0.14.27",
"http",
"hyper",
"rustls 0.21.10",
"tokio",
"tokio-rustls 0.24.1",
@@ -3465,28 +3420,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [
"hyper 0.14.27",
"hyper",
"pin-project-lite 0.2.13",
"tokio",
"tokio-io-timeout",
]
[[package]]
name = "hyper-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-util",
"http 1.1.0",
"http-body 1.0.0",
"hyper 1.2.0",
"pin-project-lite 0.2.13",
"socket2 0.5.4",
"tokio",
]
[[package]]
name = "iana-time-zone"
version = "0.1.58"
@@ -3811,7 +3750,7 @@ dependencies = [
"curl-sys",
"event-listener",
"futures-lite",
"http 0.2.9",
"http",
"log",
"once_cell",
"polling",
@@ -4624,7 +4563,7 @@ dependencies = [
"bytes",
"encoding_rs",
"futures-util",
"http 0.2.9",
"http",
"httparse",
"log",
"memchr",
@@ -5261,10 +5200,7 @@ dependencies = [
"dirs 4.0.0",
"futures",
"gloo-timers",
"http-body-util",
"humantime-serde",
"hyper 1.2.0",
"hyper-util",
"log",
"nym-bandwidth-controller",
"nym-config",
@@ -5273,7 +5209,6 @@ dependencies = [
"nym-explorer-client",
"nym-gateway-client",
"nym-gateway-requests",
"nym-metrics",
"nym-network-defaults",
"nym-nonexhaustive-delayqueue",
"nym-pemstore",
@@ -5587,7 +5522,7 @@ dependencies = [
"dotenvy",
"futures",
"humantime-serde",
"hyper 0.14.27",
"hyper",
"ipnetwork 0.16.0",
"log",
"nym-api-requests",
@@ -5678,9 +5613,7 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"tokio",
"tungstenite",
"wasmtimer",
"zeroize",
]
@@ -5784,16 +5717,6 @@ dependencies = [
"url",
]
[[package]]
name = "nym-metrics"
version = "0.1.0"
dependencies = [
"dashmap",
"lazy_static",
"log",
"prometheus",
]
[[package]]
name = "nym-mixnet-client"
version = "0.1.0"
@@ -5834,19 +5757,19 @@ dependencies = [
"anyhow",
"axum",
"bs58 0.5.0",
"cfg-if",
"clap 4.4.7",
"colored",
"cpu-cycles",
"cupid",
"dirs 4.0.0",
"futures",
"humantime-serde",
"lazy_static",
"log",
"nym-bin-common",
"nym-config",
"nym-contracts-common",
"nym-crypto",
"nym-metrics",
"nym-mixnet-client",
"nym-mixnode-common",
"nym-node",
@@ -5859,6 +5782,7 @@ dependencies = [
"nym-topology",
"nym-types",
"nym-validator-client",
"opentelemetry",
"rand 0.7.3",
"serde",
"serde_json",
@@ -5867,6 +5791,7 @@ dependencies = [
"tokio",
"tokio-util",
"toml 0.5.11",
"tracing",
"url",
]
@@ -5875,12 +5800,13 @@ name = "nym-mixnode-common"
version = "0.1.0"
dependencies = [
"bytes",
"cfg-if",
"cpu-cycles",
"futures",
"humantime-serde",
"log",
"nym-bin-common",
"nym-crypto",
"nym-metrics",
"nym-network-defaults",
"nym-sphinx-acknowledgements",
"nym-sphinx-addressing",
@@ -5895,6 +5821,7 @@ dependencies = [
"thiserror",
"tokio",
"tokio-util",
"tracing",
"url",
]
@@ -6022,7 +5949,7 @@ dependencies = [
"dashmap",
"fastrand 2.0.1",
"hmac 0.12.1",
"hyper 0.14.27",
"hyper",
"ipnetwork 0.16.0",
"mime",
"nym-config",
@@ -6175,7 +6102,7 @@ dependencies = [
"dotenvy",
"futures",
"hex",
"http 0.2.9",
"http",
"httpcodec",
"libp2p",
"log",
@@ -6915,7 +6842,7 @@ checksum = "a819b71d6530c4297b49b3cae2939ab3a8cc1b9f382826a1bc29dd0ca3864906"
dependencies = [
"async-trait",
"bytes",
"http 0.2.9",
"http",
"isahc",
"opentelemetry_api",
]
@@ -6929,7 +6856,7 @@ dependencies = [
"async-trait",
"futures",
"futures-executor",
"http 0.2.9",
"http",
"isahc",
"once_cell",
"opentelemetry",
@@ -7514,21 +7441,6 @@ dependencies = [
"yansi",
]
[[package]]
name = "prometheus"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
dependencies = [
"cfg-if",
"fnv",
"lazy_static",
"memchr",
"parking_lot 0.12.1",
"protobuf",
"thiserror",
]
[[package]]
name = "prometheus-client"
version = "0.19.0"
@@ -7650,17 +7562,11 @@ dependencies = [
"prost 0.12.1",
]
[[package]]
name = "protobuf"
version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "psl"
version = "2.1.22"
version = "2.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc74a6e6a56708be1cf5c4c4d1a0dc21d33b2dcaa24e731b7fa9c287ce4f916f"
checksum = "383703acfc34f7a00724846c14dc5ea4407c59e5aedcbbb18a1c0c1a23fe5013"
dependencies = [
"psl-types",
]
@@ -8056,13 +7962,13 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.3"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.6",
"regex-automata 0.4.3",
"regex-syntax 0.8.2",
]
@@ -8077,9 +7983,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.6"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
@@ -8110,9 +8016,9 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"http",
"http-body",
"hyper",
"hyper-rustls",
"ipnet",
"js-sys",
@@ -8271,7 +8177,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfac3a1df83f8d4fc96aa41dba3b86c786417b7fc0f52ec76295df2ba781aa69"
dependencies = [
"http 0.2.9",
"http",
"log",
"regex",
"rocket",
@@ -8291,8 +8197,8 @@ dependencies = [
"cookie",
"either",
"futures",
"http 0.2.9",
"hyper 0.14.27",
"http",
"hyper",
"indexmap 2.0.2",
"log",
"memchr",
@@ -8902,9 +8808,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.6.0"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981"
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
dependencies = [
"base64 0.21.4",
"chrono",
@@ -8919,11 +8825,11 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.6.0"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15"
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
dependencies = [
"darling 0.20.5",
"darling 0.20.3",
"proc-macro2",
"quote",
"syn 2.0.38",
@@ -9096,9 +9002,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.13.1"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]]
name = "snafu"
@@ -9947,10 +9853,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
"rustls 0.21.10",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.24.1",
"tungstenite",
]
@@ -10053,9 +9956,9 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"http",
"http-body",
"hyper",
"hyper-timeout",
"percent-encoding",
"pin-project",
@@ -10098,8 +10001,8 @@ dependencies = [
"bytes",
"futures-core",
"futures-util",
"http 0.2.9",
"http-body 0.4.5",
"http",
"http-body",
"http-range-header",
"httpdate",
"mime",
@@ -10377,7 +10280,7 @@ dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 0.2.9",
"http",
"httparse",
"log",
"rand 0.8.5",
+7 -20
View File
@@ -32,7 +32,7 @@ members = [
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common",
# "common/cosmwasm-smart-contracts/ephemera",
# "common/cosmwasm-smart-contracts/ephemera",
"common/cosmwasm-smart-contracts/group-contract",
"common/cosmwasm-smart-contracts/mixnet-contract",
"common/cosmwasm-smart-contracts/multisig-contract",
@@ -57,7 +57,6 @@ members = [
"common/nonexhaustive-delayqueue",
"common/nymcoconut",
"common/nym-id",
"common/nym-metrics",
"common/nymsphinx",
"common/nymsphinx/acknowledgements",
"common/nymsphinx/addressing",
@@ -113,10 +112,9 @@ members = [
"tools/nymvisor",
"tools/ts-rs-cli",
"wasm/client",
# "wasm/full-nym-wasm",
# "wasm/full-nym-wasm",
"wasm/mix-fetch",
"wasm/node-tester",
"common/nym-metrics",
]
default-members = [
@@ -132,16 +130,7 @@ default-members = [
"nym-validator-rewarder",
]
exclude = [
"explorer",
"contracts",
"nym-wallet",
"nym-connect/mobile/src-tauri",
"nym-connect/desktop",
"nym-vpn/ui/src-tauri",
"cpu-cycles",
"sdk/ffi/cpp",
]
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles", "sdk/ffi/cpp"]
[workspace.package]
authors = ["Nym Technologies SA"]
@@ -172,7 +161,7 @@ log = "0.4"
once_cell = "1.7.2"
parking_lot = "0.12.1"
rand = "0.8.5"
reqwest = { version = "0.11.22", default-features = false }
reqwest = { version = "0.11.22", default_features = false }
schemars = "0.8.1"
serde = "1.0.152"
serde_json = "1.0.91"
@@ -191,12 +180,10 @@ utoipa-swagger-ui = "3.1.5"
url = "2.4"
zeroize = "1.6.0"
prometheus = { version = "0.13.0" }
# coconut/DKG related
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch = "feature/gt-serialization-0.8.0" }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="feature/gt-serialization-0.8.0" }
group = "0.13.0"
ff = "0.13.0"
@@ -221,9 +208,9 @@ cw-controllers = { version = "=1.1.0" }
bip32 = "0.5.1"
# temporarily using a fork again (yay.) because we need staking and slashing support
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" }
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch ="nym-temp/all-validator-features" }
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.34" # same version as used by cosmrs
tendermint = "0.34" # same version as used by cosmrs
tendermint-rpc = "0.34" # same version as used by cosmrs
prost = "0.12"
@@ -1667,9 +1667,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"dev": true,
"funding": [
{
@@ -1705,9 +1705,9 @@
}
},
"node_modules/fs-monkey": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
"integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
"integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==",
"dev": true
},
"node_modules/fs.realpath": {
@@ -2430,12 +2430,12 @@
}
},
"node_modules/memfs": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
"integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
"dev": true,
"dependencies": {
"fs-monkey": "^1.0.4"
"fs-monkey": "1.0.3"
},
"engines": {
"node": ">= 4.0.0"
@@ -4047,13 +4047,13 @@
}
},
"node_modules/webpack-dev-middleware": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
"integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
"dev": true,
"dependencies": {
"colorette": "^2.0.10",
"memfs": "^3.4.3",
"memfs": "^3.4.1",
"mime-types": "^2.1.31",
"range-parser": "^1.2.1",
"schema-utils": "^4.0.0"
@@ -5800,9 +5800,9 @@
}
},
"follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"dev": true
},
"forwarded": {
@@ -5818,9 +5818,9 @@
"dev": true
},
"fs-monkey": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
"integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
"integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==",
"dev": true
},
"fs.realpath": {
@@ -6346,12 +6346,12 @@
"dev": true
},
"memfs": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
"integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
"dev": true,
"requires": {
"fs-monkey": "^1.0.4"
"fs-monkey": "1.0.3"
}
},
"merge-descriptors": {
@@ -7547,13 +7547,13 @@
}
},
"webpack-dev-middleware": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
"integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
"dev": true,
"requires": {
"colorette": "^2.0.10",
"memfs": "^3.4.3",
"memfs": "^3.4.1",
"mime-types": "^2.1.31",
"range-parser": "^1.2.1",
"schema-utils": "^4.0.0"
+3 -22
View File
@@ -27,7 +27,7 @@ tap = "1.0.1"
thiserror = { workspace = true }
url = { workspace = true, features = ["serde"] }
tungstenite = { workspace = true, default-features = false }
tokio = { workspace = true, features = ["macros"] }
tokio = { workspace = true, features = ["macros"]}
time = "0.3.17"
zeroize = { workspace = true }
@@ -38,7 +38,6 @@ nym-crypto = { path = "../crypto" }
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-metrics = { path = "../nym-metrics" }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" }
nym-pemstore = { path = "../pemstore" }
@@ -49,19 +48,6 @@ nym-credential-storage = { path = "../credential-storage" }
nym-network-defaults = { path = "../network-defaults" }
si-scale = "0.2.2"
### For serving prometheus metrics
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper]
version = "1"
features = ["server", "http1"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.http-body-util]
version = "0.1"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.hyper-util]
version = "0.1"
features = ["tokio"]
###
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream]
version = "0.1.11"
features = ["time"]
@@ -72,7 +58,6 @@ features = ["time"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite]
version = "0.20.1"
features = ["rustls-tls-native-roots"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true
@@ -106,15 +91,11 @@ tempfile = "3.1.0"
[build-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
[features]
default = []
cli = ["clap"]
fs-surb-storage = ["sqlx"]
wasm = ["nym-gateway-client/wasm"]
@@ -300,7 +300,7 @@ impl KeyManager {
/// Gets an atomically reference counted pointer to [`SharedKey`].
pub fn gateway_shared_key(&self) -> Option<Arc<SharedKeys>> {
self.gateway_shared_key.clone()
self.gateway_shared_key.as_ref().map(Arc::clone)
}
pub fn remove_gateway_key(self) -> KeyManagerBuilder {
@@ -3,30 +3,8 @@ use std::{
time::{Duration, Instant},
};
use log::{info, warn};
use nym_metrics::{inc, inc_by, metrics};
use si_scale::helpers::bibytes2;
// Metrics server
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use http_body_util::Full;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use hyper::body::Bytes;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use hyper::server::conn::http1;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use hyper::service::service_fn;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use hyper::{Request, Response};
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use hyper_util::rt::TokioIo;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use std::convert::Infallible;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use std::net::SocketAddr;
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
use tokio::net::TcpListener;
use crate::spawn_future;
// Time interval between reporting packet statistics
@@ -75,60 +53,42 @@ impl PacketStatistics {
PacketStatisticsEvent::RealPacketSent(packet_size) => {
self.real_packets_sent += 1;
self.real_packets_sent_size += packet_size;
inc!("real_packets_sent");
inc_by!("real_packets_sent_size", packet_size);
}
PacketStatisticsEvent::CoverPacketSent(packet_size) => {
self.cover_packets_sent += 1;
self.cover_packets_sent_size += packet_size;
inc!("cover_packets_sent");
inc_by!("cover_packets_sent_size", packet_size);
}
PacketStatisticsEvent::RealPacketReceived(packet_size) => {
self.real_packets_received += 1;
self.real_packets_received_size += packet_size;
inc!("real_packets_received");
inc_by!("real_packets_received_size", packet_size);
}
PacketStatisticsEvent::CoverPacketReceived(packet_size) => {
self.cover_packets_received += 1;
self.cover_packets_received_size += packet_size;
inc!("cover_packets_received");
inc_by!("cover_packets_received_size", packet_size);
}
PacketStatisticsEvent::AckReceived(packet_size) => {
self.total_acks_received += 1;
self.total_acks_received_size += packet_size;
inc!("total_acks_received");
inc_by!("total_acks_received_size", packet_size);
}
PacketStatisticsEvent::RealAckReceived(packet_size) => {
self.real_acks_received += 1;
self.real_acks_received_size += packet_size;
inc!("real_acks_received");
inc_by!("real_acks_received_size", packet_size);
}
PacketStatisticsEvent::CoverAckReceived(packet_size) => {
self.cover_acks_received += 1;
self.cover_acks_received_size += packet_size;
inc!("cover_acks_received");
inc_by!("cover_acks_received_size", packet_size);
}
PacketStatisticsEvent::RealPacketQueued => {
self.real_packets_queued += 1;
inc!("real_packets_queued");
}
PacketStatisticsEvent::RetransmissionQueued => {
self.retransmissions_queued += 1;
inc!("retransmissions_queued");
}
PacketStatisticsEvent::ReplySurbRequestQueued => {
self.reply_surbs_queued += 1;
inc!("reply_surbs_queued");
}
PacketStatisticsEvent::AdditionalReplySurbRequestQueued => {
self.additional_reply_surbs_queued += 1;
inc!("additional_reply_surbs_queued");
}
}
}
@@ -505,33 +465,6 @@ impl PacketStatisticsControl {
let snapshot_interval = Duration::from_millis(SNAPSHOT_INTERVAL_MS);
let mut snapshot_interval = tokio::time::interval(snapshot_interval);
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
log::warn!("Metrics server is not supported on wasm32-unknown-unknown");
let listener = None;
} else {
let mut metrics_port = 18000;
let listener: Option<TcpListener>;
loop {
let addr = SocketAddr::from(([0, 0, 0, 0], metrics_port));
match TcpListener::bind(addr).await {
Ok(l) => {
info!("###############################");
info!("Metrics endpoint is at: {:?}", l.local_addr());
info!("###############################");
listener = Some(l);
break;
},
Err(err) => {
log::warn!("Failed to bind metrics server: {:?}", err);
metrics_port += 1;
}
};
}
}
}
loop {
tokio::select! {
stats_event = self.stats_rx.recv() => match stats_event {
@@ -544,27 +477,6 @@ impl PacketStatisticsControl {
break;
}
},
// conditional will disable the branch if we're in wasm32-unknown-unknown
result = listener.as_ref().unwrap().accept(), if listener.is_some() => {
cfg_if::cfg_if! {
if #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] {
if let Ok((stream, _)) = result {
let io = TokioIo::new(stream);
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(io, service_fn(serve_metrics))
.await
{
warn!("Error serving connection: {:?}", err);
}
});
} else {
warn!("Error accepting connection");
}
}
}
}
_ = snapshot_interval.tick() => {
self.update_history();
self.update_rates();
@@ -589,9 +501,3 @@ impl PacketStatisticsControl {
})
}
}
async fn serve_metrics(
_: Request<hyper::body::Incoming>,
) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(Response::new(Full::new(Bytes::from(metrics!()))))
}
@@ -49,7 +49,6 @@ workspace = true
# the choice of this particular tls feature was arbitrary;
# if you reckon a different one would be more appropriate, feel free to change it
# features = ["native-tls"]
features = ["rustls-tls-native-roots"]
# wasm-only dependencies
[target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen]
@@ -20,7 +20,7 @@ use nym_gateway_requests::authentication::encrypted_address::EncryptedAddressByt
use nym_gateway_requests::iv::IV;
use nym_gateway_requests::registration::handshake::{client_handshake, SharedKeys};
use nym_gateway_requests::{
BinaryRequest, ClientControlRequest, ServerResponse, CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION,
BinaryRequest, ClientControlRequest, ServerResponse, CREDENTIAL_UPDATE_V1_PROTOCOL_VERSION,
CURRENT_PROTOCOL_VERSION,
};
use nym_network_defaults::{REMAINING_BANDWIDTH_THRESHOLD, TOKENS_TO_BURN};
@@ -438,7 +438,6 @@ impl<C, St> GatewayClient<C, St> {
ws_stream,
self.local_identity.as_ref(),
self.gateway_identity,
!self.disabled_credentials_mode,
)
.await
.map_err(GatewayClientError::RegistrationFailure),
@@ -495,13 +494,8 @@ impl<C, St> GatewayClient<C, St> {
.derive_destination_address();
let encrypted_address = EncryptedAddressBytes::new(&self_address, shared_key, &iv);
let msg = ClientControlRequest::new_authenticate(
self_address,
encrypted_address,
iv,
!self.disabled_credentials_mode,
)
.into();
let msg =
ClientControlRequest::new_authenticate(self_address, encrypted_address, iv).into();
match self.send_websocket_message(msg).await? {
ServerResponse::Authenticate {
@@ -605,7 +599,7 @@ impl<C, St> GatewayClient<C, St> {
});
};
if gateway_protocol < CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION {
if gateway_protocol < CREDENTIAL_UPDATE_V1_PROTOCOL_VERSION {
return Err(GatewayClientError::OutdatedGatewayCredentialVersion {
negotiated_protocol: Some(gateway_protocol),
});
@@ -69,10 +69,6 @@ impl PacketRouter {
}
Ok(())
}
pub fn mark_as_success(&mut self) {
self.shutdown.mark_as_success();
}
}
impl GatewayPacketRouter for PacketRouter {
@@ -44,7 +44,9 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
#[cfg(unix)]
match _conn.get_ref() {
MaybeTlsStream::Plain(stream) => Some(stream.as_raw_fd()),
&_ => None,
&_ => unreachable!(
"If tls features are enabled, the inner stream needs to be unpacked into raw fd"
),
}
#[cfg(not(unix))]
None
@@ -97,7 +99,7 @@ impl PartiallyDelegated {
pub(crate) fn split_and_listen_for_mixnet_messages(
conn: WsConn,
mut packet_router: PacketRouter,
packet_router: PacketRouter,
shared_key: Arc<SharedKeys>,
mut shutdown: TaskClient,
) -> Self {
@@ -140,7 +142,6 @@ impl PartiallyDelegated {
if match ret_err {
Err(err) => stream_sender.send(Err(err)),
Ok(_) => {
packet_router.mark_as_success();
shutdown.mark_as_success();
stream_sender.send(Ok(stream))
}
@@ -695,6 +695,46 @@ pub trait MixnetSigningClient {
)
.await
}
async fn admin_add_mixnode(
&self,
mix_node: MixNode,
cost_params: MixNodeCostParams,
owner: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::UncheckedImportMixnode {
mix_node,
cost_params,
owner,
pledge: pledge.into(),
},
vec![],
)
.await
}
async fn admin_add_gateway(
&self,
gateway: Gateway,
owner: String,
pledge: Coin,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::UncheckedImportGateway {
gateway,
owner,
pledge: pledge.into(),
},
vec![],
)
.await
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -734,6 +774,7 @@ where
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
use nym_mixnet_contract_common::ExecuteMsg;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
@@ -933,6 +974,21 @@ mod tests {
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
client.testing_resolve_all_pending_events(None).ignore()
}
ExecuteMsg::UncheckedImportMixnode {
mix_node,
cost_params,
owner,
pledge,
} => client
.admin_add_mixnode(mix_node, cost_params, owner, pledge.into(), None)
.ignore(),
ExecuteMsg::UncheckedImportGateway {
gateway,
owner,
pledge,
} => client
.admin_add_gateway(gateway, owner, pledge.into(), None)
.ignore(),
};
}
}
@@ -274,6 +274,19 @@ pub enum ExecuteMsg {
TestingResolveAllPendingEvents {
limit: Option<u32>,
},
// speedtest:
UncheckedImportMixnode {
mix_node: MixNode,
cost_params: MixNodeCostParams,
owner: String,
pledge: Coin,
},
UncheckedImportGateway {
gateway: Gateway,
owner: String,
pledge: Coin,
},
}
impl ExecuteMsg {
@@ -385,6 +398,9 @@ impl ExecuteMsg {
ExecuteMsg::TestingResolveAllPendingEvents { .. } => {
"resolving all pending events".into()
}
ExecuteMsg::UncheckedImportMixnode { .. } => "unchecked import mixnode".into(),
ExecuteMsg::UncheckedImportGateway { .. } => "unchecked import gateway".into(),
}
}
}
+1 -1
View File
@@ -837,7 +837,7 @@ mod tests {
let share3 = chunks3.clone().try_into().unwrap();
let shares = vec![share1, share2, share3];
let chunks = &[chunks1, chunks2, chunks3];
let chunks = vec![chunks1, chunks2, chunks3];
for (i, pk_i) in pks.iter().enumerate() {
let mut ciphertext_chunk_i = Vec::with_capacity(NUM_CHUNKS);
+1 -8
View File
@@ -34,13 +34,6 @@ impl MultiIpPacketCodec {
}
}
pub fn bundle_one_packet(packet: Bytes) -> Bytes {
let mut bundled_packets = BytesMut::new();
bundled_packets.extend_from_slice(&(packet.len() as u16).to_be_bytes());
bundled_packets.extend_from_slice(&packet);
bundled_packets.freeze()
}
// Append a packet to the buffer and return the buffer if it's full
pub fn append_packet(&mut self, packet: Bytes) -> Option<Bytes> {
let mut bundled_packets = BytesMut::new();
@@ -54,7 +47,7 @@ impl MultiIpPacketCodec {
}
// Flush the current buffer and return it.
pub fn flush_current_buffer(&mut self) -> Bytes {
fn flush_current_buffer(&mut self) -> Bytes {
let mut output_buffer = BytesMut::new();
std::mem::swap(&mut output_buffer, &mut self.buffer);
output_buffer.freeze()
+3 -11
View File
@@ -2,22 +2,14 @@ use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::net::{Ipv4Addr, Ipv6Addr};
// The current version of the protocol.
// The idea here is that we add new request response types at least one version before we start
// using them.
// Also, depending on the version in the client connect message the IPR could respond with a
// matching older version.
pub use v6::request;
pub use v6::response;
pub mod codec;
pub mod v6;
pub mod request;
pub mod response;
// version 3: initial version
// version 4: IPv6 support
// version 5: Add severity level to info response
// version 6: Increase the available IPs
pub const CURRENT_VERSION: u8 = 6;
pub const CURRENT_VERSION: u8 = 5;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct IpPair {
@@ -83,34 +83,6 @@ impl IpPacketRequest {
}
}
pub fn new_ping(reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
version: CURRENT_VERSION,
data: IpPacketRequestData::Ping(PingRequest {
request_id,
reply_to,
}),
},
request_id,
)
}
pub fn new_health_request(reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
version: CURRENT_VERSION,
data: IpPacketRequestData::Health(HealthRequest {
request_id,
reply_to,
}),
},
request_id,
)
}
pub fn id(&self) -> Option<u64> {
match &self.data {
IpPacketRequestData::StaticConnect(request) => Some(request.request_id),
@@ -144,35 +144,6 @@ impl IpPacketResponse {
}
}
pub fn new_pong(request_id: u64, reply_to: Recipient) -> Self {
Self {
version: CURRENT_VERSION,
data: IpPacketResponseData::Pong(PongResponse {
request_id,
reply_to,
}),
}
}
pub fn new_health_response(
request_id: u64,
reply_to: Recipient,
build_info: nym_bin_common::build_information::BinaryBuildInformationOwned,
routable: Option<bool>,
) -> Self {
Self {
version: CURRENT_VERSION,
data: IpPacketResponseData::Health(HealthResponse {
request_id,
reply_to,
reply: HealthResponseReply {
build_info,
routable,
},
}),
}
}
pub fn id(&self) -> Option<u64> {
match &self.data {
IpPacketResponseData::StaticConnect(response) => Some(response.request_id),
-2
View File
@@ -1,2 +0,0 @@
pub mod request;
pub mod response;
+9 -1
View File
@@ -25,6 +25,9 @@ tokio-util = { workspace = true, features = ["codec"] }
url = { workspace = true }
thiserror = { workspace = true }
## tracing
tracing = { version = "0.1.37", optional = true }
nym-crypto = { path = "../crypto" }
nym-network-defaults = { path = "../network-defaults" }
nym-sphinx-acknowledgements = { path = "../nymsphinx/acknowledgements" }
@@ -36,4 +39,9 @@ nym-sphinx-types = { path = "../nymsphinx/types" }
nym-task = { path = "../task" }
nym-validator-client = { path = "../client-libs/validator-client" }
nym-bin-common = { path = "../bin-common" }
nym-metrics = { path = "../nym-metrics" }
cfg-if = "1.0.0"
cpu-cycles = { path = "../../cpu-cycles", optional = true }
[features]
cpucycles = ["cpu-cycles", "tracing"]
+37
View File
@@ -2,3 +2,40 @@
// SPDX-License-Identifier: Apache-2.0
pub mod packet_processor;
pub mod verloc;
pub fn cpu_cycles() -> Result<i64, Box<dyn std::error::Error>> {
cfg_if::cfg_if! {
if #[cfg(feature = "cpucycles")] {
Ok(cpu_cycles::cpucycles()?)
} else {
Err("`cpucycles` feature is not turned on!".into())
}
}
}
#[macro_export]
macro_rules! measure {
( $x:expr ) => {{
cfg_if::cfg_if! {
if #[cfg(feature = "cpucycles")] {
let start_cycles = $crate::cpu_cycles();
// if the block needs to return something, we can return it
let r = $x;
let end_cycles = $crate::cpu_cycles();
let name = if let Some(meta) = tracing::Span::current().metadata() {
meta.name()
} else {
"measure"
};
match (start_cycles, end_cycles) {
(Ok(start), Ok(end)) => log::trace!("{} cpucycles: {}", name, end - start),
(Err(e), _) => error!("{e}"),
(_, Err(e)) => error!("{e}"),
}
r
} else {
$x
}
}
}};
}
@@ -1,9 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::measure;
use crate::packet_processor::error::MixProcessingError;
use log::*;
use nym_metrics::nanos;
use nym_sphinx_acknowledgements::surb_ack::SurbAck;
use nym_sphinx_addressing::nodes::NymNodeRoutingAddress;
use nym_sphinx_forwarding::packet::MixPacket;
@@ -15,6 +15,8 @@ use nym_sphinx_types::{
};
use std::convert::TryFrom;
use std::sync::Arc;
#[cfg(feature = "cpucycles")]
use tracing::instrument;
type ForwardAck = MixPacket;
@@ -49,11 +51,15 @@ impl SphinxPacketProcessor {
}
/// Performs a fresh sphinx unwrapping using no cache.
#[cfg_attr(
feature = "cpucycles",
instrument(skip(self, packet), fields(cpucycles))
)]
fn perform_initial_packet_processing(
&self,
packet: NymPacket,
) -> Result<NymProcessedPacket, MixProcessingError> {
nanos!("perform_initial_packet_processing", {
measure!({
packet.process(&self.sphinx_key).map_err(|err| {
debug!("Failed to unwrap NymPacket packet: {err}");
MixProcessingError::NymPacketProcessingError(err)
@@ -62,12 +68,17 @@ impl SphinxPacketProcessor {
}
/// Takes the received framed packet and tries to unwrap it from the sphinx encryption.
#[cfg_attr(
feature = "cpucycles",
instrument(skip(self, received), fields(cpucycles))
)]
fn perform_initial_unwrapping(
&self,
received: FramedNymPacket,
) -> Result<NymProcessedPacket, MixProcessingError> {
nanos!("perform_initial_unwrapping", {
measure!({
let packet = received.into_inner();
self.perform_initial_packet_processing(packet)
})
}
@@ -212,12 +223,16 @@ impl SphinxPacketProcessor {
}
}
#[cfg_attr(
feature = "cpucycles",
instrument(skip(self, received), fields(cpucycles))
)]
pub fn process_received(
&self,
received: FramedNymPacket,
) -> Result<MixProcessingResult, MixProcessingError> {
// explicit packet size will help to correctly parse final hop
nanos!("process_received", {
measure!({
let packet_size = received.packet_size();
let packet_type = received.packet_type();
+22 -15
View File
@@ -79,13 +79,7 @@ impl NymNetworkDetails {
pub fn new_from_env() -> Self {
fn get_optional_env<K: AsRef<OsStr>>(env: K) -> Option<String> {
match var(env) {
Ok(var) => {
if var.is_empty() {
None
} else {
Some(var)
}
}
Ok(var) => Some(var),
Err(VarError::NotPresent) => None,
err => panic!("Unable to set: {:?}", err),
}
@@ -119,15 +113,28 @@ impl NymNetworkDetails {
Some(var(var_names::NYM_API).expect("nym api not set")),
get_optional_env(var_names::NYXD_WEBSOCKET),
))
.with_mixnet_contract(get_optional_env(var_names::MIXNET_CONTRACT_ADDRESS))
.with_vesting_contract(get_optional_env(var_names::VESTING_CONTRACT_ADDRESS))
.with_coconut_bandwidth_contract(get_optional_env(
var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
.with_mixnet_contract(Some(
var(var_names::MIXNET_CONTRACT_ADDRESS).expect("mixnet contract not set"),
))
.with_vesting_contract(Some(
var(var_names::VESTING_CONTRACT_ADDRESS).expect("vesting contract not set"),
))
.with_coconut_bandwidth_contract(Some(
var(var_names::COCONUT_BANDWIDTH_CONTRACT_ADDRESS)
.expect("coconut bandwidth contract not set"),
))
.with_group_contract(Some(
var(var_names::GROUP_CONTRACT_ADDRESS).expect("group contract not set"),
))
.with_multisig_contract(Some(
var(var_names::MULTISIG_CONTRACT_ADDRESS).expect("multisig contract not set"),
))
.with_coconut_dkg_contract(Some(
var(var_names::COCONUT_DKG_CONTRACT_ADDRESS).expect("coconut dkg contract not set"),
))
.with_ephemera_contract(Some(
var(var_names::EPHEMERA_CONTRACT_ADDRESS).expect("ephemera contract not set"),
))
.with_group_contract(get_optional_env(var_names::GROUP_CONTRACT_ADDRESS))
.with_multisig_contract(get_optional_env(var_names::MULTISIG_CONTRACT_ADDRESS))
.with_coconut_dkg_contract(get_optional_env(var_names::COCONUT_DKG_CONTRACT_ADDRESS))
.with_ephemera_contract(get_optional_env(var_names::EPHEMERA_CONTRACT_ADDRESS))
.with_service_provider_directory_contract(get_optional_env(
var_names::SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS,
))
+5 -7
View File
@@ -16,13 +16,11 @@ pub const MIXNET_CONTRACT_ADDRESS: &str =
"n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr";
pub const VESTING_CONTRACT_ADDRESS: &str =
"n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw";
pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "";
pub const GROUP_CONTRACT_ADDRESS: &str = "";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "";
pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub const GROUP_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub const MULTISIG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub const EPHEMERA_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0";
pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy";
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
-17
View File
@@ -1,17 +0,0 @@
[package]
name = "nym-metrics"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
prometheus = { workspace = true }
log = { workspace = true }
dashmap = { workspace = true }
lazy_static = "1.4"
-278
View File
@@ -1,278 +0,0 @@
use dashmap::DashMap;
pub use log::error;
use log::{debug, warn};
use std::fmt;
pub use std::time::Instant;
use prometheus::{core::Collector, Counter, Encoder as _, Gauge, Registry, TextEncoder};
#[macro_export]
macro_rules! prepend_package_name {
($name: literal) => {
&format!(
"{}_{}",
std::module_path!()
.split("::")
.next()
.unwrap_or("x")
.to_string(),
$name
)
};
}
#[macro_export]
macro_rules! inc_by {
($name:literal, $x:expr) => {
$crate::REGISTRY.inc_by($crate::prepend_package_name!($name), $x as f64);
};
}
#[macro_export]
macro_rules! inc {
($name:literal) => {
$crate::REGISTRY.inc($crate::prepend_package_name!($name));
};
}
#[macro_export]
macro_rules! metrics {
() => {
$crate::REGISTRY.to_string();
};
}
#[macro_export]
macro_rules! nanos {
( $name:literal, $x:expr ) => {{
let start = $crate::Instant::now();
// if the block needs to return something, we can return it
let r = $x;
let duration = start.elapsed().as_nanos() as f64;
let name = $crate::prepend_package_name!($name);
$crate::REGISTRY.inc_by(&format!("{}_nanos", $name), duration);
r
}};
}
lazy_static::lazy_static! {
pub static ref REGISTRY: MetricsController = MetricsController::default();
}
#[derive(Default)]
pub struct MetricsController {
registry: Registry,
registry_index: DashMap<String, Metric>,
}
enum Metric {
C(Box<Counter>),
G(Box<Gauge>),
}
fn fq_name(c: &dyn Collector) -> String {
c.desc()
.first()
.map(|d| d.fq_name.clone())
.unwrap_or_default()
}
impl Metric {
#[inline(always)]
fn fq_name(&self) -> String {
match self {
Metric::C(c) => fq_name(c.as_ref()),
Metric::G(g) => fq_name(g.as_ref()),
}
}
#[inline(always)]
fn inc(&self) {
match self {
Metric::C(c) => c.inc(),
Metric::G(g) => g.inc(),
}
}
#[inline(always)]
fn inc_by(&self, value: f64) {
match self {
Metric::C(c) => c.inc_by(value),
Metric::G(g) => g.add(value),
}
}
#[inline(always)]
fn set(&self, value: f64) {
match self {
Metric::C(_c) => {
warn!("Cannot set value for counter {:?}", self.fq_name());
}
Metric::G(g) => g.set(value),
}
}
}
impl fmt::Display for MetricsController {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let metrics = self.gather();
let output = match String::from_utf8(metrics) {
Ok(output) => output,
Err(e) => return write!(f, "Error decoding metrics to String: {}", e),
};
write!(f, "{}", output)
}
}
impl MetricsController {
#[inline(always)]
pub fn gather(&self) -> Vec<u8> {
let mut buffer = vec![];
let encoder = TextEncoder::new();
let metrics = self.registry.gather();
match encoder.encode(&metrics, &mut buffer) {
Ok(_) => {}
Err(e) => error!("Error encoding metrics to buffer: {}", e),
}
buffer
}
pub fn to_writer(&self, writer: &mut dyn std::io::Write) {
let metrics = self.gather();
match writer.write_all(&metrics) {
Ok(_) => {}
Err(e) => error!("Error writing metrics to writer: {}", e),
}
}
pub fn set(&self, name: &str, value: f64) {
if let Some(metric) = self.registry_index.get(name) {
metric.set(value);
} else {
let gauge = match Gauge::new(sanitize_metric_name(name), name) {
Ok(g) => g,
Err(e) => {
debug!("Failed to create gauge {:?}:\n{}", name, e);
return;
}
};
self.register_gauge(Box::new(gauge));
self.set(name, value)
}
}
pub fn inc(&self, name: &str) {
if let Some(metric) = self.registry_index.get(name) {
metric.inc();
} else {
let counter = match Counter::new(sanitize_metric_name(name), name) {
Ok(c) => c,
Err(e) => {
debug!("Failed to create counter {:?}:\n{}", name, e);
return;
}
};
self.register_counter(Box::new(counter));
self.inc(name)
}
}
pub fn inc_by(&self, name: &str, value: f64) {
if let Some(metric) = self.registry_index.get(name) {
metric.inc_by(value);
} else {
let counter = match Counter::new(sanitize_metric_name(name), name) {
Ok(c) => c,
Err(e) => {
debug!("Failed to create counter {:?}:\n{}", name, e);
return;
}
};
self.register_counter(Box::new(counter));
self.inc_by(name, value)
}
}
fn register_gauge(&self, metric: Box<Gauge>) {
let fq_name = metric
.desc()
.first()
.map(|d| d.fq_name.clone())
.unwrap_or_default();
if self.registry_index.contains_key(&fq_name) {
return;
}
match self.registry.register(metric.clone()) {
Ok(_) => {
self.registry_index
.insert(fq_name, Metric::G(metric.clone()));
}
Err(e) => {
debug!("Failed to register {:?}:\n{}", fq_name, e)
}
}
}
fn register_counter(&self, metric: Box<Counter>) {
let fq_name = metric
.desc()
.first()
.map(|d| d.fq_name.clone())
.unwrap_or_default();
if self.registry_index.contains_key(&fq_name) {
return;
}
match self.registry.register(metric.clone()) {
Ok(_) => {
self.registry_index
.insert(fq_name, Metric::C(metric.clone()));
}
Err(e) => {
debug!("Failed to register {:?}:\n{}", fq_name, e)
}
}
}
}
fn sanitize_metric_name(name: &str) -> String {
// The first character must be [a-zA-Z_:], and all subsequent characters must be [a-zA-Z0-9_:].
let mut out = String::with_capacity(name.len());
let mut is_invalid: fn(char) -> bool = invalid_metric_name_start_character;
for c in name.chars() {
if is_invalid(c) {
out.push('_');
} else {
out.push(c);
}
is_invalid = invalid_metric_name_character;
}
out
}
#[inline]
fn invalid_metric_name_start_character(c: char) -> bool {
// Essentially, needs to match the regex pattern of [a-zA-Z_:].
!(c.is_ascii_alphabetic() || c == '_' || c == ':')
}
#[inline]
fn invalid_metric_name_character(c: char) -> bool {
// Essentially, needs to match the regex pattern of [a-zA-Z0-9_:].
!(c.is_ascii_alphanumeric() || c == '_' || c == ':')
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sanitization() {
assert_eq!(
sanitize_metric_name("packets_sent_34.242.65.133:1789"),
"packets_sent_34_242_65_133:1789"
)
}
}
+13
View File
@@ -6,6 +6,7 @@ use crate::interval::storage as interval_storage;
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
use crate::mixnodes::storage as mixnode_storage;
use crate::rewards::storage as rewards_storage;
use crate::speedtest_tmp::{admin_add_gateway, admin_add_mixnode};
use cosmwasm_std::{
entry_point, to_binary, Addr, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
};
@@ -372,6 +373,18 @@ pub fn execute(
ExecuteMsg::TestingResolveAllPendingEvents { limit } => {
crate::testing::transactions::try_resolve_all_pending_events(deps, env, limit)
}
ExecuteMsg::UncheckedImportMixnode {
mix_node,
cost_params,
owner,
pledge,
} => admin_add_mixnode(deps, env, info, mix_node, cost_params, pledge, owner),
ExecuteMsg::UncheckedImportGateway {
gateway,
owner,
pledge,
} => admin_add_gateway(deps, env, info, gateway, pledge, owner),
}
}
+2
View File
@@ -19,3 +19,5 @@ mod support;
#[cfg(feature = "contract-testing")]
mod testing;
mod speedtest_tmp;
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::gateways::storage::gateways;
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
use crate::mixnodes::helpers::save_new_mixnode;
use crate::support::helpers::ensure_no_existing_bond;
use cosmwasm_std::{Coin, DepsMut, Env, MessageInfo, Response};
use mixnet_contract_common::error::MixnetContractError;
use mixnet_contract_common::{Gateway, GatewayBond, MixNode, MixNodeCostParams};
pub fn admin_add_mixnode(
deps: DepsMut<'_>,
env: Env,
info: MessageInfo,
mixnode: MixNode,
cost_params: MixNodeCostParams,
pledge: Coin,
owner: String,
) -> Result<Response, MixnetContractError> {
let state = mixnet_params_storage::CONTRACT_STATE.load(deps.storage)?;
// check if this is executed by the owner, if not reject the transaction
if info.sender != state.owner {
return Err(MixnetContractError::Unauthorized);
}
let owner = deps.api.addr_validate(&owner)?;
ensure_no_existing_bond(&owner, deps.storage)?;
save_new_mixnode(deps.storage, env, mixnode, cost_params, owner, None, pledge)?;
Ok(Response::new())
}
pub fn admin_add_gateway(
deps: DepsMut<'_>,
env: Env,
info: MessageInfo,
gateway: Gateway,
pledge: Coin,
owner: String,
) -> Result<Response, MixnetContractError> {
let state = mixnet_params_storage::CONTRACT_STATE.load(deps.storage)?;
// check if this is executed by the owner, if not reject the transaction
if info.sender != state.owner {
return Err(MixnetContractError::Unauthorized);
}
let owner = deps.api.addr_validate(&owner)?;
ensure_no_existing_bond(&owner, deps.storage)?;
let bond = GatewayBond::new(pledge, owner, env.block.height, gateway, None);
gateways().save(deps.storage, bond.identity(), &bond)?;
Ok(Response::new())
}
+13 -16
View File
@@ -18,7 +18,7 @@
},
"devDependencies": {
"@tsconfig/recommended": "^1.0.1",
"prettier": "^2.8.7",
"prettier": "^2.2.1",
"typescript": "^4.1.3"
}
},
@@ -570,9 +570,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"funding": [
{
"type": "individual",
@@ -875,18 +875,15 @@
}
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/protobufjs": {
@@ -1667,9 +1664,9 @@
}
},
"follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
},
"fsevents": {
"version": "2.3.2",
@@ -1888,9 +1885,9 @@
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
"dev": true
},
"protobufjs": {
@@ -682,8 +682,6 @@ Which should return:
Proxying various full node services through port 80 can then be done by creating a file with the following at `/etc/nginx/sites-enabled/nyxd-webrequests.conf`:
Setting up a reverse proxy using a webserver such as Nginx allows you to easily configure SSL certificates for the endpoints. When running on mainnet, it is recommended to encrypt all web traffic to your node.
```sh
### To expose RPC server
server {
@@ -697,14 +695,6 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /websocket {
proxy_pass http://127.0.0.1:26657;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
}
### To expose Cosmos API server
@@ -2,6 +2,10 @@
[//]: # (> The nym-api binary was built in the [building nym]&#40;../binaries/building-nym.md&#41; section. If you haven't yet built Nym and want to run the code, go there first. You can build just the API with `cargo build --release --bin nym-api`.)
> The `nym-api` binary will be released in the immediate future - we're releasing this document beforehand so that validators have information as soon as possible and get an idea of what to expect. This doc will be expanded over time as we release the API binary itself as well as start enabling functionality.
>
> You can build the API with `cargo build --release --bin nym-api`.
> Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets.
## What is the Nym API?
+2
View File
@@ -22,3 +22,5 @@ REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYXD="http://127.0.0.1:26657"
NYM_API="http://127.0.0.1:8000"
DKG_TIME_CONFIGURATION="600,300,300,60,60,1209600"
+7 -2
View File
@@ -11,13 +11,18 @@ MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr
VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
GROUP_CONTRACT_ADDRESS=n1rw8fw2mpcpzzq3jpa4e52ufawnmj5a4u68p35umvgskewuw0nlzsaa5w4m
MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_DKG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
EPHEMERA_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
NYXD="https://rpc.nymtech.net"
NYM_API="https://validator.nymtech.net/api/"
NYXD_WS="wss://rpc.nymtech.net/websocket"
EXPLORER_API="https://explorer.nymtech.net/api/"
DKG_TIME_CONFIGURATION="259200,300,300,60,60,1209600"
+1
View File
@@ -25,4 +25,5 @@ EXPLORER_API=https://qa-network-explorer.qa.nymte.ch/api
NYXD="https://qa-validator.qa.nymte.ch"
NYM_API="https://qa-nym-api.qa.nymte.ch/api"
DKG_TIME_CONFIGURATION="600,300,300,60,60,1209600"
EXIT_POLICY="https://nymtech.net/.wellknown/network-requester/exit-policy.txt"
+6 -6
View File
@@ -112,12 +112,12 @@ pub(crate) struct NodeStats {
)]
previous_update_time: SystemTime,
packets_received_since_startup: f64,
packets_sent_since_startup: f64,
packets_explicitly_dropped_since_startup: f64,
packets_received_since_last_update: f64,
packets_sent_since_last_update: f64,
packets_explicitly_dropped_since_last_update: f64,
packets_received_since_startup: u64,
packets_sent_since_startup: u64,
packets_explicitly_dropped_since_startup: u64,
packets_received_since_last_update: u64,
packets_sent_since_last_update: u64,
packets_explicitly_dropped_since_last_update: u64,
}
#[derive(Clone, Serialize, Deserialize, JsonSchema)]
-8
View File
@@ -28,14 +28,6 @@ nym-sphinx = { path = "../../common/nymsphinx" }
nym-credentials = { path = "../../common/credentials" }
nym-credentials-interface = { path = "../../common/credentials-interface" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
workspace = true
features = ["time"]
[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer]
workspace = true
features = ["tokio"]
[dependencies.tungstenite]
workspace = true
default-features = false
+2 -2
View File
@@ -13,7 +13,7 @@ pub mod models;
pub mod registration;
pub mod types;
pub const CURRENT_PROTOCOL_VERSION: u8 = CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION;
pub const CURRENT_PROTOCOL_VERSION: u8 = CREDENTIAL_UPDATE_V1_PROTOCOL_VERSION;
/// Defines the current version of the communication protocol between gateway and clients.
/// It has to be incremented for any breaking change.
@@ -21,7 +21,7 @@ pub const CURRENT_PROTOCOL_VERSION: u8 = CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION;
// 1 - initial release
// 2 - changes to client credentials structure
pub const INITIAL_PROTOCOL_VERSION: u8 = 1;
pub const CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION: u8 = 2;
pub const CREDENTIAL_UPDATE_V1_PROTOCOL_VERSION: u8 = 2;
pub type GatewayMac = HmacOutput<GatewayIntegrityHmacAlgorithm>;
@@ -24,18 +24,11 @@ impl<'a> ClientHandshake<'a> {
ws_stream: &'a mut S,
identity: &'a nym_crypto::asymmetric::identity::KeyPair,
gateway_pubkey: identity::PublicKey,
expects_credential_usage: bool,
) -> Self
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
let mut state = State::new(
rng,
ws_stream,
identity,
Some(gateway_pubkey),
expects_credential_usage,
);
let mut state = State::new(rng, ws_stream, identity, Some(gateway_pubkey));
ClientHandshake {
handshake_future: Box::pin(async move {
@@ -25,7 +25,4 @@ pub enum HandshakeError {
MalformedRequest,
#[error("sent request was malformed")]
HandshakeFailure,
#[error("timed out waiting for a handshake message")]
Timeout,
}
@@ -26,7 +26,7 @@ impl<'a> GatewayHandshake<'a> {
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
let mut state = State::new(rng, ws_stream, identity, None, true);
let mut state = State::new(rng, ws_stream, identity, None);
GatewayHandshake {
handshake_future: Box::pin(async move {
// If any step along the way failed (that are non-network related),
@@ -30,19 +30,11 @@ pub async fn client_handshake<'a, S>(
ws_stream: &'a mut S,
identity: &'a identity::KeyPair,
gateway_pubkey: identity::PublicKey,
expects_credential_usage: bool,
) -> Result<SharedKeys, HandshakeError>
where
S: Stream<Item = WsItem> + Sink<WsMessage> + Unpin + Send + 'a,
{
ClientHandshake::new(
rng,
ws_stream,
identity,
gateway_pubkey,
expects_credential_usage,
)
.await
ClientHandshake::new(rng, ws_stream, identity, gateway_pubkey).await
}
#[cfg(not(target_arch = "wasm32"))]
@@ -1,4 +1,4 @@
// Copyright 2020-2024 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::registration::handshake::error::HandshakeError;
@@ -15,17 +15,9 @@ use nym_crypto::{
};
use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewaySharedKeyHkdfAlgorithm};
use rand::{CryptoRng, RngCore};
use std::convert::TryInto;
use std::str::FromStr;
use std::time::Duration;
use std::convert::{TryFrom, TryInto};
use tungstenite::Message as WsMessage;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::timeout;
#[cfg(target_arch = "wasm32")]
use wasmtimer::tokio::timeout;
/// Handshake state.
pub(crate) struct State<'a, S> {
/// The underlying WebSocket stream.
@@ -44,10 +36,6 @@ pub(crate) struct State<'a, S> {
/// The known or received public identity key of the remote.
/// Ideally it would always be known before the handshake was initiated.
remote_pubkey: Option<identity::PublicKey>,
// this field is really out of place here, however, we need to propagate this information somehow
// in order to establish correct protocol for backwards compatibility reasons
expects_credential_usage: bool,
}
impl<'a, S> State<'a, S> {
@@ -56,7 +44,6 @@ impl<'a, S> State<'a, S> {
ws_stream: &'a mut S,
identity: &'a identity::KeyPair,
remote_pubkey: Option<identity::PublicKey>,
expects_credential_usage: bool,
) -> Self {
let ephemeral_keypair = encryption::KeyPair::new(rng);
State {
@@ -65,7 +52,6 @@ impl<'a, S> State<'a, S> {
identity,
remote_pubkey,
derived_shared_keys: None,
expects_credential_usage,
}
}
@@ -81,8 +67,15 @@ impl<'a, S> State<'a, S> {
self.identity
.public_key()
.to_bytes()
.into_iter()
.chain(self.ephemeral_keypair.public_key().to_bytes())
.iter()
.cloned()
.chain(
self.ephemeral_keypair
.public_key()
.to_bytes()
.iter()
.cloned(),
)
.collect()
}
@@ -139,8 +132,9 @@ impl<'a, S> State<'a, S> {
.ephemeral_keypair
.public_key()
.to_bytes()
.into_iter()
.chain(remote_ephemeral_key.to_bytes())
.iter()
.cloned()
.chain(remote_ephemeral_key.to_bytes().iter().cloned())
.collect();
let signature = self.identity.private_key().sign(message);
@@ -183,8 +177,15 @@ impl<'a, S> State<'a, S> {
// g^y || g^x, if y is remote and x is local
let signed_payload: Vec<_> = remote_ephemeral_key
.to_bytes()
.into_iter()
.chain(self.ephemeral_keypair.public_key().to_bytes())
.iter()
.cloned()
.chain(
self.ephemeral_keypair
.public_key()
.to_bytes()
.iter()
.cloned(),
)
.collect();
self.remote_pubkey
@@ -199,54 +200,33 @@ impl<'a, S> State<'a, S> {
self.remote_pubkey = Some(remote_pubkey)
}
async fn _receive_handshake_message(&mut self) -> Result<Vec<u8>, HandshakeError>
where
S: Stream<Item = WsItem> + Unpin,
{
loop {
let Some(msg) = self.ws_stream.next().await else {
return Err(HandshakeError::ClosedStream);
};
let Ok(msg) = msg else {
return Err(HandshakeError::NetworkError);
};
match msg {
WsMessage::Text(ref ws_msg) => {
match types::RegistrationHandshake::from_str(ws_msg) {
Ok(reg_handshake_msg) => {
return match reg_handshake_msg {
// hehe, that's a bit disgusting that the type system requires we explicitly ignore the
// protocol_version field that we actually never attach at this point
// yet another reason for the overdue refactor
types::RegistrationHandshake::HandshakePayload { data, .. } => {
Ok(data)
}
types::RegistrationHandshake::HandshakeError { message } => {
Err(HandshakeError::RemoteError(message))
}
};
}
Err(_) => {
error!("Received a non-handshake message during the registration handshake! It's getting dropped. The received content was: '{msg}'");
continue;
}
}
}
_ => error!("Received non-text message during registration handshake"),
}
}
}
pub(crate) async fn receive_handshake_message(&mut self) -> Result<Vec<u8>, HandshakeError>
where
S: Stream<Item = WsItem> + Unpin,
{
// TODO: make timeout duration configurable
timeout(Duration::from_secs(5), self._receive_handshake_message())
.await
.map_err(|_| HandshakeError::Timeout)?
loop {
if let Some(msg) = self.ws_stream.next().await {
if let Ok(msg) = msg {
match msg {
WsMessage::Text(ws_msg) => match types::RegistrationHandshake::try_from(ws_msg) {
Ok(reg_handshake_msg) => return match reg_handshake_msg {
// hehe, that's a bit disgusting that the type system requires we explicitly ignore the
// protocol_version field that we actually never attach at this point
// yet another reason for the overdue refactor
types::RegistrationHandshake::HandshakePayload { data, .. } => Ok(data),
types::RegistrationHandshake::HandshakeError { message } => Err(HandshakeError::RemoteError(message)),
},
Err(_) => error!("Received a non-handshake message during the registration handshake! It's getting dropped."),
},
_ => error!("Received non-text message during registration handshake"),
}
} else {
return Err(HandshakeError::NetworkError);
}
} else {
return Err(HandshakeError::ClosedStream);
}
}
}
// upon receiving this, the receiver should terminate the handshake
@@ -271,8 +251,7 @@ impl<'a, S> State<'a, S> {
where
S: Sink<WsMessage> + Unpin,
{
let handshake_message =
types::RegistrationHandshake::new_payload(payload, self.expects_credential_usage);
let handshake_message = types::RegistrationHandshake::new_payload(payload);
self.ws_stream
.send(WsMessage::Text(handshake_message.try_into().unwrap()))
.await
+5 -31
View File
@@ -5,7 +5,7 @@ use crate::authentication::encrypted_address::EncryptedAddressBytes;
use crate::iv::IV;
use crate::models::{CredentialSpendingRequest, OldV1Credential};
use crate::registration::handshake::SharedKeys;
use crate::{GatewayMacSize, CURRENT_PROTOCOL_VERSION, INITIAL_PROTOCOL_VERSION};
use crate::{GatewayMacSize, CURRENT_PROTOCOL_VERSION};
use log::error;
use nym_credentials::coconut::bandwidth::CredentialSpendingData;
use nym_credentials_interface::{CoconutError, UnknownCredentialType};
@@ -19,7 +19,6 @@ use nym_sphinx::params::{GatewayEncryptionAlgorithm, GatewayIntegrityHmacAlgorit
use nym_sphinx::DestinationAddressBytes;
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
use std::str::FromStr;
use std::string::FromUtf8Error;
use thiserror::Error;
use tungstenite::protocol::Message;
@@ -38,17 +37,9 @@ pub enum RegistrationHandshake {
}
impl RegistrationHandshake {
pub fn new_payload(data: Vec<u8>, will_use_credentials: bool) -> Self {
// if we're not going to be using credentials, advertise lower protocol version to allow connection
// to wider range of gateways
let protocol_version = if will_use_credentials {
Some(CURRENT_PROTOCOL_VERSION)
} else {
Some(INITIAL_PROTOCOL_VERSION)
};
pub fn new_payload(data: Vec<u8>) -> Self {
RegistrationHandshake::HandshakePayload {
protocol_version,
protocol_version: Some(CURRENT_PROTOCOL_VERSION),
data,
}
}
@@ -60,19 +51,11 @@ impl RegistrationHandshake {
}
}
impl FromStr for RegistrationHandshake {
type Err = serde_json::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
impl TryFrom<String> for RegistrationHandshake {
type Error = serde_json::Error;
fn try_from(msg: String) -> Result<Self, serde_json::Error> {
msg.parse()
serde_json::from_str(&msg)
}
}
@@ -172,18 +155,9 @@ impl ClientControlRequest {
address: DestinationAddressBytes,
enc_address: EncryptedAddressBytes,
iv: IV,
uses_credentials: bool,
) -> Self {
// if we're not going to be using credentials, advertise lower protocol version to allow connection
// to wider range of gateways
let protocol_version = if uses_credentials {
Some(CURRENT_PROTOCOL_VERSION)
} else {
Some(INITIAL_PROTOCOL_VERSION)
};
ClientControlRequest::Authenticate {
protocol_version,
protocol_version: Some(CURRENT_PROTOCOL_VERSION),
address: address.as_base58_string(),
enc_address: enc_address.to_base58_string(),
iv: iv.to_base58_string(),
+8 -9
View File
@@ -88,19 +88,18 @@ impl OverrideConfig {
if config.network_requester.enabled
&& config.storage_paths.network_requester_config.is_none()
{
config = config.with_default_network_requester_config_path();
}
if config.ip_packet_router.enabled && config.storage_paths.ip_packet_router_config.is_none()
Ok(config.with_default_network_requester_config_path())
} else if config.ip_packet_router.enabled
&& config.storage_paths.ip_packet_router_config.is_none()
{
config = config.with_default_ip_packet_router_config_path();
Ok(config.with_default_ip_packet_router_config_path())
} else {
Ok(config)
}
Ok(config)
}
}
#[derive(Default, Debug)]
#[derive(Default)]
pub(crate) struct OverrideNetworkRequesterConfig {
pub(crate) fastmode: bool,
pub(crate) no_cover: bool,
@@ -113,7 +112,7 @@ pub(crate) struct OverrideNetworkRequesterConfig {
pub(crate) statistics_recipient: Option<String>,
}
#[derive(Default, Debug)]
#[derive(Default)]
pub(crate) struct OverrideIpPacketRouterConfig {
// TODO
}
+4 -6
View File
@@ -17,7 +17,7 @@ use std::{fs, io};
use super::helpers::OverrideIpPacketRouterConfig;
#[derive(Args, Clone, Debug)]
#[derive(Args, Clone)]
pub struct Init {
/// Id of the gateway we want to create config for
#[clap(long)]
@@ -82,11 +82,11 @@ pub struct Init {
statistics_service_url: Option<url::Url>,
/// Allows this gateway to run an embedded network requester for minimal network overhead
#[clap(long)]
#[clap(long, conflicts_with = "with_ip_packet_router")]
with_network_requester: bool,
/// Allows this gateway to run an embedded network requester for minimal network overhead
#[clap(long, hide = true)]
#[clap(long, hide = true, conflicts_with = "with_network_requester")]
with_ip_packet_router: bool,
// ##### NETWORK REQUESTER FLAGS #####
@@ -243,9 +243,7 @@ pub async fn execute(args: Init) -> anyhow::Result<()> {
if config.network_requester.enabled {
initialise_local_network_requester(&config, nr_opts, *identity_keys.public_key())
.await?;
}
if config.ip_packet_router.enabled {
} else if config.ip_packet_router.enabled {
initialise_local_ip_packet_router(&config, ip_opts, *identity_keys.public_key())
.await?;
}
+2 -1
View File
@@ -5,6 +5,7 @@ use crate::Cli;
use clap::CommandFactory;
use clap::Subcommand;
use nym_bin_common::completions::{fig_generate, ArgShell};
use std::error::Error;
pub(crate) mod build_info;
pub(crate) mod helpers;
@@ -49,7 +50,7 @@ pub(crate) enum Commands {
GenerateFigSpec,
}
pub(crate) async fn execute(args: Cli) -> anyhow::Result<()> {
pub(crate) async fn execute(args: Cli) -> Result<(), Box<dyn Error + Send + Sync>> {
let bin_name = "nym-gateway";
match args.command {
+2 -2
View File
@@ -87,11 +87,11 @@ pub struct Run {
statistics_service_url: Option<url::Url>,
/// Allows this gateway to run an embedded network requester for minimal network overhead
#[arg(long)]
#[arg(long, conflicts_with = "with_ip_packet_router")]
with_network_requester: Option<bool>,
/// Allows this gateway to run an embedded network requester for minimal network overhead
#[arg(long, hide = true)]
#[arg(long, hide = true, conflicts_with = "with_network_requester")]
with_ip_packet_router: Option<bool>,
// ##### NETWORK REQUESTER FLAGS #####
+2 -1
View File
@@ -11,6 +11,7 @@ use nym_bin_common::bin_info;
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
use nym_bin_common::output_format::OutputFormat;
use nym_network_defaults::setup_env;
use std::error::Error;
use std::sync::OnceLock;
mod commands;
@@ -41,7 +42,7 @@ struct Cli {
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
setup_logging();
let args = Cli::parse();
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-only
use super::websocket::message_receiver::{IsActiveRequestSender, MixMessageSender};
use crate::node::client_handling::embedded_clients::LocalEmbeddedClientHandle;
use crate::node::client_handling::embedded_network_requester::LocalNetworkRequesterHandle;
use dashmap::DashMap;
use log::warn;
use nym_sphinx::DestinationAddressBytes;
@@ -12,8 +12,8 @@ enum ActiveClient {
/// Handle to a remote client connected via a network socket.
Remote(ClientIncomingChannels),
/// Handle to a locally (inside the same process) running client.
Embedded(LocalEmbeddedClientHandle),
/// Handle to a locally (inside the same process) running network requester client.
Embedded(LocalNetworkRequesterHandle),
}
impl ActiveClient {
@@ -149,14 +149,13 @@ impl ActiveClientsStore {
}
}
/// Inserts a handle to the embedded client
pub(crate) fn insert_embedded(&self, local_client_handle: LocalEmbeddedClientHandle) {
let key = local_client_handle.client_destination();
let entry = ActiveClient::Embedded(local_client_handle);
/// Inserts a handle to the embedded network requester
pub(crate) fn insert_embedded(&self, local_nr_handle: LocalNetworkRequesterHandle) {
let key = local_nr_handle.client_destination();
let entry = ActiveClient::Embedded(local_nr_handle);
if self.inner.insert(key, entry).is_some() {
// this is literally impossible since we're starting the local embedded client before
// even spawning the websocket listener task
panic!("somehow we already had a client with the same address as our local embedded client!")
// this is literally impossible since we're starting local NR before even spawning the websocket listener task
panic!("somehow we already had a client with the same address as our local NR!")
}
}
@@ -12,15 +12,15 @@ use nym_sphinx::DestinationAddressBytes;
use nym_task::TaskClient;
#[derive(Debug)]
pub(crate) struct LocalEmbeddedClientHandle {
/// Nym address of the embedded client.
pub(crate) struct LocalNetworkRequesterHandle {
/// Nym address of the embedded network requester.
pub(crate) address: Recipient,
/// Message channel used internally to forward any received mix packets to the client.
/// Message channel used internally to forward any received mix packets to the network requester.
pub(crate) mix_message_sender: MixMessageSender,
}
impl LocalEmbeddedClientHandle {
impl LocalNetworkRequesterHandle {
pub(crate) fn new(address: Recipient, mix_message_sender: MixMessageSender) -> Self {
Self {
address,
@@ -28,6 +28,17 @@ impl LocalEmbeddedClientHandle {
}
}
// TODO: generalize this whole thing to be general. And change the name(s).
pub(crate) fn new_ip(
start_data: nym_ip_packet_router::OnStartData,
mix_message_sender: MixMessageSender,
) -> Self {
Self {
address: start_data.address,
mix_message_sender,
}
}
pub(crate) fn client_destination(&self) -> DestinationAddressBytes {
self.address.identity().derive_destination_address()
}
@@ -37,8 +48,8 @@ impl LocalEmbeddedClientHandle {
// calling the method. however, this would have caused slightly more complexity and more overhead
// (due to more data being copied to every [mix] connection)
//
/// task responsible for receiving messages for locally embedded clients from multiple mix
/// connections and forwarding them via the router. kinda equivalent of a client socket handler
/// task responsible for receiving messages for locally NR requester from multiple mix connections
/// and forwarding them via the router. kinda equivalent of a client socket handler
pub(crate) struct MessageRouter {
mix_receiver: MixMessageReceiver,
packet_router: PacketRouter,
@@ -60,29 +71,29 @@ impl MessageRouter {
if let Err(err) = self.packet_router.route_received(messages) {
// TODO: what should we do here? I don't think this could/should ever fail.
// is panicking the appropriate thing to do then?
error!("failed to route packets to local embedded client: {err}")
error!("failed to route packets to local NR: {err}")
}
}
pub(crate) async fn run_with_shutdown(mut self, mut shutdown: TaskClient) {
debug!("Started embedded client message router with graceful shutdown support");
debug!("Started embedded network requester message router with graceful shutdown support");
while !shutdown.is_shutdown() {
tokio::select! {
messages = self.mix_receiver.next() => match messages {
Some(messages) => self.handle_received_messages(messages),
None => {
log::trace!("embedded_clients::MessageRouter: Stopping since channel closed");
log::trace!("embedded_network_requester::MessageRouter: Stopping since channel closed");
break;
}
},
_ = shutdown.recv_with_delay() => {
log::trace!("embedded_clients::MessageRouter: Received shutdown");
log::trace!("embedded_network_requester::MessageRouter: Received shutdown");
debug_assert!(shutdown.is_shutdown());
break
}
}
}
debug!("embedded_network_clients::MessageRouter: Exiting")
debug!("embedded_network_requester::MessageRouter: Exiting")
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ use crate::node::client_handling::bandwidth::Bandwidth;
pub(crate) mod active_clients;
mod bandwidth;
pub(crate) mod embedded_clients;
pub(crate) mod embedded_network_requester;
pub(crate) mod websocket;
pub(crate) const FREE_TESTNET_BANDWIDTH_VALUE: Bandwidth = Bandwidth::new(64 * 1024 * 1024 * 1024); // 64GB
@@ -92,9 +92,6 @@ pub(crate) enum RequestHandlingError {
#[error("the provided credential did not have a bandwidth attribute")]
MissingBandwidthAttribute,
#[error("the DKG contract is unavailable")]
UnavailableDkgContract,
}
impl RequestHandlingError {
@@ -603,7 +600,7 @@ where
None => break,
Some(Ok(socket_msg)) => socket_msg,
Some(Err(err)) => {
debug!("failed to obtain message from websocket stream! stopping connection handler: {err}");
error!("failed to obtain message from websocket stream! stopping connection handler: {err}");
break;
}
};
@@ -614,7 +611,7 @@ where
if let Some(response) = self.handle_request(socket_msg).await {
if let Err(err) = self.inner.send_websocket_message(response).await {
debug!(
warn!(
"Failed to send message over websocket: {err}. Assuming the connection is dead.",
);
break;
@@ -624,13 +621,13 @@ where
mix_messages = self.mix_receiver.next() => {
let mix_messages = match mix_messages {
None => {
debug!("mix receiver was closed! Assuming the connection is dead.");
warn!("mix receiver was closed! Assuming the connection is dead.");
break;
}
Some(mix_messages) => mix_messages,
};
if let Err(err) = self.inner.push_packets_to_client(&self.client.shared_keys, mix_messages).await {
debug!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead");
warn!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead");
break;
}
}
@@ -36,7 +36,6 @@ pub(crate) struct CoconutVerifier {
impl CoconutVerifier {
pub async fn new(
nyxd_client: DirectSigningHttpRpcNyxdClient,
only_coconut_credentials: bool,
) -> Result<Self, RequestHandlingError> {
let mix_denom_base = nyxd_client.current_chain_details().mix_denom.base.clone();
let address = nyxd_client.address();
@@ -46,17 +45,9 @@ impl CoconutVerifier {
// don't make it a hard failure in case we're running on mainnet (where DKG hasn't been deployed yet)
if nyxd_client.dkg_contract_address().is_none() {
if !only_coconut_credentials {
warn!(
"the DKG contract address is not available - \
no coconut credentials will be redeemable \
(if the DKG ceremony hasn't been run yet this warning is expected)"
);
} else {
// if we require coconut credentials, we MUST have DKG contract available
return Err(RequestHandlingError::UnavailableDkgContract);
}
error!(
"DKG contract address is not available - no coconut credentials will be redeemable"
);
return Ok(CoconutVerifier {
address,
nyxd_client: RwLock::new(nyxd_client),
@@ -69,10 +60,6 @@ impl CoconutVerifier {
let Ok(current_epoch) = nyxd_client.get_current_epoch().await else {
// another case of somebody putting a placeholder address that doesn't exist
error!("the specified DKG contract address is invalid - no coconut credentials will be redeemable");
if only_coconut_credentials {
// if we require coconut credentials, we MUST have DKG contract available
return Err(RequestHandlingError::UnavailableDkgContract);
}
return Ok(CoconutVerifier {
address,
nyxd_client: RwLock::new(nyxd_client),
@@ -667,7 +667,7 @@ where
let msg = match msg {
Ok(msg) => msg,
Err(err) => {
debug!("failed to obtain message from websocket stream! stopping connection handler: {err}");
error!("failed to obtain message from websocket stream! stopping connection handler: {err}");
break;
}
};
@@ -723,7 +723,7 @@ where
Message::Binary(_) => {
// perhaps logging level should be reduced here, let's leave it for now and see what happens
// if client is working correctly, this should have never happened
debug!("possibly received a sphinx packet without prior authentication. Request is going to be ignored");
warn!("possibly received a sphinx packet without prior authentication. Request is going to be ignored");
if let Err(err) = self
.send_websocket_message(
ServerResponse::new_error(
+22 -11
View File
@@ -11,7 +11,9 @@ use crate::config::Config;
use crate::error::GatewayError;
use crate::http::HttpApiBuilder;
use crate::node::client_handling::active_clients::ActiveClientsStore;
use crate::node::client_handling::embedded_clients::{LocalEmbeddedClientHandle, MessageRouter};
use crate::node::client_handling::embedded_network_requester::{
LocalNetworkRequesterHandle, MessageRouter,
};
use crate::node::client_handling::websocket;
use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier;
use crate::node::helpers::{initialise_main_storage, load_network_requester_config};
@@ -49,7 +51,7 @@ struct StartedNetworkRequester {
used_request_filter: RequestFilter,
/// Handle to interact with the local network requester
handle: LocalEmbeddedClientHandle,
handle: LocalNetworkRequesterHandle,
}
/// Wire up and create Gateway instance
@@ -78,7 +80,7 @@ pub(crate) async fn create_gateway(
let cfg = load_ip_packet_router_config(&config.gateway.id, path)?;
Some(override_ip_packet_router_config(cfg, ip_config_override))
} else {
// if IPR is enabled, the config path must be specified
// if NR is enabled, the config path must be specified
return Err(GatewayError::UnspecifiedIpPacketRouterConfig);
}
} else {
@@ -317,7 +319,7 @@ impl<St> Gateway<St> {
info!("the local network requester is running on {address}",);
Ok(StartedNetworkRequester {
used_request_filter: start_data.request_filter,
handle: LocalEmbeddedClientHandle::new(address, nr_mix_sender),
handle: LocalNetworkRequesterHandle::new(address, nr_mix_sender),
})
}
@@ -325,16 +327,17 @@ impl<St> Gateway<St> {
&self,
forwarding_channel: MixForwardingSender,
shutdown: TaskClient,
) -> Result<LocalEmbeddedClientHandle, GatewayError> {
) -> Result<LocalNetworkRequesterHandle, GatewayError> {
info!("Starting IP packet provider...");
// if network requester is enabled, configuration file must be provided!
let Some(ip_opts) = &self.ip_packet_router_opts else {
log::error!("IP packet router is enabled but no configuration file was provided!");
return Err(GatewayError::UnspecifiedIpPacketRouterConfig);
};
// this gateway, whenever it has anything to send to its local NR will use fake_client_tx
let (ipr_mix_sender, ipr_mix_receiver) = mpsc::unbounded();
let (nr_mix_sender, nr_mix_receiver) = mpsc::unbounded();
let router_shutdown = shutdown.fork("message_router");
let (router_tx, mut router_rx) = oneshot::channel();
@@ -345,6 +348,7 @@ impl<St> Gateway<St> {
router_tx,
);
// TODO: well, wire it up internally to gateway traffic, shutdowns, etc.
let (on_start_tx, on_start_rx) = oneshot::channel();
let mut ip_packet_router =
nym_ip_packet_router::IpPacketRouter::new(ip_opts.config.clone())
@@ -375,11 +379,16 @@ impl<St> Gateway<St> {
return Err(GatewayError::IpPacketRouterStartupFailure);
};
MessageRouter::new(ipr_mix_receiver, packet_router).start_with_shutdown(router_shutdown);
let address = start_data.address;
MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown);
info!(
"the local ip packet router is running on {}",
start_data.address
);
info!("the local ip packet router is running on {address}");
Ok(LocalEmbeddedClientHandle::new(address, ipr_mix_sender))
Ok(LocalNetworkRequesterHandle::new_ip(
start_data,
nr_mix_sender,
))
}
async fn wait_for_interrupt(
@@ -447,7 +456,7 @@ impl<St> Gateway<St> {
let coconut_verifier = {
let nyxd_client = self.random_nyxd_client()?;
CoconutVerifier::new(nyxd_client, self.config.gateway.only_coconut_credentials).await
CoconutVerifier::new(nyxd_client).await
}?;
let mix_forwarding_channel =
@@ -495,6 +504,8 @@ impl<St> Gateway<St> {
None
};
// NOTE: this is mutually exclusive with the network requester (for now). This is reflected
// in the command line arguments as well.
if self.config.ip_packet_router.enabled {
let embedded_ip_sp = self
.start_ip_packet_router(
+15 -2
View File
@@ -26,7 +26,6 @@ cupid = "0.6.1"
dirs = "4.0"
futures = { workspace = true }
humantime-serde = "1.0"
lazy_static = "1.4"
log = { workspace = true }
rand = "0.7.3"
serde = { workspace = true, features = ["derive"] }
@@ -36,8 +35,14 @@ tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] }
tokio-util = { workspace = true, features = ["codec"] }
toml = "0.5.8"
url = { workspace = true, features = ["serde"] }
cfg-if = "1.0.0"
thiserror = { workspace = true }
## tracing
tracing = { workspace = true, optional = true }
opentelemetry = { version = "0.19.0", optional = true }
# internal
nym-node = { path = "../nym-node" }
@@ -46,7 +51,6 @@ nym-crypto = { path = "../common/crypto" }
nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" }
nym-mixnet-client = { path = "../common/client-libs/mixnet-client" }
nym-mixnode-common = { path = "../common/mixnode-common" }
nym-metrics = { path = "../common/nym-metrics" }
nym-nonexhaustive-delayqueue = { path = "../common/nonexhaustive-delayqueue" }
nym-sphinx = { path = "../common/nymsphinx" }
nym-sphinx-params = { path = "../common/nymsphinx/params" }
@@ -56,6 +60,7 @@ nym-types = { path = "../common/types" }
nym-topology = { path = "../common/topology" }
nym-validator-client = { path = "../common/client-libs/validator-client" }
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
cpu-cycles = { path = "../cpu-cycles", optional = true }
[dev-dependencies]
tokio = { workspace = true, features = [
@@ -68,6 +73,14 @@ tokio = { workspace = true, features = [
nym-sphinx-types = { path = "../common/nymsphinx/types" }
nym-sphinx-params = { path = "../common/nymsphinx/params" }
[features]
cpucycles = [
"nym-mixnode-common/cpucycles",
"tracing",
"opentelemetry",
"nym-bin-common/tracing",
]
[package.metadata.deb]
name = "nym-mixnode"
maintainer-scripts = "debian"
-4
View File
@@ -42,9 +42,6 @@ pub(crate) struct Init {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
#[clap(long)]
metrics_key: Option<String>,
}
impl From<Init> for OverrideConfig {
@@ -56,7 +53,6 @@ impl From<Init> for OverrideConfig {
verloc_port: init_config.verloc_port,
http_api_port: init_config.http_api_port,
nym_apis: init_config.nym_apis,
metrics_key: init_config.metrics_key,
}
}
}
-2
View File
@@ -59,7 +59,6 @@ struct OverrideConfig {
verloc_port: Option<u16>,
http_api_port: Option<u16>,
nym_apis: Option<Vec<url::Url>>,
metrics_key: Option<String>,
}
pub(crate) async fn execute(args: Cli) -> anyhow::Result<()> {
@@ -84,7 +83,6 @@ fn override_config(config: Config, args: OverrideConfig) -> Config {
.with_optional(Config::with_mix_port, args.mix_port)
.with_optional(Config::with_verloc_port, args.verloc_port)
.with_optional(Config::with_http_api_port, args.http_api_port)
.with_optional(Config::with_metrics_key, args.metrics_key)
.with_optional_custom_env(
Config::with_custom_nym_apis,
args.nym_apis,
-4
View File
@@ -44,9 +44,6 @@ pub(crate) struct Run {
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
#[clap(long)]
metrics_key: Option<String>,
}
impl From<Run> for OverrideConfig {
@@ -58,7 +55,6 @@ impl From<Run> for OverrideConfig {
verloc_port: run_config.verloc_port,
http_api_port: run_config.http_api_port,
nym_apis: run_config.nym_apis,
metrics_key: run_config.metrics_key,
}
}
}
-10
View File
@@ -80,7 +80,6 @@ fn default_mixnode_http_config() -> config::Http {
DEFAULT_HTTP_API_LISTENING_PORT,
),
landing_page_assets_path: None,
metrics_key: None,
}
}
@@ -209,15 +208,6 @@ impl Config {
pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
self.mixnode.nym_api_urls.clone()
}
pub fn with_metrics_key(mut self, metrics_key: String) -> Self {
self.http.metrics_key = Some(metrics_key);
self
}
pub fn metrics_key(&self) -> Option<&String> {
self.http.metrics_key.as_ref()
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
-1
View File
@@ -95,7 +95,6 @@ impl From<ConfigV1_1_32> for Config {
value.mixnode.http_api_port,
),
landing_page_assets_path: None,
metrics_key: None,
},
// /\ ADDED
mixnode: MixNode {
-2
View File
@@ -57,8 +57,6 @@ bind_address = '{{ http.bind_address }}'
# Path to assets directory of custom landing page of this node
landing_page_assets_path = '{{ http.landing_page_assets_path }}'
metrics_key = '{{ http.metrics_key }}'
[storage_paths]
# Path to file containing private identity key.
+27 -1
View File
@@ -3,11 +3,18 @@
use ::nym_config::defaults::setup_env;
use clap::{crate_name, crate_version, Parser};
use log::info;
use nym_bin_common::bin_info;
use std::sync::OnceLock;
#[allow(unused_imports)]
use nym_bin_common::logging::{maybe_print_banner, setup_logging};
#[cfg(feature = "cpucycles")]
use nym_bin_common::setup_tracing;
#[cfg(feature = "cpucycles")]
use nym_mixnode_common::measure;
#[cfg(feature = "cpucycles")]
use tracing::instrument;
mod commands;
mod config;
@@ -34,6 +41,12 @@ struct Cli {
command: commands::Commands,
}
#[cfg(feature = "cpucycles")]
#[instrument(fields(cpucycles))]
fn test_function() {
measure!({})
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Cli::parse();
@@ -43,10 +56,23 @@ async fn main() -> anyhow::Result<()> {
maybe_print_banner(crate_name!(), crate_version!());
}
setup_logging();
cfg_if::cfg_if! {
if #[cfg(feature = "cpucycles")] {
setup_tracing!("mixnode");
info!("CPU cycles measurement is ON")
} else {
setup_logging();
info!("CPU cycles measurement is OFF")
}
}
commands::execute(args).await?;
cfg_if::cfg_if! {
if #[cfg(feature = "cpucycles")] {
opentelemetry::global::shutdown_tracer_provider();
}}
Ok(())
}
-3
View File
@@ -4,7 +4,6 @@
use crate::node::http::legacy::description::description;
use crate::node::http::legacy::hardware::hardware;
use crate::node::http::legacy::state::MixnodeAppState;
use crate::node::http::legacy::stats::metrics;
use crate::node::http::legacy::stats::stats;
use crate::node::http::legacy::verloc::verloc;
use crate::node::node_description::NodeDescription;
@@ -30,7 +29,6 @@ pub(crate) mod api_routes {
pub(crate) const VERLOC: &str = "/verloc";
pub(crate) const DESCRIPTION: &str = "/description";
pub(crate) const STATS: &str = "/stats";
pub(crate) const METRICS: &str = "/metrics";
pub(crate) const HARDWARE: &str = "/hardware";
}
@@ -46,7 +44,6 @@ pub(crate) fn routes<S: Send + Sync + 'static + Clone>(
)
.route(api_routes::STATS, get(stats))
.route(api_routes::HARDWARE, get(hardware))
.route(api_routes::METRICS, get(metrics))
.fallback(not_found)
.with_state(state)
}
-1
View File
@@ -10,7 +10,6 @@ use axum::extract::FromRef;
pub(crate) struct MixnodeAppState {
pub(crate) verloc: VerlocState,
pub(crate) stats: SharedNodeStats,
pub(crate) metrics_key: Option<String>,
}
impl FromRef<MixnodeAppState> for VerlocState {
+9 -35
View File
@@ -1,59 +1,33 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::node_statistics::{NodeStatsSimple, SharedNodeStats};
use axum::{
extract::{Query, State},
http::HeaderMap,
};
use nym_metrics::metrics;
use crate::node::node_statistics::{NodeStats, NodeStatsSimple, SharedNodeStats};
use axum::extract::{Query, State};
use nym_node::http::api::{FormattedResponse, Output};
use serde::{Deserialize, Serialize};
use super::state::MixnodeAppState;
#[derive(Serialize)]
#[serde(untagged)]
pub enum NodeStatsResponse {
Full(String),
Full(NodeStats),
Simple(NodeStatsSimple),
}
pub(crate) async fn metrics(State(state): State<MixnodeAppState>, headers: HeaderMap) -> String {
if let Some(metrics_key) = state.metrics_key {
if let Some(auth) = headers.get("Authorization") {
if auth.to_str().unwrap_or_default() == format!("Bearer {}", metrics_key) {
metrics!()
} else {
"Unauthorized".to_string()
}
} else {
"Unauthorized".to_string()
}
} else {
"Set metrics_key in config to enable Prometheus metrics".to_string()
}
}
pub(crate) async fn stats(
Query(params): Query<StatsQueryParams>,
State(stats): State<SharedNodeStats>,
) -> MixnodeStatsResponse {
let output = params.output.unwrap_or_default();
// there's no point in returning the entire hashmap of sending destinations in regular mode
let response = generate_stats(params.debug, stats).await;
output.to_response(response)
}
async fn generate_stats(full: bool, stats: SharedNodeStats) -> NodeStatsResponse {
let snapshot_data = stats.clone_data().await;
if full {
NodeStatsResponse::Full(metrics!())
// there's no point in returning the entire hashmap of sending destinations in regular mode
let response = if params.debug {
NodeStatsResponse::Full(snapshot_data)
} else {
NodeStatsResponse::Simple(snapshot_data.simplify())
}
};
output.to_response(response)
}
pub type MixnodeStatsResponse = FormattedResponse<NodeStatsResponse>;
-6
View File
@@ -64,12 +64,6 @@ impl<'a> HttpApiBuilder<'a> {
}
}
#[must_use]
pub(crate) fn with_metrics_key(mut self, metrics_key: Option<&String>) -> Self {
self.legacy_mixnode.metrics_key = metrics_key.map(|k| k.to_string());
self
}
#[must_use]
pub(crate) fn with_verloc(mut self, verloc: VerlocState) -> Self {
self.legacy_mixnode.verloc = verloc;
@@ -9,7 +9,7 @@ use crate::node::TaskClient;
use futures::StreamExt;
use log::debug;
use log::{error, info, warn};
use nym_metrics::nanos;
use nym_mixnode_common::measure;
use nym_sphinx::forwarding::packet::MixPacket;
use nym_sphinx::framing::codec::NymCodec;
use nym_sphinx::framing::packet::FramedNymPacket;
@@ -19,6 +19,9 @@ use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_util::codec::Framed;
#[cfg(feature = "cpucycles")]
use tracing::instrument;
pub(crate) mod packet_processing;
#[derive(Clone)]
@@ -50,6 +53,10 @@ impl ConnectionHandler {
.expect("the delay-forwarder has died!");
}
#[cfg_attr(
feature = "cpucycles",
instrument(skip(self, framed_sphinx_packet), fields(cpucycles))
)]
fn handle_received_packet(&self, framed_sphinx_packet: FramedNymPacket) {
//
// TODO: here be replay attack detection - it will require similar key cache to the one in
@@ -59,7 +66,7 @@ impl ConnectionHandler {
// all processing such, key caching, etc. was done.
// however, if it was a forward hop, we still need to delay it
nanos!("handle_received_packet", {
measure!({
match self.packet_processor.process_received(framed_sphinx_packet) {
Err(err) => debug!("We failed to process received sphinx packet - {err}"),
Ok(res) => match res {
-3
View File
@@ -72,13 +72,11 @@ impl MixNode {
&self,
atomic_verloc_result: AtomicVerlocResult,
node_stats_pointer: SharedNodeStats,
metrics_key: Option<&String>,
task_client: TaskClient,
) -> Result<(), MixnodeError> {
HttpApiBuilder::new(&self.config, &self.identity_keypair, &self.sphinx_keypair)
.with_verloc(VerlocState::new(atomic_verloc_result))
.with_mixing_stats(node_stats_pointer)
.with_metrics_key(metrics_key)
.with_descriptor(self.descriptor.clone())
.start(task_client)
}
@@ -251,7 +249,6 @@ impl MixNode {
self.start_http_api(
atomic_verloc_results,
node_stats_pointer,
self.config.metrics_key(),
shutdown.subscribe().named("http-api"),
)?;
+75 -64
View File
@@ -1,8 +1,6 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use nym_metrics::inc_by;
use super::TaskClient;
use futures::channel::mpsc;
use futures::lock::Mutex;
@@ -17,7 +15,7 @@ use std::time::{Duration, SystemTime};
use tokio::sync::{RwLock, RwLockReadGuard};
// convenience aliases
type PacketsMap = HashMap<String, f64>;
type PacketsMap = HashMap<String, u64>;
type PacketDataReceiver = mpsc::UnboundedReceiver<PacketEvent>;
type PacketDataSender = mpsc::UnboundedSender<PacketEvent>;
@@ -29,15 +27,14 @@ pub(crate) struct SharedNodeStats {
impl SharedNodeStats {
pub(crate) fn new() -> Self {
let now = SystemTime::now();
SharedNodeStats {
inner: Arc::new(RwLock::new(NodeStats {
update_time: now,
previous_update_time: now,
packets_received_since_startup: 0.,
packets_sent_since_startup_all: 0.,
packets_dropped_since_startup_all: 0.,
packets_received_since_last_update: 0.,
packets_received_since_startup: 0,
packets_sent_since_startup: HashMap::new(),
packets_explicitly_dropped_since_startup: HashMap::new(),
packets_received_since_last_update: 0,
packets_sent_since_last_update: HashMap::new(),
packets_explicitly_dropped_since_last_update: HashMap::new(),
})),
@@ -46,7 +43,7 @@ impl SharedNodeStats {
pub(crate) async fn update(
&self,
new_received: f64,
new_received: u64,
new_sent: PacketsMap,
new_dropped: PacketsMap,
) {
@@ -57,24 +54,20 @@ impl SharedNodeStats {
guard.update_time = snapshot_time;
guard.packets_received_since_startup += new_received;
for count in new_sent.values() {
guard.packets_sent_since_startup_all += count;
for (mix, count) in &new_sent {
*guard
.packets_sent_since_startup
.entry(mix.clone())
.or_insert(0) += *count;
}
for count in new_dropped.values() {
guard.packets_dropped_since_startup_all += count;
for (mix, count) in &new_dropped {
*guard
.packets_explicitly_dropped_since_last_update
.entry(mix.clone())
.or_insert(0) += *count;
}
inc_by!("packets_received_since_startup", new_received);
inc_by!(
"packets_sent_since_startup_all",
new_sent.values().sum::<f64>()
);
inc_by!(
"packets_dropped_since_startup_all",
new_dropped.values().sum::<f64>()
);
guard.packets_received_since_last_update = new_received;
guard.packets_sent_since_last_update = new_sent;
guard.packets_explicitly_dropped_since_last_update = new_dropped;
@@ -89,18 +82,27 @@ impl SharedNodeStats {
}
}
#[derive(Clone)]
#[derive(Serialize, Clone)]
pub struct NodeStats {
#[serde(serialize_with = "humantime_serde::serialize")]
update_time: SystemTime,
#[serde(serialize_with = "humantime_serde::serialize")]
previous_update_time: SystemTime,
packets_received_since_startup: f64,
packets_sent_since_startup_all: f64,
packets_dropped_since_startup_all: f64,
packets_received_since_last_update: f64,
packets_received_since_startup: u64,
// note: sent does not imply forwarded. We don't know if it was delivered successfully
packets_sent_since_startup: PacketsMap,
// we know for sure we dropped packets to those destinations
packets_explicitly_dropped_since_startup: PacketsMap,
packets_received_since_last_update: u64,
// note: sent does not imply forwarded. We don't know if it was delivered successfully
packets_sent_since_last_update: PacketsMap,
// we know for sure we dropped packets to those destinations
packets_explicitly_dropped_since_last_update: PacketsMap,
}
@@ -110,10 +112,10 @@ impl Default for NodeStats {
NodeStats {
update_time: SystemTime::UNIX_EPOCH,
previous_update_time: SystemTime::UNIX_EPOCH,
packets_received_since_startup: 0.,
packets_sent_since_startup_all: 0.,
packets_dropped_since_startup_all: 0.,
packets_received_since_last_update: 0.,
packets_received_since_startup: 0,
packets_sent_since_startup: Default::default(),
packets_explicitly_dropped_since_startup: Default::default(),
packets_received_since_last_update: 0,
packets_sent_since_last_update: Default::default(),
packets_explicitly_dropped_since_last_update: Default::default(),
}
@@ -126,8 +128,11 @@ impl NodeStats {
update_time: self.update_time,
previous_update_time: self.previous_update_time,
packets_received_since_startup: self.packets_received_since_startup,
packets_sent_since_startup: self.packets_sent_since_startup_all,
packets_explicitly_dropped_since_startup: self.packets_dropped_since_startup_all,
packets_sent_since_startup: self.packets_sent_since_startup.values().sum(),
packets_explicitly_dropped_since_startup: self
.packets_explicitly_dropped_since_startup
.values()
.sum(),
packets_received_since_last_update: self.packets_received_since_last_update,
packets_sent_since_last_update: self.packets_sent_since_last_update.values().sum(),
packets_explicitly_dropped_since_last_update: self
@@ -146,21 +151,21 @@ pub struct NodeStatsSimple {
#[serde(serialize_with = "humantime_serde::serialize")]
previous_update_time: SystemTime,
packets_received_since_startup: f64,
packets_received_since_startup: u64,
// note: sent does not imply forwarded. We don't know if it was delivered successfully
packets_sent_since_startup: f64,
packets_sent_since_startup: u64,
// we know for sure we dropped those packets
packets_explicitly_dropped_since_startup: f64,
packets_explicitly_dropped_since_startup: u64,
packets_received_since_last_update: f64,
packets_received_since_last_update: u64,
// note: sent does not imply forwarded. We don't know if it was delivered successfully
packets_sent_since_last_update: f64,
packets_sent_since_last_update: u64,
// we know for sure we dropped those packets
packets_explicitly_dropped_since_last_update: f64,
packets_explicitly_dropped_since_last_update: u64,
}
pub(crate) enum PacketEvent {
@@ -198,14 +203,14 @@ impl CurrentPacketData {
async fn increment_sent(&self, destination: String) {
let mut unlocked = self.inner.sent.lock().await;
let receiver_count = unlocked.entry(destination).or_insert(0.);
*receiver_count += 1.;
let receiver_count = unlocked.entry(destination).or_insert(0);
*receiver_count += 1;
}
async fn increment_dropped(&self, destination: String) {
let mut unlocked = self.inner.dropped.lock().await;
let dropped_count = unlocked.entry(destination).or_insert(0.);
*dropped_count += 1.;
let dropped_count = unlocked.entry(destination).or_insert(0);
*dropped_count += 1;
}
async fn acquire_and_reset(&self) -> (u64, PacketsMap, PacketsMap) {
@@ -327,9 +332,7 @@ impl StatsUpdater {
async fn update_stats(&self) {
// grab new data since last update
let (received, sent, dropped) = self.current_packet_data.acquire_and_reset().await;
self.current_stats
.update(received as f64, sent, dropped)
.await;
self.current_stats.update(received, sent, dropped).await;
}
async fn run(&mut self) {
@@ -373,18 +376,21 @@ impl PacketStatsConsoleLogger {
info!(
"Since startup mixed {} packets! ({} in last {} seconds)",
stats.packets_sent_since_startup_all,
stats.packets_sent_since_last_update.values().sum::<f64>(),
stats.packets_sent_since_startup.values().sum::<u64>(),
stats.packets_sent_since_last_update.values().sum::<u64>(),
difference_secs,
);
if stats.packets_dropped_since_startup_all > 0. {
if !stats.packets_explicitly_dropped_since_startup.is_empty() {
info!(
"Since startup dropped {} packets! ({} in last {} seconds)",
stats.packets_dropped_since_startup_all,
stats
.packets_explicitly_dropped_since_startup
.values()
.sum::<u64>(),
stats
.packets_explicitly_dropped_since_last_update
.values()
.sum::<f64>(),
.sum::<u64>(),
difference_secs,
);
}
@@ -397,19 +403,22 @@ impl PacketStatsConsoleLogger {
);
trace!(
"Since startup sent packets to the following: \n{:#?} \n And in last {} seconds: {:#?})",
stats.packets_sent_since_startup_all,
stats.packets_sent_since_startup,
difference_secs,
stats.packets_sent_since_last_update
);
} else {
info!(
"Since startup mixed {} packets!",
stats.packets_sent_since_startup_all,
stats.packets_sent_since_startup.values().sum::<u64>(),
);
if stats.packets_dropped_since_startup_all > 0. {
if !stats.packets_explicitly_dropped_since_startup.is_empty() {
info!(
"Since startup dropped {} packets!",
stats.packets_dropped_since_startup_all,
stats
.packets_explicitly_dropped_since_startup
.values()
.sum::<u64>(),
);
}
@@ -418,8 +427,8 @@ impl PacketStatsConsoleLogger {
stats.packets_received_since_startup
);
trace!(
"Since startup sent packets {}",
stats.packets_sent_since_startup_all
"Since startup sent packets to the following: \n{:#?}",
stats.packets_sent_since_startup
);
}
}
@@ -512,7 +521,6 @@ impl Controller {
#[cfg(test)]
mod tests {
use super::*;
use nym_metrics::metrics;
use nym_task::TaskManager;
#[tokio::test]
@@ -537,11 +545,14 @@ mod tests {
// Get output (stats)
let stats = node_stats_pointer.read().await;
assert_eq!(&stats.packets_sent_since_startup_all, &2.);
assert_eq!(&stats.packets_sent_since_last_update.get("foo"), &Some(&2.));
assert_eq!(&stats.packets_sent_since_startup.get("foo"), &Some(&2u64));
assert_eq!(&stats.packets_sent_since_startup.len(), &1);
assert_eq!(
&stats.packets_sent_since_last_update.get("foo"),
&Some(&2u64)
);
assert_eq!(&stats.packets_sent_since_last_update.len(), &1);
assert_eq!(&stats.packets_received_since_startup, &0.);
assert_eq!(&stats.packets_dropped_since_startup_all, &0.);
assert_eq!(metrics!(), "# HELP nym_mixnode_packets_dropped_since_startup_all nym_mixnode_packets_dropped_since_startup_all\n# TYPE nym_mixnode_packets_dropped_since_startup_all counter\nnym_mixnode_packets_dropped_since_startup_all 0\n# HELP nym_mixnode_packets_received_since_startup nym_mixnode_packets_received_since_startup\n# TYPE nym_mixnode_packets_received_since_startup counter\nnym_mixnode_packets_received_since_startup 0\n# HELP nym_mixnode_packets_sent_since_startup_all nym_mixnode_packets_sent_since_startup_all\n# TYPE nym_mixnode_packets_sent_since_startup_all counter\nnym_mixnode_packets_sent_since_startup_all 2\n")
assert_eq!(&stats.packets_received_since_startup, &0u64);
assert!(&stats.packets_explicitly_dropped_since_startup.is_empty());
}
}
+6 -6
View File
@@ -2555,9 +2555,9 @@
"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ=="
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"funding": [
{
"type": "individual",
@@ -6845,9 +6845,9 @@
"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ=="
},
"follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
},
"form-data": {
"version": "4.0.0",
+3 -3
View File
@@ -1568,9 +1568,9 @@ flatted@^3.1.0:
integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==
follow-redirects@^1.15.0:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
version "1.15.4"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf"
integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==
form-data@4.0.0, form-data@^4.0.0:
version "4.0.0"
+17 -124
View File
@@ -2529,7 +2529,7 @@ dependencies = [
"futures-core",
"futures-sink",
"gloo-utils",
"http 0.2.9",
"http",
"js-sys",
"pin-project",
"serde",
@@ -2664,7 +2664,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.9",
"http",
"indexmap 1.9.3",
"slab",
"tokio",
@@ -2833,17 +2833,6 @@ dependencies = [
"itoa 1.0.9",
]
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa 1.0.9",
]
[[package]]
name = "http-api-client"
version = "0.1.0"
@@ -2865,30 +2854,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http 0.2.9",
"pin-project-lite",
]
[[package]]
name = "http-body"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [
"bytes",
"http 1.1.0",
]
[[package]]
name = "http-body-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [
"bytes",
"futures-core",
"http 1.1.0",
"http-body 1.0.0",
"http",
"pin-project-lite",
]
@@ -2946,8 +2912,8 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http 0.2.9",
"http-body 0.4.5",
"http",
"http-body",
"httparse",
"httpdate",
"itoa 1.0.9",
@@ -2959,25 +2925,6 @@ dependencies = [
"want",
]
[[package]]
name = "hyper"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.1.0",
"http-body 1.0.0",
"httparse",
"httpdate",
"itoa 1.0.9",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-rustls"
version = "0.24.1"
@@ -2985,8 +2932,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
dependencies = [
"futures-util",
"http 0.2.9",
"hyper 0.14.27",
"http",
"hyper",
"rustls 0.21.7",
"tokio",
"tokio-rustls 0.24.1",
@@ -2999,28 +2946,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper 0.14.27",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "hyper-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-util",
"http 1.1.0",
"http-body 1.0.0",
"hyper 1.2.0",
"pin-project-lite",
"socket2 0.5.5",
"tokio",
]
[[package]]
name = "iana-time-zone"
version = "0.1.57"
@@ -3823,10 +3754,7 @@ dependencies = [
"dirs 4.0.0",
"futures",
"gloo-timers",
"http-body-util",
"humantime-serde",
"hyper 1.2.0",
"hyper-util",
"log",
"nym-bandwidth-controller",
"nym-config",
@@ -3835,7 +3763,6 @@ dependencies = [
"nym-explorer-client",
"nym-gateway-client",
"nym-gateway-requests",
"nym-metrics",
"nym-network-defaults",
"nym-nonexhaustive-delayqueue",
"nym-pemstore",
@@ -4160,9 +4087,7 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
"tokio",
"tungstenite",
"wasmtimer",
"zeroize",
]
@@ -4177,16 +4102,6 @@ dependencies = [
"serde",
]
[[package]]
name = "nym-metrics"
version = "0.1.0"
dependencies = [
"dashmap",
"lazy_static",
"log",
"prometheus",
]
[[package]]
name = "nym-mixnet-contract-common"
version = "0.6.0"
@@ -5289,21 +5204,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "prometheus"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
dependencies = [
"cfg-if",
"fnv",
"lazy_static",
"memchr",
"parking_lot 0.12.1",
"protobuf",
"thiserror",
]
[[package]]
name = "prost"
version = "0.12.1"
@@ -5336,12 +5236,6 @@ dependencies = [
"prost",
]
[[package]]
name = "protobuf"
version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "quick-error"
version = "1.2.3"
@@ -5591,9 +5485,9 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"http",
"http-body",
"hyper",
"hyper-rustls",
"hyper-tls",
"ipnet",
@@ -6413,9 +6307,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.13.2"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "socket2"
@@ -6891,7 +6785,7 @@ dependencies = [
"glob",
"gtk",
"heck 0.4.1",
"http 0.2.9",
"http",
"ignore",
"minisign-verify",
"notify-rust",
@@ -6991,7 +6885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769"
dependencies = [
"gtk",
"http 0.2.9",
"http",
"http-range",
"rand 0.8.5",
"raw-window-handle",
@@ -7377,7 +7271,6 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
"rustls 0.21.7",
"tokio",
"tungstenite",
]
@@ -7555,7 +7448,7 @@ dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 0.2.9",
"http",
"httparse",
"log",
"rand 0.8.5",
@@ -8368,7 +8261,7 @@ dependencies = [
"glib",
"gtk",
"html5ever",
"http 0.2.9",
"http",
"kuchiki",
"libc",
"log",
-4
View File
@@ -49,9 +49,6 @@ pub struct Http {
/// Path to assets directory of custom landing page of this node.
#[serde(deserialize_with = "de_maybe_path")]
pub landing_page_assets_path: Option<PathBuf>,
#[serde(default)]
pub metrics_key: Option<String>,
}
impl Default for Http {
@@ -59,7 +56,6 @@ impl Default for Http {
Http {
bind_address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), DEFAULT_HTTP_PORT),
landing_page_assets_path: None,
metrics_key: None,
}
}
}
@@ -1,55 +0,0 @@
# Wallet CLI Recovery Tool Guide
This guide provides instructions on how to use the Wallet CLI recovery tool to recover your mnemonic phrase using your password, especially useful if you're unable to access your wallet in the usual way.
## Step 1: Install the CLI Tool
1. Change directory `cd /nym-wallet/nym-wallet-recovery-cli` from root Nym repository
2. Have rust installed `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
3. Once the installation is complete run `cargo build --release`
4. The binary should live here: `nym/nym-wallet/nym-wallet-recovery-cli)`
## Step 2: Prepare Your Command
The tool requires specific command-line arguments to specify the password(s) and the file path to your wallet file. The basic structure of the command is as follows:
```
nym-recovery-cli --password <YOUR_PASSWORD> --file <PATH_TO_YOUR_WALLET_FILE> [OPTIONS]
```
- Replace `<YOUR_PASSWORD>` with your wallet password.
- Replace `<PATH_TO_YOUR_WALLET_FILE>` with the path to your wallet file, where your encrypted mnemonic is stored.
## Step 3: Running the Tool
1. Open your terminal or command prompt.
2. Navigate to the directory where the `nym-recovery-cli` tool is located.
3. Execute the command prepared in Step 2.
Example:
```
./nym-recovery-cli --password "mySecurePassword123" --file "/path/to/mywallet.json"
```
To try multiple passwords:
```
./nym-recovery-cli --password "myFirstPassword" --password "mySecondPassword" --file "/path/to/mywallet.json"
```
## Step 4: Understanding the Output
The tool will attempt to decrypt the wallet file. If successful, it will print the decrypted content, including your mnemonic phrase.
## Step 5: If You Encounter Issues
- Verify the accuracy of the passwords and file path.
- Ensure there are no typos in the command.
- Make sure the wallet file's path is correctly specified.
## Additional Options
- `--raw`: Skips trying to parse the decrypted content, showing raw output instead.
This guide should help you safely recover your mnemonic phrase. Remember to keep it secure once retrieved.
+3 -3
View File
@@ -20,13 +20,13 @@ echo "Using $localnetdir for the localnet"
# initialise mixnet
echo "initialising mixnode1..."
cargo run --release --bin nym-mixnode -- init --id "mix1-$suffix" --host 127.0.0.1 --mix-port 10001 --verloc-port 20001 --http-api-port 30001 --metrics-key=lala --output=json >>"$localnetdir/mix1.json"
cargo run --release --bin nym-mixnode -- init --id "mix1-$suffix" --host 127.0.0.1 --mix-port 10001 --verloc-port 20001 --http-api-port 30001 --output=json >>"$localnetdir/mix1.json"
echo "initialising mixnode2..."
cargo run --release --bin nym-mixnode -- init --id "mix2-$suffix" --host 127.0.0.1 --mix-port 10002 --verloc-port 20002 --http-api-port 30002 --metrics-key=lala --output=json >>"$localnetdir/mix2.json"
cargo run --release --bin nym-mixnode -- init --id "mix2-$suffix" --host 127.0.0.1 --mix-port 10002 --verloc-port 20002 --http-api-port 30002 --output=json >>"$localnetdir/mix2.json"
echo "initialising mixnode3..."
cargo run --release --bin nym-mixnode -- init --id "mix3-$suffix" --host 127.0.0.1 --mix-port 10003 --verloc-port 20003 --http-api-port 30003 --metrics-key=lala --output=json >>"$localnetdir/mix3.json"
cargo run --release --bin nym-mixnode -- init --id "mix3-$suffix" --host 127.0.0.1 --mix-port 10003 --verloc-port 20003 --http-api-port 30003 --output=json >>"$localnetdir/mix3.json"
echo "initialising gateway..."
cargo run --release --bin nym-gateway -- init --id "gateway-$suffix" --host 127.0.0.1 --mix-port 10004 --clients-port 9000 --output=json >>"$localnetdir/gateway.json"
-83
View File
@@ -1,83 +0,0 @@
#!/bin/bash
# Check if the script is run as root
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root. Please use sudo or log in as the root user."
exit 1
fi
# Hardcoded node_exporter version
node_exporter_version="1.7.0"
# Create a user for node_exporter without a home directory
useradd --no-create-home --shell /bin/false node_exporter
# Download node_exporter
echo "Downloading node_exporter version $node_exporter_version..."
wget "https://github.com/prometheus/node_exporter/releases/download/v$node_exporter_version/node_exporter-$node_exporter_version.linux-amd64.tar.gz" -O /tmp/node_exporter-$node_exporter_version.linux-amd64.tar.gz
if [ $? -ne 0 ]; then
echo "Failed to download node_exporter."
exit 1
fi
# Unarchive node_exporter
echo "Unarchiving node_exporter..."
tar xvfz /tmp/node_exporter-$node_exporter_version.linux-amd64.tar.gz -C /tmp
if [ $? -ne 0 ]; then
echo "Failed to unarchive node_exporter."
exit 1
fi
# Move node_exporter to /usr/local/bin
echo "Moving node_exporter to /usr/local/bin..."
mv /tmp/node_exporter-$node_exporter_version.linux-amd64/node_exporter /usr/local/bin/node_exporter
if [ $? -ne 0 ]; then
echo "Failed to move node_exporter."
exit 1
fi
# Set ownership and permissions
chown node_exporter:node_exporter /usr/local/bin/node_exporter
chmod 0755 /usr/local/bin/node_exporter
# Create node_exporter service file
echo "Creating node_exporter service file..."
cat <<EOF > /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --web.config.file /etc/prometheus_node_exporter/configuration.yml
[Install]
WantedBy=multi-user.target
EOF
mkdir -p /etc/prometheus_node_exporter/
sudo cat << EOF > /etc/prometheus_node_exporter/configuration.yml
basic_auth_users:
prometheus: "\$2y\$10\$aB1RMr6ZGg2psbMOezmfluVzGcH/VHIqP4Lksx0DWuw/QSr9Iccwu"
EOF
ufw allow 9100
# Reload systemd, enable and start node_exporter service
echo "Configuring systemd for node_exporter..."
systemctl daemon-reload
systemctl enable node_exporter.service
systemctl start node_exporter.service
# Cleanup
echo "Cleaning up..."
rm -rf /tmp/node_exporter-${node_exporter_version}.linux-amd64.tar.gz
rm -rf /tmp/node_exporter-${node_exporter_version}.linux-amd64
echo "node_exporter installation and configuration complete."
-119
View File
@@ -1,119 +0,0 @@
import argparse
import os
import requests
import json
from collections import namedtuple
Config = namedtuple("Config", ["port", "outfile", "outlink", "env"])
def gateway_targets(entry):
targets = [
# Config(
# None,
# "/tmp/temp_targets_gateway.json",
# f"/tmp/prom_targets_gateway_{entry['env']}.json",
# entry["env"],
# ),
Config(
9100,
"/tmp/temp_targets_gateway_node.json",
f"/tmp/prom_targets_gateway_node_{entry['env']}.json",
entry["env"],
),
]
gateways = requests.get(f"{entry['nym_api']}/api/v1/gateways").json()
for config in targets:
config_to_targets(config, gateways, {"kind": "gateway"})
def mixnode_targets(entry):
targets = [
Config(
None,
"/tmp/temp_targets_mix.json",
f"/tmp/prom_targets_mix_{entry['env']}.json",
entry["env"],
),
Config(
9100,
"/tmp/temp_targets_node.json",
f"/tmp/prom_targets_node_{entry['env']}.json",
entry["env"],
),
]
mixnodes = requests.get(f"{entry['nym_api']}/api/v1/mixnodes").json()
for config in targets:
config_to_targets(config, mixnodes, {"kind": "mixnode"})
def validate_config_entry(entry):
return entry.get("nym_api") and entry.get("env")
def config_to_targets(config, mixnodes, labels=None):
prom_targets = [
make_prom_target(config.env, mixnode, config.port, labels)
for mixnode in mixnodes
]
with open(config.outfile, "w") as f:
json.dump(prom_targets, f)
os.chmod(config.outfile, 0o777)
os.rename(config.outfile, config.outlink)
os.chmod(config.outlink, 0o777)
print(f"Prometheus -> {len(prom_targets)} targets written to {config.outlink}")
def make_prom_target(env, mixnode, port=None, labels=None):
bond_info = mixnode.get("bond_information", {})
mix_node = bond_info.get("mix_node")
if mix_node is None:
mix_node = mixnode.get("gateway")
host = mix_node.get("host", None)
port = port if port else mix_node.get("http_api_port", None)
if host is None or port is None:
return None
target = {
"targets": [f"{host}:{port}"],
"labels": {
"mix_node_host": host,
"identity_key": mix_node.get("identity_key", None),
"sphinx_key": mix_node.get("sphinx_key", None),
"mix_node_version": mix_node.get("version", None),
"mixnet_env": env,
},
}
for k, v in labels.items():
target["labels"][k] = v
return target
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Create prometheus targets for rewarded set mixnodes."
)
parser.add_argument(
"config",
type=str,
help="Config file, see scripts/prom_targets_config.json",
)
args = parser.parse_args()
config_file = args.config
with open(config_file, "r") as f:
config = json.load(f)
for entry in config:
mixnode_targets(entry)
gateway_targets(entry)
-4
View File
@@ -1,4 +0,0 @@
[
{ "nym_api": "https://sandbox-nym-api1.nymtech.net", "env": "sandbox" },
{ "nym_api": "https://api.performance.nymte.ch", "env": "performance" }
]
-1
View File
@@ -1 +0,0 @@
requests
-43
View File
@@ -1,43 +0,0 @@
import json
import os
ips = [
"2.221.182.179",
"54.232.20.104",
"15.237.112.155",
"54.93.108.209",
"13.38.74.100",
"15.237.93.154",
"18.156.175.57",
"3.76.123.170",
]
port_range = range(18000, 18999)
def make_prom_target(ip, port, env):
return {
"targets": [f"{ip}:{port}"],
"labels": {
"mixnet_env": env,
},
}
if __name__ == "__main__":
outfile = "/tmp/tmp_static_prom_tragets.json"
outlink = "/tmp/static_prom_tragets.json"
targets = []
for ip in ips:
for port in port_range:
targets.append(make_prom_target(ip, port, "performance"))
with open(outfile, "w") as f:
json.dump(targets, f)
os.chmod(outfile, 0o777)
os.rename(outfile, outlink)
os.chmod(outlink, 0o777)
print(f"Prometheus -> {len(targets)} targets written to {outlink}")
-7
View File
@@ -1,7 +0,0 @@
# FFI
This repo contains bindings for C/C++ and Go in the respectively named directories.
`shared/` contains shared 'internal' functions which are imported by bindings. Primarily these functions rely on managing:
* that the client is not mutated by multiple threads simultaneously
* that client actions happen in blocking threads
+13 -344
View File
@@ -155,47 +155,6 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "askama"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
dependencies = [
"askama_derive",
"askama_escape",
]
[[package]]
name = "askama_derive"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
dependencies = [
"askama_parser",
"basic-toml",
"mime",
"mime_guess",
"proc-macro2",
"quote",
"serde",
"syn 2.0.48",
]
[[package]]
name = "askama_escape"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
[[package]]
name = "askama_parser"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
dependencies = [
"nom",
]
[[package]]
name = "async-trait"
version = "0.1.77"
@@ -281,15 +240,6 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "basic-toml"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5"
dependencies = [
"serde",
]
[[package]]
name = "bincode"
version = "1.3.3"
@@ -524,38 +474,6 @@ dependencies = [
"serde",
]
[[package]]
name = "camino"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
dependencies = [
"serde",
]
[[package]]
name = "cargo-platform"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d"
dependencies = [
"serde",
]
[[package]]
name = "cargo_metadata"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
"semver 1.0.21",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "cc"
version = "1.0.83"
@@ -1548,15 +1466,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
[[package]]
name = "fs-err"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41"
dependencies = [
"autocfg",
]
[[package]]
name = "funty"
version = "2.0.0"
@@ -1741,12 +1650,6 @@ dependencies = [
"url",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "gloo-net"
version = "0.3.1"
@@ -1793,17 +1696,6 @@ dependencies = [
"web-sys",
]
[[package]]
name = "goblin"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68"
dependencies = [
"log",
"plain",
"scroll",
]
[[package]]
name = "group"
version = "0.10.0"
@@ -2391,16 +2283,6 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@@ -2679,20 +2561,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "nym-cpp-ffi"
version = "0.1.1"
dependencies = [
"anyhow",
"bs58 0.5.0",
"lazy_static",
"nym-bin-common",
"nym-ffi-shared",
"nym-sdk",
"nym-sphinx-anonymous-replies",
"tokio",
]
[[package]]
name = "nym-credential-storage"
version = "0.1.0"
@@ -2828,21 +2696,6 @@ dependencies = [
"url",
]
[[package]]
name = "nym-ffi-shared"
version = "0.1.0"
dependencies = [
"anyhow",
"bs58 0.5.0",
"lazy_static",
"nym-bin-common",
"nym-sdk",
"nym-sphinx-anonymous-replies",
"tokio",
"uniffi",
"uniffi_build",
]
[[package]]
name = "nym-gateway-client"
version = "0.1.0"
@@ -3439,6 +3292,19 @@ dependencies = [
"x25519-dalek 2.0.0",
]
[[package]]
name = "nym_cpp_ffi"
version = "0.1.0"
dependencies = [
"anyhow",
"bs58 0.5.0",
"lazy_static",
"nym-bin-common",
"nym-sdk",
"nym-sphinx-anonymous-replies",
"tokio",
]
[[package]]
name = "object"
version = "0.32.2"
@@ -3454,12 +3320,6 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oneshot-uniffi"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c"
[[package]]
name = "opaque-debug"
version = "0.2.3"
@@ -3751,12 +3611,6 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "platforms"
version = "3.3.0"
@@ -4295,26 +4149,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scroll"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
dependencies = [
"scroll_derive",
]
[[package]]
name = "scroll_derive"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "sct"
version = "0.6.1"
@@ -4386,9 +4220,6 @@ name = "semver"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
dependencies = [
"serde",
]
[[package]]
name = "semver-parser"
@@ -4551,12 +4382,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "slab"
version = "0.4.9"
@@ -4824,12 +4649,6 @@ dependencies = [
"tokio-rustls 0.23.4",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stringprep"
version = "0.1.4"
@@ -5365,15 +5184,6 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
@@ -5407,138 +5217,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "uniffi"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21345172d31092fd48c47fd56c53d4ae9e41c4b1f559fb8c38c1ab1685fd919f"
dependencies = [
"anyhow",
"camino",
"clap",
"uniffi_bindgen",
"uniffi_build",
"uniffi_core",
"uniffi_macros",
]
[[package]]
name = "uniffi_bindgen"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd992f2929a053829d5875af1eff2ee3d7a7001cb3b9a46cc7895f2caede6940"
dependencies = [
"anyhow",
"askama",
"camino",
"cargo_metadata",
"clap",
"fs-err",
"glob",
"goblin",
"heck",
"once_cell",
"paste",
"serde",
"toml 0.5.11",
"uniffi_meta",
"uniffi_testing",
"uniffi_udl",
]
[[package]]
name = "uniffi_build"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "001964dd3682d600084b3aaf75acf9c3426699bc27b65e96bb32d175a31c74e9"
dependencies = [
"anyhow",
"camino",
"uniffi_bindgen",
]
[[package]]
name = "uniffi_checksum_derive"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55137c122f712d9330fd985d66fa61bdc381752e89c35708c13ce63049a3002c"
dependencies = [
"quote",
"syn 2.0.48",
]
[[package]]
name = "uniffi_core"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6121a127a3af1665cd90d12dd2b3683c2643c5103281d0fed5838324ca1fad5b"
dependencies = [
"anyhow",
"bytes",
"camino",
"log",
"once_cell",
"oneshot-uniffi",
"paste",
"static_assertions",
]
[[package]]
name = "uniffi_macros"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11cf7a58f101fcedafa5b77ea037999b88748607f0ef3a33eaa0efc5392e92e4"
dependencies = [
"bincode",
"camino",
"fs-err",
"once_cell",
"proc-macro2",
"quote",
"serde",
"syn 2.0.48",
"toml 0.5.11",
"uniffi_build",
"uniffi_meta",
]
[[package]]
name = "uniffi_meta"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71dc8573a7b1ac4b71643d6da34888273ebfc03440c525121f1b3634ad3417a2"
dependencies = [
"anyhow",
"bytes",
"siphasher",
"uniffi_checksum_derive",
]
[[package]]
name = "uniffi_testing"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "118448debffcb676ddbe8c5305fb933ab7e0123753e659a71dc4a693f8d9f23c"
dependencies = [
"anyhow",
"camino",
"cargo_metadata",
"fs-err",
"once_cell",
]
[[package]]
name = "uniffi_udl"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "889edb7109c6078abe0e53e9b4070cf74a6b3468d141bdf5ef1bd4d1dc24a1c3"
dependencies = [
"anyhow",
"uniffi_meta",
"uniffi_testing",
"weedle2",
]
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -5795,15 +5473,6 @@ dependencies = [
"webpki 0.22.4",
]
[[package]]
name = "weedle2"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e79c5206e1f43a2306fd64bdb95025ee4228960f2e6c5a8b173f3caaf807741"
dependencies = [
"nom",
]
[[package]]
name = "winapi"
version = "0.3.9"
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-cpp-ffi"
version = "0.1.1"
name = "nym_cpp_ffi"
version = "0.1.0"
edition = "2021"
[lib]
@@ -10,11 +10,11 @@ crate-type = ["cdylib"]
[dependencies]
# Async runtime
tokio = { version = "1", features = ["full"] }
# Nym clients, addressing, packet format, common tools (logging), ffi shared
# Nym clients, addressing, packet format, common tools (logging)
nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-bin-common = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-ffi-shared = { path = "../shared" }
# static var macro
lazy_static = "1.4.0"
# error handling
anyhow = "1.0.75"
+2 -2
View File
@@ -1,8 +1,8 @@
# C++ FFI
> ⚠️ This is an initial version of this library in order to give developers something to experiment with. If you use this code to begin testing out Mixnet integration and run into issues, errors, or have feedback, please feel free to open an issue; feedback from developers trying to use it will help us improve it. If you have questions feel free to reach out via our [Matrix channel](https://matrix.to/#/#dev:nymtech.chat).
> ⚠️ This is an initial version of this library in order to give developers something to experiment with. If you use this code to begin testing out Mixnet integration and run into issues, errors, or have feedback, please feel free to open an issue; feedback from developers trying to use it will help us improve it. If you have questions feel free to reach out via our [Matrix channel]().
This repo contains:
* `lib.rs`: an initial version of bindings for interacting with the Mixnet via the Rust SDK from C++. These are essentially match statements wrapping imported functions from the `nym-ffi-shared` lib allowing for nicer [error handling](#error-handling-).
* `lib.rs`: an initial version of bindings for interacting with the Mixnet via the Rust SDK from C++.
* `main.cpp`: an example of using this library, relying on `Boost` for threads.
The example `.cpp` file is a simple example flow of:
+1 -1
View File
@@ -44,7 +44,7 @@ else
build_artifacts_and_link;
./main;
else
printf "unknown optional argument - the only available optional argument is 'clean'"
echo "unknown optional argument - the only available optional argument is 'clean'"
exit 1
fi
fi
+171 -45
View File
@@ -1,13 +1,49 @@
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_ffi_shared;
use std::ffi::{c_char, c_int, CStr, CString};
use anyhow::{anyhow, bail};
use lazy_static::lazy_static;
use nym_sdk::mixnet::{MixnetClient, MixnetMessageSender, ReconstructedMessage};
use nym_sphinx_anonymous_replies::requests::AnonymousSenderTag;
use std::ffi::{c_char, c_int, CStr, CString};
use std::mem::forget;
mod types;
use crate::types::types::{CMessageCallback, CStringCallback, ReceivedMessage, StatusCode};
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
/*
NYM_CLIENT: Static reference (only init-ed once) to:
- Arc: share ownership
- Mutex: thread-safe way to share data between threads
- Option: init-ed or not
RUNTIME: Tokio runtime: no need to pass back to C and deal with raw pointers as it was previously
*/
lazy_static! {
static ref NYM_CLIENT: Arc<Mutex<Option<MixnetClient>>> = Arc::new(Mutex::new(None));
static ref RUNTIME: Runtime = Runtime::new().unwrap();
}
#[derive(Debug)]
pub enum StatusCode {
NoError = 0,
ClientInitError = -1,
ClientUninitialisedError = -2,
SelfAddrError = -3,
SendMsgError = -4,
ReplyError = -5,
ListenError = -6,
}
// pub type CIntCallback = extern "C" fn(i32);
pub type CStringCallback = extern "C" fn(*const c_char);
pub type CMessageCallback = extern "C" fn(ReceivedMessage);
// FFI-sanitised way of sending back a ReconstructedMessage to C
#[repr(C)]
pub struct ReceivedMessage {
message: *const u8,
size: usize,
sender_tag: *const c_char,
}
#[no_mangle]
pub extern "C" fn init_logging() {
@@ -16,31 +52,76 @@ pub extern "C" fn init_logging() {
#[no_mangle]
pub extern "C" fn init_ephemeral() -> c_int {
match nym_ffi_shared::init_ephemeral_internal() {
match init_ephemeral_internal() {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::ClientInitError as c_int,
}
}
fn init_ephemeral_internal() -> anyhow::Result<(), anyhow::Error> {
if NYM_CLIENT.lock().unwrap().as_ref().is_some() {
bail!("client already exists");
} else {
RUNTIME.block_on(async move {
let init_client = MixnetClient::connect_new().await?;
let mut client = NYM_CLIENT.try_lock();
if let Ok(ref mut client) = client {
**client = Some(init_client);
} else {
anyhow!("couldnt lock NYM_CLIENT");
}
Ok::<(), anyhow::Error>(())
})?;
}
Ok(())
}
#[no_mangle]
pub extern "C" fn get_self_address(callback: CStringCallback) -> c_int {
match nym_ffi_shared::get_self_address_internal(/*callback*/) {
Ok(addr) => {
let c_ptr = CString::new(addr).expect("could not convert Nym address to CString");
let call = CStringCallback::new(callback.callback);
// as_ptr() keeps ownership in rust unlike into_raw() so no need to free it
call.trigger(c_ptr.as_ptr());
StatusCode::NoError as c_int
}
match get_self_address_internal(callback) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::SelfAddrError as c_int,
}
}
fn get_self_address_internal(callback: CStringCallback) -> anyhow::Result<(), anyhow::Error> {
let client = NYM_CLIENT.lock().expect("could not lock NYM_CLIENT");
if client.is_none() {
bail!("Client is not yet initialised");
}
let nym_client = client
.as_ref()
.ok_or_else(|| anyhow!("could not get client as_ref()"))?;
// get address as cstring
let c_string = CString::new(nym_client.nym_address().to_string())?;
// as_ptr() keeps ownership in rust unlike into_raw() so no need to free it
callback(c_string.as_ptr());
Ok(())
}
#[no_mangle]
pub extern "C" fn send_message(recipient: *const c_char, message: *const c_char) -> c_int {
match send_message_internal(recipient, message) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::SendMsgError as c_int,
}
}
fn send_message_internal(
recipient: *const c_char,
message: *const c_char,
) -> anyhow::Result<(), anyhow::Error> {
let client = NYM_CLIENT.lock().expect("could not lock NYM_CLIENT");
if client.is_none() {
bail!("Client is not yet initialised");
}
let nym_client = client
.as_ref()
.ok_or_else(|| anyhow!("could not get client as_ref()"))?;
let c_str = unsafe {
if recipient.is_null() {
return StatusCode::RecipientNullError as c_int;
bail!("recipient is null");
}
let c_str = CStr::from_ptr(recipient);
c_str
@@ -49,24 +130,44 @@ pub extern "C" fn send_message(recipient: *const c_char, message: *const c_char)
let recipient = r_str.parse().unwrap();
let c_str = unsafe {
if message.is_null() {
return StatusCode::MessageNullError as c_int;
bail!("message is null");
}
let c_str = CStr::from_ptr(message);
c_str
};
let message = c_str.to_str().unwrap();
match nym_ffi_shared::send_message_internal(recipient, message) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::SendMsgError as c_int,
}
// send message
RUNTIME.block_on(async move {
nym_client.send_plain_message(recipient, message).await?;
Ok::<(), anyhow::Error>(())
})?;
Ok(())
}
#[no_mangle]
pub extern "C" fn reply(recipient: *const c_char, message: *const c_char) -> c_int {
match reply_internal(recipient, message) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::ReplyError as c_int,
}
}
fn reply_internal(
recipient: *const c_char,
message: *const c_char,
) -> anyhow::Result<(), anyhow::Error> {
let client = NYM_CLIENT.lock().expect("could not lock NYM_CLIENT");
if client.is_none() {
bail!("Client is not yet initialised");
}
let nym_client = client
.as_ref()
.ok_or_else(|| anyhow!("could not get client as_ref()"))?;
let recipient = unsafe {
if recipient.is_null() {
return StatusCode::RecipientNullError as c_int;
bail!("recipient is null");
}
let r_str = CStr::from_ptr(recipient).to_string_lossy().into_owned();
AnonymousSenderTag::try_from_base58_string(r_str)
@@ -74,39 +175,64 @@ pub extern "C" fn reply(recipient: *const c_char, message: *const c_char) -> c_i
};
let message = unsafe {
if message.is_null() {
return StatusCode::MessageNullError as c_int;
bail!("message is null");
}
let c_str = CStr::from_ptr(message);
let r_str = c_str.to_str().unwrap();
r_str
};
match nym_ffi_shared::reply_internal(recipient, message) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::ReplyError as c_int,
}
RUNTIME.block_on(async move {
nym_client.send_reply(recipient, message).await?;
Ok::<(), anyhow::Error>(())
})?;
Ok(())
}
#[no_mangle]
pub extern "C" fn listen_for_incoming(callback: CMessageCallback) -> c_int {
match nym_ffi_shared::listen_for_incoming_internal() {
Ok(received) => {
let message_ptr = received.message.as_ptr();
let message_length = received.message.len();
let c_string = CString::new(received.sender_tag.unwrap().to_string()).unwrap();
let sender_ptr = c_string.as_ptr();
// stop deallocation when out of scope as passing raw ptr to it elsewhere
forget(received);
let rec_for_c = ReceivedMessage {
message: message_ptr,
size: message_length,
sender_tag: sender_ptr,
};
let call = CMessageCallback::new(callback.callback);
call.trigger(rec_for_c);
StatusCode::NoError as c_int
}
match listen_for_incoming_internal(callback) {
Ok(_) => StatusCode::NoError as c_int,
Err(_) => StatusCode::ListenError as c_int,
}
}
fn listen_for_incoming_internal(callback: CMessageCallback) -> anyhow::Result<(), anyhow::Error> {
let mut binding = NYM_CLIENT.lock().expect("could not lock NYM_CLIENT");
if binding.is_none() {
bail!("recipient is null");
}
let client = binding
.as_mut()
.ok_or_else(|| anyhow!("could not get client as_ref()"))?;
RUNTIME.block_on(async move {
let received = wait_for_non_empty_message(client).await?;
let message_ptr = received.message.as_ptr();
let message_length = received.message.len();
let c_string = CString::new(received.sender_tag.unwrap().to_string())?;
let sender_ptr = c_string.as_ptr();
// stop deallocation when out of scope as passing raw ptr to it elsewhere
forget(received);
let rec_for_c = ReceivedMessage {
message: message_ptr,
size: message_length,
sender_tag: sender_ptr,
};
callback(rec_for_c);
Ok::<(), anyhow::Error>(())
})?;
Ok(())
}
pub async fn wait_for_non_empty_message(
client: &mut MixnetClient,
) -> anyhow::Result<ReconstructedMessage> {
while let Some(mut new_message) = client.wait_for_messages().await {
if !new_message.is_empty() {
return new_message
.pop()
.ok_or_else(|| anyhow!("could not get client as_ref()"));
}
}
bail!("(Rust) did not receive any non-empty message")
}
+5 -7
View File
@@ -67,7 +67,6 @@ int main() {
// - execute
// - get() returned val
// - handle val
// initialise an ephemeral client - aka one without specified keystore
boost::packaged_task<char> init(boost::bind(init_ephemeral));
boost::unique_future<char> init_future = init.get_future();
init();
@@ -78,7 +77,7 @@ int main() {
return_code = get_self_address(string_callback_function);
handle(return_code);
// send a message through the mixnet - in this case to ourselves using the value from get_self_address
// send a message through the mixnet - in this case to ourselves
std::cout << "(c++) message to send through mixnet: " << message << std::endl;
boost::packaged_task<char> send(boost::bind(send_message, addr, message));
boost::unique_future<char> send_future = send.get_future();
@@ -95,17 +94,16 @@ int main() {
return_code = listen_future.get();
handle(return_code);
// replying to incoming message (from ourselves) with SURBs - note that sending a message to a recipient and
// replying to an incoming are different functions: replying relies on parsing the incoming sender_tag on the Rust
// side and creating an AnonymousSenderTag type, instead of the Recipient type which relies on a nym address
// replying to incoming message (from ourselves) with SURBs- note that sending a message to a recipient and
// replying to an incoming are different functions
boost::packaged_task<char> reply_fn(boost::bind(reply, sender_tag, reply_message));
boost::unique_future<char> reply_future = reply_fn.get_future();
reply_fn();
return_code = reply_future.get();
handle(return_code);
// sleep so that the client processes can catch up - in reality you'd have another process running to keep logging
// going, so this is only necessary for this reference
// sleep so that the nym side logging can catch up - in reality you'd have another process running to keep logging
// going, so this is only necessary for this reference implementation
std::this_thread::sleep_for(std::chrono::seconds(40));
return 0;
-52
View File
@@ -1,52 +0,0 @@
pub mod types {
use std::ffi::c_char;
#[derive(Debug)]
pub enum StatusCode {
NoError = 0,
ClientInitError = -1,
ClientUninitialisedError = -2,
SelfAddrError = -3,
SendMsgError = -4,
ReplyError = -5,
ListenError = -6,
RecipientNullError = -7,
MessageNullError = -8,
}
#[repr(C)]
pub struct CStringCallback {
pub callback: extern "C" fn(*const c_char),
}
impl CStringCallback {
pub fn new(callback: extern "C" fn(*const c_char)) -> Self {
CStringCallback { callback }
}
pub fn trigger(&self, char: *const c_char) {
(self.callback)(char);
}
}
#[repr(C)]
pub struct CMessageCallback {
pub callback: extern "C" fn(ReceivedMessage),
}
impl CMessageCallback {
pub fn new(callback: extern "C" fn(ReceivedMessage)) -> Self {
CMessageCallback { callback }
}
pub fn trigger(&self, message: ReceivedMessage) {
(self.callback)(message)
}
}
#[repr(C)]
pub struct ReceivedMessage {
pub message: *const u8,
pub size: usize,
pub sender_tag: *const c_char,
}
}
-6061
View File
File diff suppressed because it is too large Load Diff
-31
View File
@@ -1,31 +0,0 @@
[package]
name = "nym-go-ffi" #"goffitest"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
name = "nym_go_ffi" #"go_ffi"
[dependencies]
# Bindgen
uniffi = { version = "0.25.2", features = ["cli"] }
# Nym clients, addressing, packet format, common tools (logging), ffi shared
nym-bin-common = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", branch = "master" }
nym-ffi-shared = { path = "../shared" }
# Async runtime
tokio = { version = "1", features = ["full"] }
lazy_static = "1.4.0"
# error handling
anyhow = "1.0.79"
thiserror = "1.0.56"
[build-dependencies]
uniffi = { version = "0.25.2", features = ["build" ] }
uniffi_build = { version = "0.25.2", features=["builtin-bindgen"] }
[[bin]]
name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"
-47
View File
@@ -1,47 +0,0 @@
# Go FFI
> ⚠️ This is an initial version of this library in order to give developers something to experiment with. If you use this code to begin testing out Mixnet integration and run into issues, errors, or have feedback, please feel free to open an issue; feedback from developers trying to use it will help us improve it. If you have questions feel free to reach out via our [Matrix channel](https://matrix.to/#/#dev:nymtech.chat).
This repo contains:
* `lib.rs`: an initial version of bindings for interacting with the Mixnet via the Rust SDK from Go. These are essentially match statemtns wrapping imported functions from the `nym-ffi-shared` lib.
* `ffi/`: a directory containing:
* the `bindings/` files generated using [`uniffi-bindgen-go`](https://github.com/NordSecurity/uniffi-bindgen-go)
* [`example.go`](./example.go): an example of using this library.
The `example.go` file is an example flow of:
* setting up Nym client logging
* creating an ephemeral Nym client (no key storage / persistent address - this will come in a future iteration)
* getting its [Nym address](https://nymtech.net/docs/clients/addressing-system.html)
* using that address to send a message to yourself via the Mixnet
* listen for and parse the incoming message for the `sender_tag` used for [anonymous replies with SURBs](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs)
* send a reply to yourself using SURBs
## Useage - Consuming the Library
You can import the bindings as normal and interact with them as shown in the [example file](./example.go). This example imports the bindings from the this repository (hence the `go.mod` and `go.sum` in the crate root) but you can import them remotely as usual.
## Useage - Developing on the Library
If you want to fork and add new features/functions to this library use the following instructions to rebuild the Go bindings.
Rust functions exposed to the Go binding library are in `./src/lib.rs`.
The `build.sh` script in the root of the repository speeds up the task of building and linking the Rust and Go code.
* if want to quickly recompile your code run it as-is with `./build.sh`
* if you want to clean build both the Rust and Go code after removing existing compiled binaries run it with the optional `clean` argument: `./build.sh clean`.
> Make sure to run the script from the root of the project directory, and that your LD PATH is set first!
> ```
> RUST_BINARIES=target/release
> echo 'export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:'${RUST_BINARIES} >> ~/.zshrc
> source ~/.zshrc
> ```
This script will:
* (optionally if called with `clean` argument) remove existing Rust and Go artifacts
* build `lib.rs` with the `--release` flag
* compile the Go bindings
**WIP** you need to manually add the following `cgo` flags to the generated bindings immediately underneath LN3 (`// #include <bindings.h`). In the future this will be automated in `build.sh`:
```
// #cgo LDFLAGS: -L../../target/release -lnym_go_ffi
```
-4
View File
@@ -1,4 +0,0 @@
fn main() {
uniffi::generate_scaffolding("src/bindings.udl").unwrap();
}
-53
View File
@@ -1,53 +0,0 @@
#!/bin/bash
PROJECT_NAME="go"
set -eu
MODE="--release"
GO_DIR="./go-nym"
UDL_PATH="./src/bindings.udl"
build_artifacts() {
# build rust
cargo build $MODE
# build go bindings
printf "building go bindings \n"
uniffi-bindgen-go $UDL_PATH --out-dir $GO_DIR
printf "bindings built \n\n"
# something not right with these - having to add it manually to bindings.go for the moment
# pushd $GO_DIR/bindings
# echo $(pwd)
# LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}:../../target/release" \
# CGO_LDFLAGS="-L../target/release -lnym_go_ffi -lm -ldl" \
# CGO_ENABLED=1 \
# go run ../main.go
}
clean_artifacts() {
# clean up existing things
rm -rf $GO_DIR
cargo clean
}
if [ $(pwd | awk -F/ '{print $NF}') != ${PROJECT_NAME} ]
then
printf "please run from root dir of project"
exit 1
fi
if [ $# -eq 0 ];
then
build_artifacts;
else
arg=$1
if [ "$arg" == "clean" ]; then
clean_artifacts;
build_artifacts;
else
printf "unknown optional argument - the only available optional argument is 'clean'"
exit 1
fi
fi
-74
View File
@@ -1,74 +0,0 @@
package main
import (
"fmt"
"nymffi/go-nym/bindings"
"time"
)
func main() {
// initialise Nym client logging - this is quite verbose but very informative
bindings.InitLogging()
// initialise an ephemeral client - aka one without specified keystore
err := bindings.InitEphemeral()
if err != nil {
fmt.Println(err)
return
}
// get our client's address
str, err2 := bindings.GetSelfAddress()
if err2 != nil {
fmt.Println("(Go) Error:", err2)
return
}
fmt.Println("(Go) response:")
fmt.Println(str)
// send a message through the mixnet - in this case to ourselves using the value from GetSelfAddress
err3 := bindings.SendMessage(str, "helloworld")
if err3 != nil {
fmt.Println("(Go) Error:", err3)
return
}
// listen out for incoming messages: in the future the client can be split into a listening and a sending client,
// allowing for this to run as a persistent process in its own thread and not have to block but instead be running
// concurrently
//
// assuming a data type like so:
// type IncomingMessage struct {
// Message string
// SenderTag vec<u8>
// }
incomingMessage, err4 := bindings.ListenForIncoming()
if err4 != nil {
fmt.Println("(Go) Error:", err4)
return
}
fmt.Println("(Go) incoming message: ", incomingMessage.Message, " from: ", incomingMessage.Sender)
// we can just use the byte array we parsed from the incoming message to reply with: this is a
// byte representation of the sender_tag used for Single Use Reply Blocks (SURBs)
//
// replying to incoming message (from ourselves) with SURBs - note that sending a message to a recipient and
// replying to an incoming are different functions: replying relies on parsing the incoming sender_tag on the Rust
// side and creating an AnonymousSenderTag type, instead of the Recipient type which relies on a nym address
//
// you will see in the client logs that there are requests for more SURBs that we send to ourselves to
// be able to fit the full reply message in there. In a future iteration of this code we can also expose
// a send() which allows for developers to dictate the number of SURBs to send along with their outgoing message
fmt.Println("(Go) replying to received message")
err5 := bindings.Reply(incomingMessage.Sender, "replyworld")
if err5 != nil {
fmt.Println("(Go) Error:", err5)
return
}
// sleep so that the nym client processes can catch up - in reality you'd have another process
// running to keep logging going, so this is only necessary for this reference
time.Sleep(30 * time.Second)
fmt.Println("(Go) end go example")
}
-8
View File
@@ -1,8 +0,0 @@
#include <bindings.h>
// This file exists beacause of
// https://github.com/golang/go/issues/11263
void cgo_rust_task_callback_bridge_bindings(RustTaskCallback cb, const void * taskData, int8_t status) {
cb(taskData, status);
}

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