diff --git a/.github/actions/nym-hash-releases/dist/index.js b/.github/actions/nym-hash-releases/dist/index.js index 6759b28f93..bd9ba671a3 100644 --- a/.github/actions/nym-hash-releases/dist/index.js +++ b/.github/actions/nym-hash-releases/dist/index.js @@ -23973,10 +23973,14 @@ function getBinInfo(path) { let mode = external_fs_.statSync(path).mode external_fs_.chmodSync(path, mode | 0o111) - const raw = (0,external_child_process_namespaceObject.execSync)(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" }); + 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 parsed = JSON.parse(raw) + console.log(` ✅ ok`); return parsed } catch (_) { + console.log(` ❌ failed`); return undefined } } @@ -23986,8 +23990,11 @@ 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('.tmp'); + external_fs_.mkdirSync(directory, { recursive: true }); } catch(e) { // ignore } @@ -24002,13 +24009,13 @@ async function run(assets, algorithm, filename, cache) { let sig = null; // cache in `${WORKING_DIR}/.tmp/` - const cacheFilename = external_path_.resolve(`.tmp/${asset.name}`); + const cacheFilename = external_path_.join(directory, `${asset.name}`); if(!external_fs_.existsSync(cacheFilename)) { - console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`); + console.log(`⬇️ Downloading ${asset.browser_download_url}... to ${cacheFilename} [${numAwaiting} of ${assets.length}]`); 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'); @@ -24093,6 +24100,7 @@ async function run(assets, algorithm, filename, cache) { } } } + console.log(`Completed hashing ${assets.length} files`); return hashes; } @@ -24122,8 +24130,8 @@ async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algo let releases; if(cache) { - const cacheFilename = external_path_.resolve(`.tmp/releases.json`); - if(!external_fs_.existsSync(cacheFilename)) { + const cacheFilename = __nccwpck_require__.ab + "releases.json"; + if(!external_fs_.existsSync(__nccwpck_require__.ab + "releases.json")) { releases = await octokit.paginate( octokit.rest.repos.listReleases, { @@ -24133,10 +24141,10 @@ async function createHashesFromReleaseTagOrNameOrId({ releaseTagOrNameOrId, algo }, (response) => response.data ); - external_fs_.writeFileSync(cacheFilename, JSON.stringify(releases, null, 2)); + external_fs_.writeFileSync(__nccwpck_require__.ab + "releases.json", JSON.stringify(releases, null, 2)); } else { console.log('Loading releases from cache...'); - releases = JSON.parse(external_fs_.readFileSync(cacheFilename)); + releases = JSON.parse(external_fs_.readFileSync(__nccwpck_require__.ab + "releases.json")); } } else { releases = await octokit.paginate( @@ -24172,9 +24180,10 @@ 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; } diff --git a/.github/actions/nym-hash-releases/src/create-hashes.mjs b/.github/actions/nym-hash-releases/src/create-hashes.mjs index 584d364a4c..6cf4d137cc 100644 --- a/.github/actions/nym-hash-releases/src/create-hashes.mjs +++ b/.github/actions/nym-hash-releases/src/create-hashes.mjs @@ -11,10 +11,14 @@ function getBinInfo(path) { let mode = fs.statSync(path).mode fs.chmodSync(path, mode | 0o111) - const raw = execSync(`${path} build-info --output=json`, { stdio: 'pipe', encoding: "utf8" }); + 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 parsed = JSON.parse(raw) + console.log(` ✅ ok`); return parsed } catch (_) { + console.log(` ❌ failed`); return undefined } } @@ -24,8 +28,11 @@ 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('.tmp'); + fs.mkdirSync(directory, { recursive: true }); } catch(e) { // ignore } @@ -40,13 +47,13 @@ async function run(assets, algorithm, filename, cache) { let sig = null; // cache in `${WORKING_DIR}/.tmp/` - const cacheFilename = path.resolve(`.tmp/${asset.name}`); + const cacheFilename = path.join(directory, `${asset.name}`); if(!fs.existsSync(cacheFilename)) { - console.log(`Downloading ${asset.browser_download_url}... to ${cacheFilename}`); + console.log(`⬇️ Downloading ${asset.browser_download_url}... to ${cacheFilename} [${numAwaiting} of ${assets.length}]`); 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'); @@ -131,6 +138,7 @@ async function run(assets, algorithm, filename, cache) { } } } + console.log(`Completed hashing ${assets.length} files`); return hashes; } @@ -210,9 +218,10 @@ 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; } diff --git a/.github/actions/nym-hash-releases/src/run-local.mjs b/.github/actions/nym-hash-releases/src/run-local.mjs index f2fc6addb8..f0998580ae 100644 --- a/.github/actions/nym-hash-releases/src/run-local.mjs +++ b/.github/actions/nym-hash-releases/src/run-local.mjs @@ -1,6 +1,11 @@ import {createHashesFromReleaseTagOrNameOrId} from './create-hashes.mjs'; -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}); +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}); diff --git a/.github/workflows/release-calculate-hash.yml b/.github/workflows/release-calculate-hash.yml index 00d253908a..fb493b8541 100644 --- a/.github/workflows/release-calculate-hash.yml +++ b/.github/workflows/release-calculate-hash.yml @@ -8,8 +8,8 @@ on: required: true type: string workflow_dispatch: - release_tag: - tag: + inputs: + release_tag: description: 'Release tag' required: true type: string @@ -24,10 +24,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 18 - - name: Install packages - run: cd ./.github/actions/nym-hash-releases && npm i - - - uses: ./.github/actions/nym-hash-releases + - uses: nymtech/nym/.github/actions/nym-hash-releases@develop env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/Cargo.lock b/Cargo.lock index 729e3e9374..02a9e4886e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -389,6 +389,16 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-file-watcher" +version = "0.1.0" +dependencies = [ + "futures", + "log", + "notify", + "tokio", +] + [[package]] name = "async-io" version = "1.13.0" @@ -547,9 +557,9 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.9", + "http-body 0.4.5", + "hyper 0.14.27", "itoa", "matchit", "memchr", @@ -577,8 +587,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 0.2.9", + "http-body 0.4.5", "mime", "rustversion", "tower-layer", @@ -3001,7 +3011,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http", + "http 0.2.9", "js-sys", "pin-project", "serde", @@ -3070,7 +3080,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.9", "indexmap 1.9.3", "slab", "tokio", @@ -3280,6 +3290,31 @@ 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" +dependencies = [ + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "http-body" version = "0.4.5" @@ -3287,7 +3322,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", - "http", + "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", "pin-project-lite 0.2.13", ] @@ -3355,8 +3413,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.9", + "http-body 0.4.5", "httparse", "httpdate", "itoa", @@ -3368,6 +3426,25 @@ 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" @@ -3375,8 +3452,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.9", + "hyper 0.14.27", "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", @@ -3388,12 +3465,28 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.27", "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" @@ -3718,7 +3811,7 @@ dependencies = [ "curl-sys", "event-listener", "futures-lite", - "http", + "http 0.2.9", "log", "once_cell", "polling", @@ -3850,6 +3943,17 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "ledger" +version = "0.1.0" +dependencies = [ + "bip32", + "k256", + "ledger-transport", + "ledger-transport-hid", + "thiserror", +] + [[package]] name = "ledger-apdu" version = "0.10.0" @@ -4492,9 +4596,9 @@ version = "1.2.4-rc.2" dependencies = [ "async-trait", "futures", + "http-api-client", "js-sys", "nym-bin-common", - "nym-http-api-client", "nym-ordered-buffer", "nym-service-providers-common", "nym-socks5-requests", @@ -4520,7 +4624,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.9", "httparse", "log", "memchr", @@ -4969,16 +5073,6 @@ dependencies = [ "ts-rs", ] -[[package]] -name = "nym-async-file-watcher" -version = "0.1.0" -dependencies = [ - "futures", - "log", - "notify", - "tokio", -] - [[package]] name = "nym-bandwidth-controller" version = "0.1.0" @@ -5167,7 +5261,10 @@ 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", @@ -5176,6 +5273,7 @@ dependencies = [ "nym-explorer-client", "nym-gateway-client", "nym-gateway-requests", + "nym-metrics", "nym-network-defaults", "nym-nonexhaustive-delayqueue", "nym-pemstore", @@ -5489,7 +5587,7 @@ dependencies = [ "dotenvy", "futures", "humantime-serde", - "hyper", + "hyper 0.14.27", "ipnetwork 0.16.0", "log", "nym-api-requests", @@ -5597,20 +5695,6 @@ dependencies = [ "serde", ] -[[package]] -name = "nym-http-api-client" -version = "0.1.0" -dependencies = [ - "async-trait", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tracing", - "url", - "wasmtimer", -] - [[package]] name = "nym-id" version = "0.1.0" @@ -5700,17 +5784,6 @@ dependencies = [ "url", ] -[[package]] -name = "nym-ledger" -version = "0.1.0" -dependencies = [ - "bip32", - "k256", - "ledger-transport", - "ledger-transport-hid", - "thiserror", -] - [[package]] name = "nym-metrics" version = "0.1.0" @@ -5719,7 +5792,6 @@ dependencies = [ "lazy_static", "log", "prometheus", - "regex", ] [[package]] @@ -5876,6 +5948,7 @@ version = "1.1.33" dependencies = [ "addr", "anyhow", + "async-file-watcher", "async-trait", "bs58 0.5.0", "clap 4.4.7", @@ -5884,7 +5957,6 @@ dependencies = [ "humantime-serde", "ipnetwork 0.20.0", "log", - "nym-async-file-watcher", "nym-bin-common", "nym-client-core", "nym-client-websocket-requests", @@ -5950,7 +6022,7 @@ dependencies = [ "dashmap", "fastrand 2.0.1", "hmac 0.12.1", - "hyper", + "hyper 0.14.27", "ipnetwork 0.16.0", "mime", "nym-config", @@ -5979,10 +6051,10 @@ version = "0.1.0" dependencies = [ "async-trait", "base64 0.21.4", + "http-api-client", "nym-bin-common", "nym-crypto", "nym-exit-policy", - "nym-http-api-client", "nym-wireguard-types", "schemars", "serde", @@ -6103,7 +6175,7 @@ dependencies = [ "dotenvy", "futures", "hex", - "http", + "http 0.2.9", "httpcodec", "libp2p", "log", @@ -6560,6 +6632,7 @@ dependencies = [ "eyre", "flate2", "futures", + "http-api-client", "itertools 0.10.5", "log", "nym-api-requests", @@ -6570,7 +6643,6 @@ dependencies = [ "nym-contracts-common", "nym-ephemera-common", "nym-group-contract-common", - "nym-http-api-client", "nym-mixnet-contract-common", "nym-multisig-contract-common", "nym-name-service-common", @@ -6696,6 +6768,7 @@ name = "nymvisor" version = "0.1.0" dependencies = [ "anyhow", + "async-file-watcher", "bytes", "clap 4.4.7", "dotenvy", @@ -6705,7 +6778,6 @@ dependencies = [ "humantime 2.1.0", "humantime-serde", "nix 0.27.1", - "nym-async-file-watcher", "nym-bin-common", "nym-config", "nym-task", @@ -6843,7 +6915,7 @@ checksum = "a819b71d6530c4297b49b3cae2939ab3a8cc1b9f382826a1bc29dd0ca3864906" dependencies = [ "async-trait", "bytes", - "http", + "http 0.2.9", "isahc", "opentelemetry_api", ] @@ -6857,7 +6929,7 @@ dependencies = [ "async-trait", "futures", "futures-executor", - "http", + "http 0.2.9", "isahc", "once_cell", "opentelemetry", @@ -8038,9 +8110,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.9", + "http-body 0.4.5", + "hyper 0.14.27", "hyper-rustls", "ipnet", "js-sys", @@ -8199,7 +8271,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfac3a1df83f8d4fc96aa41dba3b86c786417b7fc0f52ec76295df2ba781aa69" dependencies = [ - "http", + "http 0.2.9", "log", "regex", "rocket", @@ -8219,8 +8291,8 @@ dependencies = [ "cookie", "either", "futures", - "http", - "hyper", + "http 0.2.9", + "hyper 0.14.27", "indexmap 2.0.2", "log", "memchr", @@ -9024,9 +9096,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "snafu" @@ -9875,7 +9947,10 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", + "rustls 0.21.10", + "rustls-native-certs", "tokio", + "tokio-rustls 0.24.1", "tungstenite", ] @@ -9978,9 +10053,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.9", + "http-body 0.4.5", + "hyper 0.14.27", "hyper-timeout", "percent-encoding", "pin-project", @@ -10023,8 +10098,8 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", - "http-body", + "http 0.2.9", + "http-body 0.4.5", "http-range-header", "httpdate", "mime", @@ -10302,7 +10377,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.9", "httparse", "log", "rand 0.8.5", diff --git a/Cargo.toml b/Cargo.toml index 45afdbdb2c..6e322cc32a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -172,7 +172,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" diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index dc6c9bba2b..124611d348 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -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,6 +38,7 @@ 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" } @@ -48,6 +49,19 @@ 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"] @@ -58,6 +72,7 @@ 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 @@ -91,11 +106,15 @@ 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"] - diff --git a/common/client-core/src/client/key_manager/mod.rs b/common/client-core/src/client/key_manager/mod.rs index 6fb3858eb7..f01f8e2fbb 100644 --- a/common/client-core/src/client/key_manager/mod.rs +++ b/common/client-core/src/client/key_manager/mod.rs @@ -300,7 +300,7 @@ impl KeyManager { /// Gets an atomically reference counted pointer to [`SharedKey`]. pub fn gateway_shared_key(&self) -> Option> { - self.gateway_shared_key.as_ref().map(Arc::clone) + self.gateway_shared_key.clone() } pub fn remove_gateway_key(self) -> KeyManagerBuilder { diff --git a/common/client-core/src/client/packet_statistics_control.rs b/common/client-core/src/client/packet_statistics_control.rs index a50e0c596c..8f5aaf434d 100644 --- a/common/client-core/src/client/packet_statistics_control.rs +++ b/common/client-core/src/client/packet_statistics_control.rs @@ -3,8 +3,30 @@ 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 @@ -53,42 +75,60 @@ 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"); } } } @@ -465,6 +505,33 @@ 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; + 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 { @@ -477,6 +544,27 @@ 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(); @@ -501,3 +589,9 @@ impl PacketStatisticsControl { }) } } + +async fn serve_metrics( + _: Request, +) -> Result>, Infallible> { + Ok(Response::new(Full::new(Bytes::from(metrics!())))) +} diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 44b9a58e82..218a7894b1 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -49,6 +49,7 @@ 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] diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index bf73ecb8ca..cd3cc23d51 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -69,6 +69,10 @@ impl PacketRouter { } Ok(()) } + + pub fn mark_as_success(&mut self) { + self.shutdown.mark_as_success(); + } } impl GatewayPacketRouter for PacketRouter { diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index afc50c7233..e58ebbcabd 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -44,9 +44,7 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option { #[cfg(unix)] match _conn.get_ref() { MaybeTlsStream::Plain(stream) => Some(stream.as_raw_fd()), - &_ => unreachable!( - "If tls features are enabled, the inner stream needs to be unpacked into raw fd" - ), + &_ => None, } #[cfg(not(unix))] None @@ -99,7 +97,7 @@ impl PartiallyDelegated { pub(crate) fn split_and_listen_for_mixnet_messages( conn: WsConn, - packet_router: PacketRouter, + mut packet_router: PacketRouter, shared_key: Arc, mut shutdown: TaskClient, ) -> Self { @@ -142,6 +140,7 @@ 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)) } diff --git a/common/dkg/src/bte/proof_chunking.rs b/common/dkg/src/bte/proof_chunking.rs index 0cbadf5249..d438793275 100644 --- a/common/dkg/src/bte/proof_chunking.rs +++ b/common/dkg/src/bte/proof_chunking.rs @@ -837,7 +837,7 @@ mod tests { let share3 = chunks3.clone().try_into().unwrap(); let shares = vec![share1, share2, share3]; - let chunks = vec![chunks1, chunks2, chunks3]; + let chunks = &[chunks1, chunks2, chunks3]; for (i, pk_i) in pks.iter().enumerate() { let mut ciphertext_chunk_i = Vec::with_capacity(NUM_CHUNKS); diff --git a/common/ip-packet-requests/src/codec.rs b/common/ip-packet-requests/src/codec.rs index 86df1ce8f7..4047fec8e7 100644 --- a/common/ip-packet-requests/src/codec.rs +++ b/common/ip-packet-requests/src/codec.rs @@ -34,6 +34,13 @@ 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 { let mut bundled_packets = BytesMut::new(); @@ -47,7 +54,7 @@ impl MultiIpPacketCodec { } // Flush the current buffer and return it. - fn flush_current_buffer(&mut self) -> Bytes { + pub 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() diff --git a/common/ip-packet-requests/src/lib.rs b/common/ip-packet-requests/src/lib.rs index d0357d0aa4..6991567d7a 100644 --- a/common/ip-packet-requests/src/lib.rs +++ b/common/ip-packet-requests/src/lib.rs @@ -9,7 +9,8 @@ pub mod response; // version 3: initial version // version 4: IPv6 support // version 5: Add severity level to info response -pub const CURRENT_VERSION: u8 = 5; +// version 6: Increase the available IPs +pub const CURRENT_VERSION: u8 = 6; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct IpPair { diff --git a/common/network-defaults/src/lib.rs b/common/network-defaults/src/lib.rs index 608b6237c6..17968821bb 100644 --- a/common/network-defaults/src/lib.rs +++ b/common/network-defaults/src/lib.rs @@ -79,7 +79,13 @@ impl NymNetworkDetails { pub fn new_from_env() -> Self { fn get_optional_env>(env: K) -> Option { match var(env) { - Ok(var) => Some(var), + Ok(var) => { + if var.is_empty() { + None + } else { + Some(var) + } + } Err(VarError::NotPresent) => None, err => panic!("Unable to set: {:?}", err), } @@ -113,28 +119,15 @@ impl NymNetworkDetails { Some(var(var_names::NYM_API).expect("nym api not set")), get_optional_env(var_names::NYXD_WEBSOCKET), )) - .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_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_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, )) diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index 4cd9d0f53c..041bd116b1 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -16,11 +16,13 @@ pub const MIXNET_CONTRACT_ADDRESS: &str = "n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr"; pub const VESTING_CONTRACT_ADDRESS: &str = "n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw"; -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 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 REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy"; pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/"; diff --git a/common/nym-metrics/Cargo.toml b/common/nym-metrics/Cargo.toml index 0b49297719..537a69a142 100644 --- a/common/nym-metrics/Cargo.toml +++ b/common/nym-metrics/Cargo.toml @@ -14,5 +14,4 @@ license.workspace = true prometheus = { workspace = true } log = { workspace = true } dashmap = { workspace = true } -regex = "1.1" lazy_static = "1.4" diff --git a/common/nym-metrics/src/lib.rs b/common/nym-metrics/src/lib.rs index d67aae7b94..a9e22909d3 100644 --- a/common/nym-metrics/src/lib.rs +++ b/common/nym-metrics/src/lib.rs @@ -1,12 +1,47 @@ use dashmap::DashMap; pub use log::error; use log::{debug, warn}; -use regex::Regex; 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 ) => {{ @@ -14,13 +49,13 @@ macro_rules! nanos { // 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 RE: Regex = Regex::new(r"[^a-zA-Z0-9_]").unwrap(); pub static ref REGISTRY: MetricsController = MetricsController::default(); } @@ -43,6 +78,7 @@ fn fq_name(c: &dyn Collector) -> String { } impl Metric { + #[inline(always)] fn fq_name(&self) -> String { match self { Metric::C(c) => fq_name(c.as_ref()), @@ -50,6 +86,15 @@ impl Metric { } } + #[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), @@ -57,6 +102,7 @@ impl Metric { } } + #[inline(always)] fn set(&self, value: f64) { match self { Metric::C(_c) => { @@ -69,14 +115,8 @@ impl Metric { impl fmt::Display for MetricsController { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut buffer = vec![]; - let encoder = TextEncoder::new(); - let metrics = self.registry.gather(); - match encoder.encode(&metrics, &mut buffer) { - Ok(_) => {} - Err(e) => return write!(f, "Error encoding metrics to buffer: {}", e), - } - let output = match String::from_utf8(buffer) { + 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), }; @@ -85,6 +125,26 @@ impl fmt::Display for MetricsController { } impl MetricsController { + #[inline(always)] + pub fn gather(&self) -> Vec { + 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); @@ -101,6 +161,22 @@ impl MetricsController { } } + 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); @@ -161,9 +237,31 @@ impl MetricsController { } } -#[inline(always)] fn sanitize_metric_name(name: &str) -> String { - RE.replace_all(name, "_").to_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)] @@ -174,7 +272,7 @@ mod tests { fn test_sanitization() { assert_eq!( sanitize_metric_name("packets_sent_34.242.65.133:1789"), - "packets_sent_34_242_65_133_1789" + "packets_sent_34_242_65_133:1789" ) } } diff --git a/docker/typescript_client/upload_contract/package-lock.json b/docker/typescript_client/upload_contract/package-lock.json index 5afb3c4577..62bfcb02b9 100644 --- a/docker/typescript_client/upload_contract/package-lock.json +++ b/docker/typescript_client/upload_contract/package-lock.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@tsconfig/recommended": "^1.0.1", - "prettier": "^2.2.1", + "prettier": "^2.8.7", "typescript": "^4.1.3" } }, @@ -570,9 +570,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -875,15 +875,18 @@ } }, "node_modules/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/protobufjs": { @@ -1664,9 +1667,9 @@ } }, "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "fsevents": { "version": "2.3.2", @@ -1885,9 +1888,9 @@ "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, "prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "protobufjs": { diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 284f1e085b..af3c0c7b97 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -682,6 +682,8 @@ 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 { @@ -695,6 +697,14 @@ 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 diff --git a/documentation/operators/src/nodes/nym-api.md b/documentation/operators/src/nodes/nym-api.md index 2e3327f174..3753d2e80c 100644 --- a/documentation/operators/src/nodes/nym-api.md +++ b/documentation/operators/src/nodes/nym-api.md @@ -2,10 +2,6 @@ [//]: # (> The nym-api binary was built in the [building nym](../binaries/building-nym.md) 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? diff --git a/envs/local.env b/envs/local.env index 0fba848a3e..32d5516ccf 100644 --- a/envs/local.env +++ b/envs/local.env @@ -22,5 +22,3 @@ 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" diff --git a/envs/mainnet.env b/envs/mainnet.env index 018b4f2e38..e0b19d027a 100644 --- a/envs/mainnet.env +++ b/envs/mainnet.env @@ -11,18 +11,13 @@ 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" diff --git a/envs/qa.env b/envs/qa.env index fa323cf41d..886fbb65d3 100644 --- a/envs/qa.env +++ b/envs/qa.env @@ -25,5 +25,4 @@ 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" \ No newline at end of file diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index 6c9456224b..7a06f36697 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -92,6 +92,9 @@ pub(crate) enum RequestHandlingError { #[error("the provided credential did not have a bandwidth attribute")] MissingBandwidthAttribute, + + #[error("the DKG contract is unavailable")] + UnavailableDkgContract, } impl RequestHandlingError { @@ -600,7 +603,7 @@ where None => break, Some(Ok(socket_msg)) => socket_msg, Some(Err(err)) => { - error!("failed to obtain message from websocket stream! stopping connection handler: {err}"); + debug!("failed to obtain message from websocket stream! stopping connection handler: {err}"); break; } }; @@ -611,7 +614,7 @@ where if let Some(response) = self.handle_request(socket_msg).await { if let Err(err) = self.inner.send_websocket_message(response).await { - warn!( + debug!( "Failed to send message over websocket: {err}. Assuming the connection is dead.", ); break; @@ -621,13 +624,13 @@ where mix_messages = self.mix_receiver.next() => { let mix_messages = match mix_messages { None => { - warn!("mix receiver was closed! Assuming the connection is dead."); + debug!("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 { - warn!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead"); + debug!("failed to send the unwrapped sphinx packets back to the client - {err}, assuming the connection is dead"); break; } } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs b/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs index d075e01bb8..26a7e76640 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/coconut.rs @@ -36,6 +36,7 @@ pub(crate) struct CoconutVerifier { impl CoconutVerifier { pub async fn new( nyxd_client: DirectSigningHttpRpcNyxdClient, + only_coconut_credentials: bool, ) -> Result { let mix_denom_base = nyxd_client.current_chain_details().mix_denom.base.clone(); let address = nyxd_client.address(); @@ -45,9 +46,17 @@ 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() { - error!( - "DKG contract address is not available - no coconut credentials will be redeemable" - ); + 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); + } + return Ok(CoconutVerifier { address, nyxd_client: RwLock::new(nyxd_client), @@ -60,6 +69,10 @@ 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), diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index 46dc7f5f80..93ef0508fd 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -667,7 +667,7 @@ where let msg = match msg { Ok(msg) => msg, Err(err) => { - error!("failed to obtain message from websocket stream! stopping connection handler: {err}"); + debug!("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 - warn!("possibly received a sphinx packet without prior authentication. Request is going to be ignored"); + debug!("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( diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index e798389f40..30e1302d1a 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -447,7 +447,7 @@ impl Gateway { let coconut_verifier = { let nyxd_client = self.random_nyxd_client()?; - CoconutVerifier::new(nyxd_client).await + CoconutVerifier::new(nyxd_client, self.config.gateway.only_coconut_credentials).await }?; let mix_forwarding_channel = diff --git a/mixnode/src/node/http/legacy/stats.rs b/mixnode/src/node/http/legacy/stats.rs index 1bbc6eea21..c986acee2b 100644 --- a/mixnode/src/node/http/legacy/stats.rs +++ b/mixnode/src/node/http/legacy/stats.rs @@ -7,7 +7,7 @@ use axum::{ extract::{Query, State}, http::HeaderMap, }; -use nym_metrics::REGISTRY; +use nym_metrics::metrics; use nym_node::http::api::{FormattedResponse, Output}; use serde::{Deserialize, Serialize}; @@ -24,7 +24,7 @@ pub(crate) async fn metrics(State(state): State, headers: Heade 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) { - REGISTRY.to_string() + metrics!() } else { "Unauthorized".to_string() } @@ -50,7 +50,7 @@ pub(crate) async fn stats( async fn generate_stats(full: bool, stats: SharedNodeStats) -> NodeStatsResponse { let snapshot_data = stats.clone_data().await; if full { - NodeStatsResponse::Full(REGISTRY.to_string()) + NodeStatsResponse::Full(metrics!()) } else { NodeStatsResponse::Simple(snapshot_data.simplify()) } diff --git a/mixnode/src/node/node_statistics.rs b/mixnode/src/node/node_statistics.rs index 935ce6f3df..aaabbb7a30 100644 --- a/mixnode/src/node/node_statistics.rs +++ b/mixnode/src/node/node_statistics.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use nym_metrics::REGISTRY; +use nym_metrics::inc_by; use super::TaskClient; use futures::channel::mpsc; @@ -65,11 +65,14 @@ impl SharedNodeStats { guard.packets_dropped_since_startup_all += count; } - REGISTRY.inc_by("packets_received_since_startup", new_received); - REGISTRY.inc_by("packets_sent_since_startup_all", new_sent.values().sum()); - REGISTRY.inc_by( + inc_by!("packets_received_since_startup", new_received); + inc_by!( + "packets_sent_since_startup_all", + new_sent.values().sum::() + ); + inc_by!( "packets_dropped_since_startup_all", - new_dropped.values().sum(), + new_dropped.values().sum::() ); guard.packets_received_since_last_update = new_received; @@ -509,6 +512,7 @@ impl Controller { #[cfg(test)] mod tests { use super::*; + use nym_metrics::metrics; use nym_task::TaskManager; #[tokio::test] @@ -538,6 +542,6 @@ mod tests { 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!(REGISTRY.to_string(), "# HELP packets_dropped_since_startup_all packets_dropped_since_startup_all\n# TYPE packets_dropped_since_startup_all counter\npackets_dropped_since_startup_all 0\n# HELP packets_received_since_startup packets_received_since_startup\n# TYPE packets_received_since_startup counter\npackets_received_since_startup 0\n# HELP packets_sent_since_startup_all packets_sent_since_startup_all\n# TYPE packets_sent_since_startup_all counter\npackets_sent_since_startup_all 2\n") + 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") } } diff --git a/nym-api/tests/package-lock.json b/nym-api/tests/package-lock.json index b1d102687c..bb3eb4bc7c 100644 --- a/nym-api/tests/package-lock.json +++ b/nym-api/tests/package-lock.json @@ -2555,9 +2555,9 @@ "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -6845,9 +6845,9 @@ "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "form-data": { "version": "4.0.0", diff --git a/nym-api/tests/yarn.lock b/nym-api/tests/yarn.lock index b21ac8d13e..735fe57700 100644 --- a/nym-api/tests/yarn.lock +++ b/nym-api/tests/yarn.lock @@ -1568,9 +1568,9 @@ flatted@^3.1.0: integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== follow-redirects@^1.15.0: - version "1.15.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" - integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== form-data@4.0.0, form-data@^4.0.0: version "4.0.0" diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index abe59e81ac..4d3504d267 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -2529,7 +2529,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http", + "http 0.2.9", "js-sys", "pin-project", "serde", @@ -2664,7 +2664,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.9", "indexmap 1.9.3", "slab", "tokio", @@ -2833,6 +2833,31 @@ 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" +dependencies = [ + "async-trait", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "http-body" version = "0.4.5" @@ -2840,7 +2865,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", - "http", + "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", "pin-project-lite", ] @@ -2898,8 +2946,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.9", + "http-body 0.4.5", "httparse", "httpdate", "itoa 1.0.9", @@ -2911,6 +2959,25 @@ 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" @@ -2918,8 +2985,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.9", + "hyper 0.14.27", "rustls 0.21.7", "tokio", "tokio-rustls 0.24.1", @@ -2932,12 +2999,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.27", "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" @@ -3740,7 +3823,10 @@ 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", @@ -3749,6 +3835,7 @@ dependencies = [ "nym-explorer-client", "nym-gateway-client", "nym-gateway-requests", + "nym-metrics", "nym-network-defaults", "nym-nonexhaustive-delayqueue", "nym-pemstore", @@ -4091,17 +4178,13 @@ dependencies = [ ] [[package]] -name = "nym-http-api-client" +name = "nym-metrics" version = "0.1.0" dependencies = [ - "async-trait", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tracing", - "url", - "wasmtimer", + "dashmap", + "lazy_static", + "log", + "prometheus", ] [[package]] @@ -4507,6 +4590,7 @@ dependencies = [ "eyre", "flate2", "futures", + "http-api-client", "itertools", "log", "nym-api-requests", @@ -4517,7 +4601,6 @@ dependencies = [ "nym-contracts-common", "nym-ephemera-common", "nym-group-contract-common", - "nym-http-api-client", "nym-mixnet-contract-common", "nym-multisig-contract-common", "nym-name-service-common", @@ -5206,6 +5289,21 @@ 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" @@ -5238,6 +5336,12 @@ 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" @@ -5487,9 +5591,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.9", + "http-body 0.4.5", + "hyper 0.14.27", "hyper-rustls", "hyper-tls", "ipnet", @@ -6309,9 +6413,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -6787,7 +6891,7 @@ dependencies = [ "glob", "gtk", "heck 0.4.1", - "http", + "http 0.2.9", "ignore", "minisign-verify", "notify-rust", @@ -6887,7 +6991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769" dependencies = [ "gtk", - "http", + "http 0.2.9", "http-range", "rand 0.8.5", "raw-window-handle", @@ -7273,6 +7377,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", + "rustls 0.21.7", "tokio", "tungstenite", ] @@ -7450,7 +7555,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 0.2.9", "httparse", "log", "rand 0.8.5", @@ -8263,7 +8368,7 @@ dependencies = [ "glib", "gtk", "html5ever", - "http", + "http 0.2.9", "kuchiki", "libc", "log", diff --git a/scripts/prom_targets.py b/scripts/prom_targets.py index e7887e1ed1..44ea2a3c83 100644 --- a/scripts/prom_targets.py +++ b/scripts/prom_targets.py @@ -72,7 +72,9 @@ def config_to_targets(config, mixnodes, labels=None): def make_prom_target(env, mixnode, port=None, labels=None): bond_info = mixnode.get("bond_information", {}) - mix_node = bond_info.get("mix_node", {}) + 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: diff --git a/scripts/static_prom_targets.py b/scripts/static_prom_targets.py new file mode 100644 index 0000000000..e3490ea089 --- /dev/null +++ b/scripts/static_prom_targets.py @@ -0,0 +1,43 @@ +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}") diff --git a/sdk/rust/nym-sdk/examples/libp2p_shared/queue.rs b/sdk/rust/nym-sdk/examples/libp2p_shared/queue.rs index 2b59c82877..694b26c65f 100644 --- a/sdk/rust/nym-sdk/examples/libp2p_shared/queue.rs +++ b/sdk/rust/nym-sdk/examples/libp2p_shared/queue.rs @@ -76,9 +76,7 @@ impl MessageQueue { } pub(crate) fn pop(&mut self) -> Option { - let Some(head) = self.queue.first() else { - return None; - }; + let head = self.queue.first()?; if head.nonce == self.next_expected_nonce { self.next_expected_nonce = self.next_expected_nonce.wrapping_add(1); diff --git a/sdk/rust/nym-sdk/src/mixnet/native_client.rs b/sdk/rust/nym-sdk/src/mixnet/native_client.rs index e00322ec71..c4e4c13739 100644 --- a/sdk/rust/nym-sdk/src/mixnet/native_client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/native_client.rs @@ -174,6 +174,7 @@ impl MixnetClient { } } +#[derive(Clone)] pub struct MixnetClientSender { client_input: ClientInput, packet_type: Option, diff --git a/service-providers/ip-packet-router/src/constants.rs b/service-providers/ip-packet-router/src/constants.rs index eb7874f902..311087ad2a 100644 --- a/service-providers/ip-packet-router/src/constants.rs +++ b/service-providers/ip-packet-router/src/constants.rs @@ -4,10 +4,10 @@ use std::time::Duration; // The interface used to route traffic pub const TUN_BASE_NAME: &str = "nymtun"; pub const TUN_DEVICE_ADDRESS_V4: Ipv4Addr = Ipv4Addr::new(10, 0, 0, 1); -pub const TUN_DEVICE_NETMASK_V4: Ipv4Addr = Ipv4Addr::new(255, 255, 255, 0); +pub const TUN_DEVICE_NETMASK_V4: Ipv4Addr = Ipv4Addr::new(255, 255, 0, 0); pub const TUN_DEVICE_ADDRESS_V6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0xa160, 0, 0, 0, 0, 0x1); // 2001:db8:a160::1 -pub const TUN_DEVICE_NETMASK_V6: &str = "120"; +pub const TUN_DEVICE_NETMASK_V6: &str = "112"; // We routinely check if any clients needs to be disconnected at this interval pub(crate) const DISCONNECT_TIMER_INTERVAL: Duration = Duration::from_secs(10); diff --git a/service-providers/ip-packet-router/src/util/generate_new_ip.rs b/service-providers/ip-packet-router/src/util/generate_new_ip.rs index 71809cac00..2d2848d821 100644 --- a/service-providers/ip-packet-router/src/util/generate_new_ip.rs +++ b/service-providers/ip-packet-router/src/util/generate_new_ip.rs @@ -6,12 +6,13 @@ use crate::constants::{TUN_DEVICE_ADDRESS_V4, TUN_DEVICE_ADDRESS_V6}; // Find an available IP address in self.connected_clients // TODO: make this nicer -fn generate_random_ips_within_subnet() -> IpPair { - let mut rng = rand::thread_rng(); - // Generate a random number in the range 1-254 - let last_octet = rand::Rng::gen_range(&mut rng, 1..=254); - let ipv4 = Ipv4Addr::new(10, 0, 0, last_octet); - let ipv6 = Ipv6Addr::new(0x2001, 0x0db8, 0xa160, 0, 0, 0, 0, last_octet as u16); +fn generate_random_ips_within_subnet(rng: &mut R) -> IpPair { + // Generate a random number in the range 2-65535 + let last_bytes: u16 = rand::Rng::gen_range(rng, 2..=65534); + let before_last_byte = (last_bytes >> 8) as u8; + let last_byte = (last_bytes & 255) as u8; + let ipv4 = Ipv4Addr::new(10, 0, before_last_byte, last_byte); + let ipv6 = Ipv6Addr::new(0x2001, 0x0db8, 0xa160, 0, 0, 0, 0, last_bytes); IpPair::new(ipv4, ipv6) } @@ -32,7 +33,8 @@ pub(crate) fn find_new_ips( connected_clients_ipv4: &HashMap, connected_clients_ipv6: &HashMap, ) -> Option { - let mut new_ips = generate_random_ips_within_subnet(); + let mut rng = rand::thread_rng(); + let mut new_ips = generate_random_ips_within_subnet(&mut rng); let mut tries = 0; let tun_ips = IpPair::new(TUN_DEVICE_ADDRESS_V4, TUN_DEVICE_ADDRESS_V6); @@ -42,7 +44,7 @@ pub(crate) fn find_new_ips( tun_ips, new_ips, ) { - new_ips = generate_random_ips_within_subnet(); + new_ips = generate_random_ips_within_subnet(&mut rng); tries += 1; if tries > 100 { return None; @@ -50,3 +52,23 @@ pub(crate) fn find_new_ips( } Some(new_ips) } + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn verify_ip_generation() { + let mut map = HashSet::with_capacity(65533); + let mut rng = rand::rngs::mock::StepRng::new(0, 65540); + for _ in 2..65535 { + let pair = generate_random_ips_within_subnet(&mut rng); + println!("{:?}", pair); + assert!(!map.contains(&pair)); + map.insert(pair); + } + let pair = generate_random_ips_within_subnet(&mut rng); + assert!(map.contains(&pair)); + } +}