diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index 2e7d024f60c..a5169a3f268 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -1,4 +1,4 @@ -name: CD docs +name: cd-docs on: workflow_dispatch: @@ -26,7 +26,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace --release --all + args: --workspace --release - name: Install mdbook run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.33" mdbook) - name: Install mdbook plugins @@ -39,30 +39,6 @@ jobs: run: cd documentation && ./build_all_to_dist.sh continue-on-error: false - - name: Deploy branch master to dev - continue-on-error: true - uses: easingthemes/ssh-deploy@main - env: - SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }} - ARGS: "-rltgoDzvO --delete" - SOURCE: "dist/docs/" - REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_DEV }} - REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }} - TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/ - EXCLUDE: "/node_modules/" - - - name: Deploy branch master to prod - if: github.ref == 'refs/heads/master' - uses: easingthemes/ssh-deploy@main - env: - SSH_PRIVATE_KEY: ${{ secrets.CD_WWW_SSH_PRIVATE_KEY }} - ARGS: "-rltgoDzvO --delete" - SOURCE: "dist/docs/" - REMOTE_HOST: ${{ secrets.CD_WWW_REMOTE_HOST_PROD }} - REMOTE_USER: ${{ secrets.CD_WWW_REMOTE_USER }} - TARGET: ${{ secrets.CD_WWW_REMOTE_TARGET }}/ - EXCLUDE: "/node_modules/" - - name: Post process run: cd documentation && ./post_process.sh continue-on-error: false diff --git a/.github/workflows/ci-binary-checker.yml b/.github/workflows/ci-binary-config-checker.yml similarity index 96% rename from .github/workflows/ci-binary-checker.yml rename to .github/workflows/ci-binary-config-checker.yml index ec08504816f..07e14d67383 100644 --- a/.github/workflows/ci-binary-checker.yml +++ b/.github/workflows/ci-binary-config-checker.yml @@ -1,4 +1,4 @@ -name: Run config checks on all binaries +name: ci-binary-config-checker on: workflow_dispatch: diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index b503516e70e..3bcf0a26792 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -26,7 +26,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace --release --all + args: --workspace --release - name: Install mdbook run: (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.4.35" mdbook) - name: Install mdbook plugins diff --git a/.github/workflows/ci-nym-connect-desktop-rust.yml b/.github/workflows/ci-nym-connect-desktop-rust.yml index e5e56b8f437..77d5a0607b3 100644 --- a/.github/workflows/ci-nym-connect-desktop-rust.yml +++ b/.github/workflows/ci-nym-connect-desktop-rust.yml @@ -33,6 +33,12 @@ jobs: override: true components: rustfmt, clippy + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check + - name: Build all binaries uses: actions-rs/cargo@v1 with: @@ -45,12 +51,6 @@ jobs: command: test args: --manifest-path nym-connect/desktop/Cargo.toml --workspace - - name: Check formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --manifest-path nym-connect/desktop/Cargo.toml --all -- --check - - uses: actions-rs/clippy-check@v1 name: Clippy checks continue-on-error: true diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 9185c9f3041..3cadf150a2b 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -4,26 +4,26 @@ on: workflow_dispatch: schedule: - cron: '14 1 * * *' + jobs: build: strategy: fail-fast: false matrix: rust: [stable, beta] - os: [custom-linux, windows10, custom-runner-mac-m1] + os: [ubuntu-20.04, windows-latest, macos-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always continue-on-error: true steps: - - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler - continue-on-error: true - if: matrix.os == 'custom-linux' - - name: Check out repository code uses: actions/checkout@v3 + - name: Install Dependencies (Linux) + run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler + if: matrix.os == 'ubuntu-20.04' + - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: @@ -32,6 +32,12 @@ jobs: override: true components: rustfmt, clippy + - name: Install Protoc + uses: arduino/setup-protoc@v2 + if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest' + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Check formatting uses: actions-rs/cargo@v1 with: @@ -42,13 +48,27 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --workspace + args: --release --workspace - name: Build examples uses: actions-rs/cargo@v1 with: command: build - args: --workspace --examples + args: --release --workspace --examples + + # To avoid running out of disk space, skip generating debug symbols + - name: Set debug to false (unix) + if: matrix.os == 'ubuntu-20.04' || matrix.os == 'macos-latest' + run: | + sed -i.bak 's/\[profile.dev\]/\[profile.dev\]\ndebug = false/' Cargo.toml + git diff + + - name: Set debug to false (win) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + (Get-Content Cargo.toml) -replace '\[profile.dev\]', "`$&`ndebug = false" | Set-Content Cargo.toml + git diff - name: Run unit tests uses: actions-rs/cargo@v1 @@ -62,6 +82,11 @@ jobs: command: test args: --workspace -- --ignored + - name: Clean + uses: actions-rs/cargo@v1 + with: + command: clean + - name: Clippy uses: actions-rs/cargo@v1 with: diff --git a/.github/workflows/nightly-nym-connect-desktop-build.yml b/.github/workflows/nightly-nym-connect-desktop-build.yml new file mode 100644 index 00000000000..1e4560f9791 --- /dev/null +++ b/.github/workflows/nightly-nym-connect-desktop-build.yml @@ -0,0 +1,92 @@ +name: nightly-nym-connect-desktop-build + +on: + workflow_dispatch: + schedule: + - cron: '14 1 * * *' + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + env: + CARGO_TERM_COLOR: always + MANIFEST_PATH: --manifest-path nym-connect/desktop/Cargo.toml + continue-on-error: true + steps: + - name: Check out repository code + uses: actions/checkout@v3 + + - name: Install Dependencies (Linux) + run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools + if: matrix.os == 'ubuntu-20.04' + + - name: Install rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: ${{ env.MANIFEST_PATH }} --all -- --check + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: ${{ env.MANIFEST_PATH }} --release --workspace + + - name: Unit tests + uses: actions-rs/cargo@v1 + with: + command: test + args: ${{ env.MANIFEST_PATH }} --workspace + + - name: Clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings + + notification: + needs: build + runs-on: custom-linux + steps: + - name: Collect jobs status + uses: technote-space/workflow-conclusion-action@v2 + - name: Check out repository code + uses: actions/checkout@v3 + - name: install npm + uses: actions/setup-node@v3 + if: env.WORKFLOW_CONCLUSION == 'failure' + with: + node-version: 18 + - name: Matrix - Node Install + if: env.WORKFLOW_CONCLUSION == 'failure' + run: npm install + working-directory: .github/workflows/support-files + - name: Matrix - Send Notification + if: env.WORKFLOW_CONCLUSION == 'failure' + env: + NYM_NOTIFICATION_KIND: nightly + NYM_PROJECT_NAME: "nym-connect-desktop-nightly-build" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" + GIT_BRANCH: "${GITHUB_REF##*/}" + IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" + MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}" + MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}" + MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}" + MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}" + MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}" + uses: docker://keybaseio/client:stable-node + with: + args: .github/workflows/support-files/notifications/entry_point.sh diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index f4d32bd396b..b310ca4fa09 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -5,27 +5,24 @@ on: schedule: - cron: '14 1 * * *' -defaults: - run: - working-directory: nym-wallet - jobs: build: strategy: fail-fast: false matrix: - os: [custom-ubuntu-20.04, macos-latest, windows10] + os: [ubuntu-20.04, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always + MANIFEST_PATH: --manifest-path nym-wallet/Cargo.toml continue-on-error: true steps: - name: Check out repository code uses: actions/checkout@v3 - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler - if: matrix.os == 'custom-ubuntu-20.04' + run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools + if: matrix.os == 'ubuntu-20.04' - name: Install rust toolchain uses: actions-rs/toolchain@v1 @@ -35,40 +32,29 @@ jobs: override: true components: rustfmt, clippy - - name: Install Protoc - uses: arduino/setup-protoc@v2 - if: matrix.os == 'macos-latest' - - name: Check formatting uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check + args: ${{ env.MANIFEST_PATH }} --all -- --check - name: Build uses: actions-rs/cargo@v1 with: command: build - args: --workspace + args: ${{ env.MANIFEST_PATH }} --release --workspace - name: Unit tests uses: actions-rs/cargo@v1 with: command: test - args: --workspace - - - name: Annotate with clippy warnings - uses: actions-rs/clippy-check@v1 - continue-on-error: true - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --workspace + args: ${{ env.MANIFEST_PATH }} --workspace - name: Clippy uses: actions-rs/cargo@v1 with: command: clippy - args: --workspace --all-targets -- -D warnings + args: ${{ env.MANIFEST_PATH }} --workspace --all-targets -- -D warnings notification: needs: build diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index 63cb7426a70..af2db3dbf56 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -39,6 +39,7 @@ jobs: env: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # create variables @@ -73,6 +74,7 @@ jobs: ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0db3dfaf1fc..04209d93f7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,28 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -- add client registry to Gateway ([#3955]) -- add HTTP API to Gateway ([#3955]) -- add `/client/`, `clients` and `register` routes to the gateway ([#3955]) + +## [2023.3-kinder] (2023-10-31) + +- suppress error output ([#4056]) +- Update frontend type for current vesting period ([#4042]) +- re-exported additional types for tx queries ([#4036]) +- fixed fmt::Display impl for GatewayNetworkRequesterDetails ([#4033]) +- Add exit node policy from TorNull and Tor Exit Node Policy ([#4024]) +- basic self-described api for gateways to dynamically announce its details + nym-api aggregation ([#4017]) +- use saturating sub in case outfox is not enabled ([#3986]) +- Fix sorting for mixnodes and gateways ([#3985]) +- Gateway client registry and api routes ([#3955]) + +[#4056]: https://github.com/nymtech/nym/pull/4056 +[#4042]: https://github.com/nymtech/nym/pull/4042 +[#4036]: https://github.com/nymtech/nym/pull/4036 +[#4033]: https://github.com/nymtech/nym/pull/4033 +[#4024]: https://github.com/nymtech/nym/issues/4024 +[#4017]: https://github.com/nymtech/nym/issues/4017 +[#3986]: https://github.com/nymtech/nym/pull/3986 +[#3985]: https://github.com/nymtech/nym/pull/3985 +[#3955]: https://github.com/nymtech/nym/pull/3955 ## [2023.1-milka] (2023-09-24) diff --git a/Cargo.lock b/Cargo.lock index 6a86db4a8c5..03da6f53bb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2938,7 +2938,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "explorer-api" -version = "1.1.30" +version = "1.1.31" dependencies = [ "chrono", "clap 4.4.7", @@ -2994,7 +2994,7 @@ dependencies = [ [[package]] name = "extension-storage" -version = "1.2.0" +version = "1.2.1" dependencies = [ "bip39", "console_error_panic_hook", @@ -5568,7 +5568,7 @@ dependencies = [ [[package]] name = "mix-fetch-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "async-trait", "futures", @@ -5960,7 +5960,7 @@ dependencies = [ [[package]] name = "nym-api" -version = "1.1.31" +version = "1.1.32" dependencies = [ "actix-web", "anyhow", @@ -6110,7 +6110,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "base64 0.13.1", @@ -6183,7 +6183,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.30" +version = "1.1.31" dependencies = [ "clap 4.4.7", "dirs 4.0.0", @@ -6269,7 +6269,7 @@ dependencies = [ [[package]] name = "nym-client-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "anyhow", "futures", @@ -6526,7 +6526,7 @@ dependencies = [ [[package]] name = "nym-gateway" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "async-trait", @@ -6659,6 +6659,7 @@ dependencies = [ name = "nym-ip-packet-router" version = "0.1.0" dependencies = [ + "etherparse", "futures", "log", "nym-bin-common", @@ -6668,9 +6669,13 @@ dependencies = [ "nym-service-providers-common", "nym-sphinx", "nym-task", + "nym-wireguard", + "nym-wireguard-types", "serde", "serde_json", + "tap", "thiserror", + "tokio", ] [[package]] @@ -6708,7 +6713,7 @@ dependencies = [ [[package]] name = "nym-mixnode" -version = "1.1.31" +version = "1.1.32" dependencies = [ "anyhow", "axum", @@ -6828,7 +6833,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.30" +version = "1.1.31" dependencies = [ "anyhow", "async-file-watcher", @@ -6876,7 +6881,7 @@ dependencies = [ [[package]] name = "nym-network-statistics" -version = "1.1.30" +version = "1.1.31" dependencies = [ "dirs 4.0.0", "log", @@ -6964,7 +6969,7 @@ dependencies = [ [[package]] name = "nym-node-tester-wasm" -version = "1.2.0" +version = "1.2.1" dependencies = [ "futures", "js-sys", @@ -7120,7 +7125,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.30" +version = "1.1.31" dependencies = [ "clap 4.4.7", "lazy_static", @@ -7566,7 +7571,7 @@ dependencies = [ [[package]] name = "nym-wasm-sdk" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mix-fetch-wasm", "nym-client-wasm", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 4f714aeaef1..eaec06aa210 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.30" +version = "1.1.31" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index a3fa47e4a09..3dc2b411ce6 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.30" +version = "1.1.31" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/common/client-core/src/client/topology_control/nym_api_provider.rs b/common/client-core/src/client/topology_control/nym_api_provider.rs index 5de16663de2..824294793bf 100644 --- a/common/client-core/src/client/topology_control/nym_api_provider.rs +++ b/common/client-core/src/client/topology_control/nym_api_provider.rs @@ -69,7 +69,7 @@ impl NymApiTopologyProvider { Ok(mixes) => mixes, }; - let gateways = match self.validator_client.get_cached_gateways().await { + let gateways = match self.validator_client.get_cached_described_gateways().await { Err(err) => { error!("failed to get network gateways - {err}"); return None; diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index b253ed44cf8..4b50f0864b0 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -67,7 +67,7 @@ pub async fn current_gateways( log::trace!("Fetching list of gateways from: {nym_api}"); - let gateways = client.get_cached_gateways().await?; + let gateways = client.get_cached_described_gateways().await?; let valid_gateways = gateways .into_iter() .filter_map(|gateway| gateway.try_into().ok()) diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index 3b546320b61..750871e8814 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -119,6 +119,7 @@ pub struct GatewayNetworkRequesterDetails { pub encryption_key: String, pub open_proxy: bool, + pub exit_policy: bool, pub enabled_statistics: bool, // just a convenience wrapper around all the keys @@ -140,6 +141,7 @@ impl fmt::Display for GatewayNetworkRequesterDetails { writeln!(f, "\taddress: {}", self.address)?; writeln!(f, "\tuses open proxy: {}", self.open_proxy)?; + writeln!(f, "\tuses exit policy: {}", self.exit_policy)?; writeln!(f, "\tsends statistics: {}", self.enabled_statistics)?; writeln!(f, "\tallow list path: {}", self.allow_list_path)?; diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index dc226c56fd1..9d734ce8d9d 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -11,7 +11,7 @@ mod packet_relayer; mod platform; mod registered_peers; mod setup; -mod tun_task_channel; +pub mod tun_task_channel; mod udp_listener; mod wg_tunnel; @@ -20,7 +20,7 @@ use std::sync::Arc; // Currently the module related to setting up the virtual network device is platform specific. #[cfg(target_os = "linux")] -use platform::linux::tun_device; +pub use platform::linux::tun_device; /// Start wireguard UDP listener and TUN device /// @@ -32,16 +32,24 @@ pub async fn start_wireguard( task_client: nym_task::TaskClient, gateway_client_registry: Arc, ) -> Result<(), Box> { - // We can either index peers by their IP like standard wireguard + // TODO: make this configurable + + // We can optionally index peers by their IP like standard wireguard. If we don't then we do + // plain NAT where we match incoming destination IP with outgoing source IP. let peers_by_ip = Arc::new(tokio::sync::Mutex::new(network_table::NetworkTable::new())); - // ... or by their tunnel tag, which is a random number assigned to them - let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + // Alternative 1: + let routing_mode = tun_device::RoutingMode::new_allowed_ips(peers_by_ip.clone()); + // Alternative 2: + //let routing_mode = tun_device::RoutingMode::new_nat(); // Start the tun device that is used to relay traffic outbound - let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(peers_by_ip.clone()); + let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(routing_mode); tun.start(); + // We also index peers by a tag + let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); + // If we want to have the tun device on a separate host, it's the tun_task and // tun_task_response channels that needs to be sent over the network to the host where the tun // device is running. diff --git a/common/wireguard/src/platform/linux/mod.rs b/common/wireguard/src/platform/linux/mod.rs index ebe0ba212c6..fdf1de229d0 100644 --- a/common/wireguard/src/platform/linux/mod.rs +++ b/common/wireguard/src/platform/linux/mod.rs @@ -1 +1 @@ -pub(crate) mod tun_device; +pub mod tun_device; diff --git a/common/wireguard/src/platform/linux/tun_device.rs b/common/wireguard/src/platform/linux/tun_device.rs index 348abdb6097..638c00ce3f6 100644 --- a/common/wireguard/src/platform/linux/tun_device.rs +++ b/common/wireguard/src/platform/linux/tun_device.rs @@ -42,17 +42,42 @@ pub struct TunDevice { // And when we get replies, this is where we should send it tun_task_response_tx: TunTaskResponseTx, + routing_mode: RoutingMode, +} + +pub enum RoutingMode { // The routing table, as how wireguard does it - peers_by_ip: Arc>, + AllowedIps(AllowedIpsInner), // This is an alternative to the routing table, where we just match outgoing source IP with // incoming destination IP. + Nat(NatInner), +} + +impl RoutingMode { + pub fn new_nat() -> Self { + RoutingMode::Nat(NatInner { + nat_table: HashMap::new(), + }) + } + + pub fn new_allowed_ips(peers_by_ip: Arc>) -> Self { + RoutingMode::AllowedIps(AllowedIpsInner { peers_by_ip }) + } +} + +pub struct AllowedIpsInner { + peers_by_ip: Arc>, +} + +pub struct NatInner { nat_table: HashMap, } impl TunDevice { pub fn new( - peers_by_ip: Arc>, + routing_mode: RoutingMode, + // peers_by_ip: Option>>, ) -> (Self, TunTaskTx, TunTaskResponseRx) { let tun = setup_tokio_tun_device( format!("{TUN_BASE_NAME}%d").as_str(), @@ -69,8 +94,7 @@ impl TunDevice { tun_task_rx, tun_task_response_tx, tun, - peers_by_ip, - nat_table: HashMap::new(), + routing_mode, }; (tun_device, tun_task_tx, tun_task_response_rx) @@ -93,7 +117,9 @@ impl TunDevice { ); // TODO: expire old entries - self.nat_table.insert(src_addr, tag); + if let RoutingMode::Nat(nat_table) = &mut self.routing_mode { + nat_table.nat_table.insert(src_addr, tag); + } self.tun .write_all(&packet) @@ -121,30 +147,32 @@ impl TunDevice { // Route packet to the correct peer. - // This is how wireguard does it, by consulting the AllowedIPs table. - if false { - let peers = self.peers_by_ip.lock().await; - if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { - log::info!("Forward packet to wg tunnel"); - peer_tx - .send(Event::Ip(packet.to_vec().into())) - .await - .tap_err(|err| log::error!("{err}")) - .ok(); - return; + match self.routing_mode { + // This is how wireguard does it, by consulting the AllowedIPs table. + RoutingMode::AllowedIps(ref peers_by_ip) => { + let peers = peers_by_ip.peers_by_ip.as_ref().lock().await; + if let Some(peer_tx) = peers.longest_match(dst_addr).map(|(_, tx)| tx) { + log::info!("Forward packet to wg tunnel"); + peer_tx + .send(Event::Ip(packet.to_vec().into())) + .await + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } } - } - // But we do it by consulting the NAT table. - { - if let Some(tag) = self.nat_table.get(&dst_addr) { - log::info!("Forward packet to wg tunnel with tag: {tag}"); - self.tun_task_response_tx - .send((*tag, packet.to_vec())) - .await - .tap_err(|err| log::error!("{err}")) - .ok(); - return; + // But we do it by consulting the NAT table. + RoutingMode::Nat(ref nat_table) => { + if let Some(tag) = nat_table.nat_table.get(&dst_addr) { + log::info!("Forward packet to wg tunnel with tag: {tag}"); + self.tun_task_response_tx + .send((*tag, packet.to_vec())) + .await + .tap_err(|err| log::error!("{err}")) + .ok(); + return; + } } } diff --git a/common/wireguard/src/tun_task_channel.rs b/common/wireguard/src/tun_task_channel.rs index 1cbd6985dac..8928aa60497 100644 --- a/common/wireguard/src/tun_task_channel.rs +++ b/common/wireguard/src/tun_task_channel.rs @@ -7,7 +7,7 @@ pub struct TunTaskTx(mpsc::Sender); pub(crate) struct TunTaskRx(mpsc::Receiver); impl TunTaskTx { - pub(crate) async fn send( + pub async fn send( &self, data: TunTaskPayload, ) -> Result<(), tokio::sync::mpsc::error::SendError> { @@ -40,7 +40,7 @@ impl TunTaskResponseTx { } impl TunTaskResponseRx { - pub(crate) async fn recv(&mut self) -> Option { + pub async fn recv(&mut self) -> Option { self.0.recv().await } } diff --git a/documentation/README.md b/documentation/README.md index 59c5e321334..3defd29526f 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -9,5 +9,4 @@ Each directory contains a readme with more information about running and contrib ## Scripts * `bump_versions.sh` allows you to update the ~~`platform_release_version` and~~ `wallet_release_version` variable~~s~~ in the `book.toml` of each mdbook project at once. You can also optionally update the `minimum_rust_version` as well. Helpful for lazy-updating when cutting a new version of the docs. * `build_all_to_dist.sh` is used by the `ci-dev.yml` and `cd-dev.yml` scripts for building all mdbook projects and moving the rendered html to `../dist/` to be rsynced with various servers. - - +* `post_process.sh` is a script called by the github CI and CD workflows to post process CSS/image/href links for serving several mdbooks from a subdirectory. diff --git a/documentation/dev-portal/.gitignore b/documentation/dev-portal/.gitignore index c29699d0c00..1451d34afd2 100644 --- a/documentation/dev-portal/.gitignore +++ b/documentation/dev-portal/.gitignore @@ -19,4 +19,6 @@ theme/ theme theme/* -.idea \ No newline at end of file +.idea + +notes \ No newline at end of file diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 5dcbd3ba70c..cd930be17a5 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -18,14 +18,21 @@ # User Manuals -- [NymConnect Monero](tutorials/monero.md) -- [NymConnect Matrix](tutorials/matrix.md) -- [NymConnect Telegram](tutorials/telegram.md) +- [NymConnect X Monero](tutorials/monero.md) +- [NymConnect X Matrix](tutorials/matrix.md) +- [NymConnect X Telegram](tutorials/telegram.md) + +# Code Examples + +- [Custom Service Providers](examples/custom-services.md) +- [Apps Using Network Requesters](examples/using-nrs.md) +- [Browser only](examples/browser-only.md) +- [Monorepo examples](examples/monorepo-examples.md) # Integrations - [Integration Options](integrations/integration-options.md) -- [Mixnet Integration](integrations/mixnet-integration.md) +[//]: # (- [Mixnet Integration](integrations/mixnet-integration.md)) - [Payment Integration](integrations/payment-integration.md) # Tutorials @@ -40,15 +47,21 @@ - [Preparing Your Service](tutorials/cosmos-service/service.md) - [Preparing Your Service pt2](tutorials/cosmos-service/service-src.md) - [Querying the Chain](tutorials/cosmos-service/querying.md) + - [Typescript](tutorials/typescript.md) - - [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) - - [Tutorial Overview](tutorials/simple-service-provider/overview.md) - - [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md) - - [Building Your User Client](tutorials/simple-service-provider/user-client.md) - - [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md) - - [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md) - - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) - + - [[DEPRECATED] Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md) + - [Tutorial Overview](tutorials/simple-service-provider/overview.md) + - [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md) + - [Building Your User Client](tutorials/simple-service-provider/user-client.md) + - [Preparing Your Service Provider Environment](tutorials/simple-service-provider/preparating-env2.md) + - [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md) + - [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md) + +# Shipyard Builders Hackathon 2023 +- [General Info & Resources](shipyard/general.md) +- [Hackathon Challenges](shipyard/challenges-overview.md) +- [A Note on Infrastructure](shipyard/infra.md) +- [Submission Guidelines](shipyard/guidelines.md) # Events diff --git a/documentation/dev-portal/src/community-resources/community-applications-and-guides.md b/documentation/dev-portal/src/community-resources/community-applications-and-guides.md index 5186dceae1c..85a842342df 100644 --- a/documentation/dev-portal/src/community-resources/community-applications-and-guides.md +++ b/documentation/dev-portal/src/community-resources/community-applications-and-guides.md @@ -1,8 +1,6 @@ # Community Applications -We love seeing our developer community create applications using Nym. If you would like to share your application with the community, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal). - - +If you would like to share your application here, please submit a pull request to the `main` branch of the `nymtech/dev-portal` [repository](https://github.com/nymtech/dev-portal). ## Pastenym diff --git a/documentation/dev-portal/src/examples/browser-only.md b/documentation/dev-portal/src/examples/browser-only.md new file mode 100644 index 00000000000..e9f8a74a06d --- /dev/null +++ b/documentation/dev-portal/src/examples/browser-only.md @@ -0,0 +1,10 @@ +# Browser only +With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework. + +- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. + - [Website](https://notrustverify.github.io/mixfetch-examples/) + - [Codebase](https://github.com/notrustverify/mixfetch-examples) + +- There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials. For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html). + +- You can find a browser-based 'hello world' chat app [here](https://chat-demo.nymtech.net). Either open in two browser windows and send messages to yourself, or share with a friend and send messages to each other through the mixnet. diff --git a/documentation/dev-portal/src/examples/custom-services.md b/documentation/dev-portal/src/examples/custom-services.md new file mode 100644 index 00000000000..4602ffa7f05 --- /dev/null +++ b/documentation/dev-portal/src/examples/custom-services.md @@ -0,0 +1,16 @@ +# Custom Services +Custom services involve two pieces of code that communicate via the mixnet: a client, and a custom server/service. This custom service will most likely interact with the wider internet / a clearnet service on your behalf, with the mixnet between you and the service, acting as a privacy shield. + +- PasteNym is a private pastebin alternative. It involves a browser-based frontend utilising the Typescript SDK and a Python-based backend service communicating with a standalone Nym Websocket Client. **If you're a Python developer, start here!**. + - [Frontend codebase](https://github.com/notrustverify/pastenym) + - [Backend codebase](https://github.com/notrustverify/pastenym-frontend) + +- Nostr-Nym is another application written by [NoTrustVerify](https://notrustverify.ch/), standing between mixnet users and a Nostr server in order to protect their metadata from being revealed when gossiping. **Useful for Go and Python developers**. + - [Codebase](https://github.com/notrustverify/nostr-nym) + +- Spook and Nym-Ethtx are both examples of Ethereum transaction broadcasters utilising the mixnet, written in Rust. Since they were written before the release of the Rust SDK, they utilise standalone clients to communicate with the mixnet. + - [Spook](https://github.com/EdenBlockVC/spook) (**Typescript**) + - [Nym-Ethtx](https://github.com/noot/nym-ethtx) (**Rust**) + +- NymDrive is an early proof of concept application for privacy-enhanced file storage on IPFS. **JS and CSS**, and a good example of packaging as an Electrum app. + - [Codebase](https://github.com/saleel/nymdrive) diff --git a/documentation/dev-portal/src/examples/monorepo-examples.md b/documentation/dev-portal/src/examples/monorepo-examples.md new file mode 100644 index 00000000000..ad04287f20e --- /dev/null +++ b/documentation/dev-portal/src/examples/monorepo-examples.md @@ -0,0 +1,5 @@ +# Monorepo examples +As well as these examples, there are a bunch of examples for each SDK in the Nym monorepo. + +- [Rust SDK examples](https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples) +- [Typescript SDK examples](https://github.com/nymtech/nym/tree/develop/sdk/typescript/examples) \ No newline at end of file diff --git a/documentation/dev-portal/src/examples/using-nrs.md b/documentation/dev-portal/src/examples/using-nrs.md new file mode 100644 index 00000000000..0732340b792 --- /dev/null +++ b/documentation/dev-portal/src/examples/using-nrs.md @@ -0,0 +1,17 @@ +# Apps Using Network Requesters +These applications utilise custom app logic in the user-facing apps in order to communicate using the mixnet as a transport layer, without having to rely on custom server-side logic. Instead, they utilise existing Nym infrastructure - [Network Requesters](https://nymtech.net/operators/nodes/network-requester-setup.html) - with a custom whitelist addition. + +If you are sending 'normal' application traffic, and/or don't require and custom logic to be happening on the 'other side' of the mixnet, this is most likely the best option to take as a developer who wishes to privacy-enhance their application. + +> Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist + +- DarkFi over Nym leverages Nym’s mixnet as a pluggable transport for DarkIRC, their p2p IRC variant. Users can anonymously connect to peers over the network, ensuring secure and private communication within the DarkFi ecosystem. Written in **Rust**. + - [Docs](https://darkrenaissance.github.io/darkfi/clients/nym_outbound.html?highlight=nym#3--run) + - [Github](https://github.com/darkrenaissance/darkfi/tree/master/doc) + +- MiniBolt is a complete guide to building a Bitcoin & Lightning full node on a personal computer. It has the capacity to run network traffic (transactions and syncing) over the mixnet, so you can privately sync your node and not expose your home IP to the wider world when interacting with the rest of the network! + - [Docs](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core) + - [Codebase](https://github.com/minibolt-guide/minibolt) + +- Email over Nym is a set of configuration options to set up a Network Requester to send and recieve emails over Nym, using something like Thunderbird. + - [Codebase](https://github.com/dial0ut/nymstr-email) \ No newline at end of file diff --git a/documentation/dev-portal/src/infrastructure/node-types.md b/documentation/dev-portal/src/infrastructure/node-types.md index e864208cd36..cb5e9c3d359 100644 --- a/documentation/dev-portal/src/infrastructure/node-types.md +++ b/documentation/dev-portal/src/infrastructure/node-types.md @@ -4,43 +4,11 @@ Discover the workings of Nym's privacy-enhancing mixnet infrastructure through t -### Mixnet Infrastructure - -There are few types of Nym infrastructure nodes: - -#### Mix Nodes -Mix nodes play a critical role in the Nym network by providing enhanced security and privacy to network content and metadata. They are part of the three-layer mixnet that ensures that communication remains anonymous and untraceable. Mix nodes receive `NYM` tokens as compensation for their quality of service, which is measured by the network validators. - -Mix nodes anonymously relay encrypted Sphinx packets between each other, adding an extra layer of protection by reordering and delaying the packets before forwarding them to the intended recipient. Additionally, cover traffic is maintained through mix nodes sending Sphinx packets to other mix nodes, making it appear as if there is a constant flow of user messages and further protecting the privacy of legitimate data packets. - -With the ability to hide, reorder and add a delay to network traffic, mix nodes make it difficult for attackers to perform time-based correlation attacks and deanonymize users. By consistently delivering high-quality service, mix nodes are rewarded with NYM tokens, reinforcing the integrity of the Nym network. - -#### Gateways -Gateways serve as the point of entry for user data into the mixnet, verifying that users have acquired sufficient NYM-based bandwidth credentials before allowing encrypted packets to be forwarded to mixnodes. They are also responsible for safeguarding against denial of service attacks and act as a message storage for users who may go offline. - -Gateways receive bandwidth credentials from users, which are periodically redeemed for `NYM` tokens as payment for their services. Users have the flexibility to choose a single gateway, split traffic across multiple gateways, run their own gateways, or a combination of these options. - -In addition, gateways also cache messages, functioning as an inbox for users who are offline. By providing secure, reliable access to the mixnet and ensuring that data remains protected, gateways play a crucial role in maintaining the integrity of the Nym network. - -#### Validators -Validators are essential to the security and integrity of the Nym network, tasked with several key responsibilities. They utilize proof-of-stake Sybil defense measures to secure the network and determine which nodes are included within it. Through their collaborative efforts, validators create Coconut threshold credentials which provide anonymous access to network data and resources. - -Validators also play a critical role in maintaining the Nym Cosmos blockchain, a secure, public ledger that records network-wide information such as node public information and keys, network configuration parameters, CosmWasm smart contracts, and `NYM` and credential transactions. - -#### Service Providers -Service Providers are a crucial aspect of the Nym infrastructure that support the application layer of the Nym network. Any application built with Nym will require a Service Provider, which can be created by anyone. Service Providers run a piece of binary code that enables them to handle requests from Nym users or other services, and then make requests to external servers on behalf of the users. - -For example, a Service Provider could receive a request to check a mail server and then forward the response to the user. The presence of Service Providers in the Nym network enhances its security and privacy, making it a reliable and robust platform for anonymous communication and data exchange. - ### Where do I go from here? 💭 -Maybe you would like to concentrate on building a application that uses the mixnet: - -* Explore the Tutorials section of the Developer Portal. Our in-depth tutorial on [Building a Simple Service Provider](../tutorials/simple-service-provider/simple-service-provider.md) give a good understanding of building User Clients and Service Providers in TypeScript, and how to configure Nym Websocket Clients for seamless communication with the mixnet. - -* Get started with using the Nym Mixnet quickly and easily by exploring the [Quickstart](../quickstart/overview.md) options, such a NymConnect, proxying traffic through the Nym Socks5 client, or dive into integrating Nym into your existing application with the [Integrations](../integrations/integration-options.md) section. - -Or perhaps you a developer that would like to run a infrastructure node such as a Gateway, Mix node or Network Requestor: -* Check out the [Network Overview](https://nymtech.net/docs/architecture/network-overview.html) docs page. +For more in-depth information on the network architecture, head to the [Network Overview page](https://nymtech.net/docs/architecture/network-overview.html), and check out the [Operators book](https://nymtech.net/operators) if you want to run a node yourself. -* Take a look at our [Node Setup Guide](https://nymtech.net/operators/nodes/setup-guides.html) with our Nym Docs, containing setup guides for setting up you own infrastructure node. +If you would like to concentrate on building an application that uses the mixnet: +* Explore the [Quickstart](../quickstart/overview.md) options. +* Check out examples of [Community Apps](../community-resources/community-applications-and-guides.md). +* Run through the [Rust SDK](../tutorials/rust-sdk.md) or [Typescript](../tutorials/typescript.md) tutorials. diff --git a/documentation/dev-portal/src/integrations/integration-options.md b/documentation/dev-portal/src/integrations/integration-options.md index 56f00a33da6..328ec154a37 100644 --- a/documentation/dev-portal/src/integrations/integration-options.md +++ b/documentation/dev-portal/src/integrations/integration-options.md @@ -1,10 +1,14 @@ # Integration Options -If you've already gone through the different [Quick Start](../quickstart/overview.md) options, you have seen the possibilities avaliable to you for quickly connecting existing application code to another Nym process. +If you've already gone through the different [Quick Start](../quickstart/overview.md) options and had a look at the tutorials, you have seen the possibilities available to you for quickly connecting existing application code to another Nym process. -This section assumes you wish to integrate with Nym into your application code. +Below are a resources that will be useful for either beginning to integrate mixnet functionality into existing application code or build a new app using Nym. -The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. _This is a good place to start to get an overall idea of the tools and software avaliable to you_. +- **We suggest you begin with this [integration decision tree](https://sdk.nymtech.net/integrations)**. This will give you a better idea of what pieces of software (SDKs, standalone clients, service providers) your integration might involve, and what is currently possible to do with as little custom code as possible. + +- The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. + +- To get an idea of what is possible / has already been built, check the [community applications and resources](../community-resources/community-applications-and-guides.md) page, as well as the [developer tutorials codebase](https://github.com/nymtech/developer-tutorials). + +> If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page. -If you wish to integrate with Nym to use the mixnet for application traffic, start with the [mixnet integration](./mixnet-integration.md) page. -If you wish to integrate with the Nyx blockchain to use `NYM` for payments, start with the [payment integration](./payment-integration.md) page. diff --git a/documentation/dev-portal/src/integrations/mixnet-integration.md b/documentation/dev-portal/src/integrations/mixnet-integration.md index 91e6c2d5598..a26f0a885b6 100644 --- a/documentation/dev-portal/src/integrations/mixnet-integration.md +++ b/documentation/dev-portal/src/integrations/mixnet-integration.md @@ -13,7 +13,7 @@ As outlined in the [clients overview documentation](https://nymtech.net/docs/cli #### Websocket client Your first option is the native websocket client. This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It runs as a persistent process on a desktop or server machine. You can connect to it with any language that supports websockets. -You can see an example of how to connect to and manage interactions with this client in the [Simple Service Provider tutorial](../tutorials/simple-service-provider/simple-service-provider.md). +[//]: # (You can see an example of how to connect to and manage interactions with this client in the [Simple Service Provider tutorial](../tutorials/simple-service-provider/simple-service-provider.md).) #### Webassembly client If you’re working in JavaScript or Typescript in the browser, or building an edge computing app, you’ll likely want to choose the webassembly client. diff --git a/documentation/dev-portal/src/shipyard/challenges-overview.md b/documentation/dev-portal/src/shipyard/challenges-overview.md new file mode 100644 index 00000000000..4e02f5a797b --- /dev/null +++ b/documentation/dev-portal/src/shipyard/challenges-overview.md @@ -0,0 +1,53 @@ +# Hackathon Challenges +There are a few different challenges to choose from, each with different approaches. It is also recommended to check out the _**Examples**_ directory above for inspiration. + +## Tooling challenge +The tooling challenge involves creating tooling for users, operators, or developers of Nym. + +### Examples of user-centric tools: +- Facilitate onboarding new users more easily to staking their Nym, and understanding the pros and cons, as well as finding a good node to stake on. Examples of tools like this: + - [ExploreNym dashboard](https://explorenym.net/) + +- Show information on a dashboard about the network. NOTE due to the amount of dashboards currently available, we expect a good justification for why / something to set this apart from existing ones e.g. it is presenting information that is not already presented, or it is presented in a different manner, such as a TUI or CLI app instead of a web dashboard - maybe an onion service, or no-JS site for those who do not wish to enable Javascript in their day-to-day browsing. Examples of tools like this: + - [NTV's node dashboard](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1) + - [IsNymUp dashboard](https://isnymup.com/) + +### Examples of operator-centric tooling: +- An APY calculator for determining different financial outcomes of running a node in different situations. + +- Scripting for updating and maintaining nodes. Examples of tools like this: + - [ExploreNym's bash scripts](https://github.com/ExploreNYM/bash-tool) + +- Scripting for packaging node binaries for different OSes. + +### Examples of developer-centric tooling: +- Tooling for use in development: are there pain points you’ve found when developing apps with Nym that you have created scripts/hacks/workarounds for? Is there a pain point that you’ve thought ‘oh it would be great if I could just do X’? These are often the best places to start for building out developer tooling - if you’ve run into this issue, it's very likely someone else already has, or will! + +- Interacting with one of the SDKs via FFI: perhaps you’re a Go developer who would love to have the functionality of one of the Nym SDKs. Building an FFI tool might be something that would make your life easier, and can be shared with other developers in your situation. + +## Integrations challenge +Integration options for Nym are currently relatively restrictive due to the manner in which Nym handles sending and receiving traffic (as unordered Sphinx packets). This challenge will involve (most likely) implementing custom logic for handling Nym traffic for an existing application. + +There are several potential avenues developers can take here: +- If your application (or the application you wish to modify) is written in either Javascript or Typescript, and relies on the `fetch` library to make API calls, then you can use its drop-in replacement: [`mixfetch`](). Perhaps you wish to interact with Coingecko, or a private search engine like Kagi without leaking your IP and metadata, or an RPC endpoint. + - Example with [NTV’s privacy-preserving Coingecko API](https://github.com/notrustverify/mixfetch-examples) + - [Mixfetch docs examples](https://github.com/nymtech/nym/tree/develop/sdk/typescript/examples) + +- If you instead have an application that is able to use any of the SOCKS5, 4a, or 4 protocols (a rule of thumb: if it can communicate over Tor, it will) then you can experiment with using Nym as the transport layer. + - For Rustaceans, check out our [socks5 rust sdk example](https://nymtech.net/docs/sdk/rust.html#socks-client-example). + - For those of you who aren’t Crustaceans, then you will have to run the [Socks Client]() alongside your application as a separate process. _NOTE If you are taking this route, please make sure to include detailed documentation on how you expect users to do this, as well as including any process management tools, scripts, and configs (e.g. if you use systemd then include the configuration file for the client, as well as initialisation logic) that may streamline this process._ + - [NTV's PasteNym backend](https://github.com/notrustverify/pastenym) is a great example of an application with this architecture. + +- Nym is not only useful for blockchain-related apps, but for anything that requires network level privacy! Email clients, messaging clients, and decentralised storage are all key elements of the privacy-enabled web. Several of these sorts of apps can be found in the [community apps page](../community-resources/community-applications-and-guides.md). + +- There is currently a proof of concept using Rust Libp2p with Nym as a transport layer. Perhaps you can think of an app that uses Gossipsub for p2p communication could benefit from network-level privacy. + - [GossipSub chat example](https://github.com/nymtech/nym/tree/develop/sdk/rust/nym-sdk/examples/libp2p_chat) + - [Chainsafe's Lighthouse Nym PoC](https://github.com/ChainSafe/lighthouse/blob/nym/USE_NYM.md#usage) + +- Alternatively if you know of an app that is written in Rust or TS and could benefit from using Nym, you could fork and modify it using the SDKs. Applications such as: + - Magic Wormhole (has a [rust implementation](https://github.com/magic-wormhole/magic-wormhole.rs)) + - [Qual](https://github.com/qaul/qaul.net) (uses Rust Libp2p) + - [Syncthing](https://github.com/syncthing/syncthing) + +### MiniApp challenge +Write an app, either using one of the SDKs or a standalone client (harder). Think of what you can ‘nymify’ e.g. a version of the [TorBirdy](https://support.torproject.org/glossary/torbirdy/) extension that uses Nym instead of Tor. This is very similar to the Integration challenge in terms of the different potential _architectures_ and approaches, but just for new applications. diff --git a/documentation/dev-portal/src/shipyard/general.md b/documentation/dev-portal/src/shipyard/general.md new file mode 100644 index 00000000000..f07f3f22ac2 --- /dev/null +++ b/documentation/dev-portal/src/shipyard/general.md @@ -0,0 +1,16 @@ +# General Info & Resources +Discussions and announcements will be taking place in the [builders channel on Matrix](https://matrix.to/#/#shipyardbuilders:nymtech.chat). This channel can be used for all discussions. + +There will be daily office horse between 12-14:00 CET. + +This is an open call and questions will be answered on a first come first serve basis. + +The timetable can be found on the [Shipyard website](https://nymtech.net/learn/shipyard). + +## Links +- You can find **code examples**, **tutorials**, & **quickstart** information here, on the Developer Portal. +- [Rust SDK docs](https://nymtech.net/docs/sdk/rust.html) +- [Typescript SDK docs](https://sdk.nymtech.net) +- [Platform docs](https://nymtech.net/docs) +- [NoTrustVerify's Awesome Nym list](https://github.com/notrustverify/awesome-nym) +- [Builders channel Matrix](https://matrix.to/#/#shipyardbuilders:nymtech.chat) diff --git a/documentation/dev-portal/src/shipyard/guidelines.md b/documentation/dev-portal/src/shipyard/guidelines.md new file mode 100644 index 00000000000..ac8a7b18a8f --- /dev/null +++ b/documentation/dev-portal/src/shipyard/guidelines.md @@ -0,0 +1,12 @@ +# Submission Guidelines +We expect to see the following for submissions: +- Working code demos hosted publicly (Gitlab, Github, some other git instance). +- Quality > quantity here: we’d prefer to see a contained, working, and well documented Proof of Concept over a sprawling and messy app that does more but is poorly explained and presented. _The repo must be open source and able to be used and modified by others. The license is up to you._ +- If you already have existing apps / projects you are more than welcome to extend them, instead of starting from scratch - we will only be looking at the NEW additions to make this fair. If you are doing this, make sure to write a detailed account of what it is you;ve added to the existing project, preferably with the possibility to see the ‘old’ version as well as the new one. +- Proper documentation: + - If an app / tool: + - How do you install and run the code? How is it to be used? + - An overview of the application architecture: what is it doing? Is it relying on other services? + - If a UI-based solution: + - How to run it locally? We are happy to also accept staging deployments as part of the submission (e.g. via Vercel) but this does not replace being able to run it locally. +- Please make sure that your application works on commonly reproducible system environments (e.g. if you’re developing on Artix Linux please check for the necessary dependencies for more common-place OSes such as Debian, or Arch). If you are developing on Windows please make sure that it works on non-Windows machines also. Where possible please try to include build and install instructions for a variety of OSes. diff --git a/documentation/dev-portal/src/shipyard/infra.md b/documentation/dev-portal/src/shipyard/infra.md new file mode 100644 index 00000000000..73c3afadb33 --- /dev/null +++ b/documentation/dev-portal/src/shipyard/infra.md @@ -0,0 +1,12 @@ +# A Note on Infrastructure +If you are writing an application that requires sending messages through the mixnet, then you will either be relying on existing infrastructure nodes (network requesters), or writing your own custom service (for example, the service written as part of the Rust SDK tutorial). + +If you are relying on network requesters then chances are that the IPs or domains your app relies on will not already be on the whitelist. Ideally, you would [run your own,](https://nymtech.net/operators/nodes/network-requester-setup.html) but we will also run a few nodes in ‘open proxy’ mode and share the addresses so that you can use them when beginning to develop. + +## Node Details: +- NR1 + - Location: Singapore + - Nym Address: `FDeWfd8q686PWLXJDCqNJTCbydTk1KSux5HVftimsPyx.9XyThN4yh92eTMuLp1NvWicRZob8Ei5xpba9dvcMLxcN@9Byd9VAtyYMnbVAcqdoQxJnq76XEg2dbxbiF5Aa5Jj9J` +- NR2 + - Location: Frankfurt + - Nym Address: `BNypKaGiGY8GNRN4gpV95GcaVS8n7CrHuoZNgQ2ezqv2.ACpaixzuaSzuMajVQj6aR7cbpbvp676tm21MiLbX1gni@678qVUJ21uwxZBhp3r56z7GRf6gMh3NYDHruTegPtgMf` \ No newline at end of file diff --git a/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md b/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md index b08d988de28..ece24270414 100644 --- a/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md +++ b/documentation/dev-portal/src/tutorials/simple-service-provider/simple-service-provider.md @@ -1,5 +1,12 @@ # Building a Simple Service Provider +```admonish warning +This tutorial was written before the creation of the [Typescript SDK](https://sdk.nymtech.net), and involves running a Nym Client alongside your application processes, instead of relying on the SDK to integrate the Client process into your application logic. + +As such, although this tutorial is still a valid way of approaching building on Nym, it is a little less streamlined than it could be. + +A more streamlined rewrite of this tutorial will be coming soon. +``` This tutorial is the best place to start for developers new to Nym. You will learn how to build a minimum viable privacy-enabled application (PEApp) able to send and receive traffic via the mixnet. This tutorial is less about building an immediately useful application, and more about beginning to understand: diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index 093c35eea0f..d87f16e8f9d 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -6,6 +6,9 @@ language = "en" multilingual = false # for the moment - ideally work on chinese, brazillian, spanish next src = "src" +[rust] +edition = "2018" + ################# # PREPROCESSORS # ################# diff --git a/documentation/docs/src/SUMMARY.md b/documentation/docs/src/SUMMARY.md index 8e4f7c61276..24a625cfb2f 100644 --- a/documentation/docs/src/SUMMARY.md +++ b/documentation/docs/src/SUMMARY.md @@ -29,7 +29,20 @@ # SDK - [Typescript SDK](sdk/typescript.md) -- [Rust SDK](sdk/rust.md) +- [Rust SDK](sdk/rust/rust.md) + - [Message Types](sdk/rust/message-types.md) + - [Message Helpers](sdk/rust/message-helpers.md) + - [Troubleshooting](sdk/rust/troubleshooting.md) + - [Examples](sdk/rust/examples.md) + - [Simple Send](sdk/rust/examples/simple.md) + - [Create and Store Keys](sdk/rust/examples/keys.md) + - [Manual Storage](sdk/rust/examples/storage.md) + - [Anonymous Replies](sdk/rust/examples/surbs.md) + - [Use Custom Network Topology](sdk/rust/examples/custom-network.md) + - [Socks Proxy](sdk/rust/examples/socks.md) + - [Split Send and Receive](sdk/rust/examples/split-send.md) + - [Testnet Bandwidth Cred](sdk/rust/examples/credential.md) + - [Example Cargo file](sdk/rust/examples/cargo.md) # Wallet - [Desktop Wallet](wallet/desktop-wallet.md) diff --git a/documentation/docs/src/architecture/traffic-flow.md b/documentation/docs/src/architecture/traffic-flow.md index 09a2501abd1..863a03f577a 100644 --- a/documentation/docs/src/architecture/traffic-flow.md +++ b/documentation/docs/src/architecture/traffic-flow.md @@ -5,7 +5,7 @@ When you send data across the internet, it can be recorded by a wide range of ob Even if the content of a network request is encrypted, observers can still see that data was transmitted, its size, frequency of transmission, and gather metadata from unencrypted parts of the data (such as IP routing information). Adversaries may then combine all the leaked information to probabilistically de-anonymize users. -The Nym mixnet provides very strong security guarantees against this sort of surveillance. It _packetizes_ and _mixes_ together IP traffic from many users inside the _mixnet_. +The Nym mixnet provides very strong security guarantees against this sort of surveillance. It _packetises_ and _mixes_ together IP traffic from many users inside the _mixnet_. > If you're into comparisons, the Nym mixnet is conceptually similar to other systems such as Tor, but provides improved protections against end-to-end timing attacks which can de-anonymize users. When Tor was first fielded, in 2002, those kinds of attacks were regarded as science fiction. But the future is now here. @@ -69,7 +69,7 @@ From your Nym client, your encrypted traffic is sent to: Whatever is on the 'other side' of the mixnet from your client, all traffic will travel this way through the mixnet. If you are sending traffic to a service external to Nym (such as a chat application's servers) then your traffic will be sent from the recieving Nym client to an application that will proxy it 'out' of the mixnet to these servers, shielding your metadata from them. P2P (peer-to-peer) applications, unlike the majority of apps, might want to keep all of their traffic entirely 'within' the mixnet, as they don't have to necessarily make outbound network requests to application servers. They would simply have their local application code communicate with their Nym clients, and not forward traffic anywhere 'outside' of the mixnet. ## Acks & Package Retransmission -Whenever a hop is completed, the recieving node will send back an acknowledgement ('ack') so that the sending node knows that the packet was recieved. If it does not recieve an ack after sending, it will resend the packet, as it assumes that the packet was dropped for some reason. This is done under the hood by the binaries themselves, and is never something that developers and node operators have to worry about dealing with themselves. +Whenever a hop is completed, the receiving node will send back an acknowledgement ('ack') so that the sending node knows that the packet was received. If it does not receive an ack after sending, it will resend the packet, as it assumes that the packet was dropped for some reason. This is done under the hood by the binaries themselves, and is never something that developers and node operators have to worry about dealing with themselves. Packet retransmission means that if a client sends 100 packets to a gateway, but only receives an acknowledgement ('ack') for 95 of them, it will resend those 5 packets to the gateway again, to make sure that all packets are received. All nodes in the mixnet support packet retransmission. diff --git a/documentation/docs/src/clients/overview.md b/documentation/docs/src/clients/overview.md index c8d2db15034..b9b5686dbd0 100644 --- a/documentation/docs/src/clients/overview.md +++ b/documentation/docs/src/clients/overview.md @@ -25,7 +25,7 @@ You need to choose which one you want incorporate into your app. Which one you u ### The websocket client Your first option is the native websocket client (`nym-client`). This is a compiled program that can run on Linux, Mac OS X, and Windows machines. It can be run as a persistent process on a desktop or server machine. You can connect to it with **any language that supports websockets**. -_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust.md)_. +_Rust developers can import websocket client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_. ### The webassembly client If you're working in JavaScript or Typescript in the browser, or building an [edge computing](https://en.wikipedia.org/wiki/Edge_computing) app, you'll likely want to choose the webassembly client. @@ -39,7 +39,7 @@ The `nym-socks5-client` is useful for allowing existing applications to use the When used as a standalone client, it's less flexible as a way of writing custom applications than the other clients, but able to be used to proxy application traffic through the mixnet without having to make any code changes. -_Rust developers can import socks client functionality into their code via the [Rust SDK](../sdk/rust.md)_. +_Rust developers can import socks client functionality into their code via the [Rust SDK](../sdk/rust/rust.md)_. ## Commonalities between clients All Nym client packages present basically the same capabilities to the privacy application developer. They need to run as a persistent process in order to stay connected and ready to receive any incoming messages from their gateway nodes. They register and authenticate to gateways, and encrypt Sphinx packets. diff --git a/documentation/docs/src/introduction.md b/documentation/docs/src/introduction.md index 9e5912ba074..c9b4c4a7d5e 100644 --- a/documentation/docs/src/introduction.md +++ b/documentation/docs/src/introduction.md @@ -15,7 +15,7 @@ If you're specically looking for TypeScript/JavaScript related information such **SDK examples:** * [Typescript SDK](https://sdk.nymtech.net/) -* [Rust SDK](./sdk/rust.md) +* [Rust SDK](sdk/rust/rust.md) **Nyx** * [Interacting with the Nyx chain](./nyx/interacting-with-chain.md) diff --git a/documentation/docs/src/sdk/rust.md b/documentation/docs/src/sdk/rust.md deleted file mode 100644 index b62353a9d63..00000000000 --- a/documentation/docs/src/sdk/rust.md +++ /dev/null @@ -1,144 +0,0 @@ -# Rust SDK -The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a seperate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a seperate console window/tab) and being able to have a single binary for other people to use. - -Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../clients/websocket-client.md)) or [`socks-client`](../clients/socks5-client.md) functionality into their Rust code. - -## Development status -The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases. - -The `nym-sdk` crate is **not yet availiable via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: - -```toml -nym-sdk = { git = "https://github.com/nymtech/nym" } -``` - -In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` - -In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym's infrastructure. - -| Component | Functionality | Released | -| --------- | ------------------------------------------------------------------------------------- | -------- | -| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ | -| Coconut | Create & verify Coconut credentials | 🛠️ | -| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ | - -The `mixnet` component currently exposes the logic of two clients: the [websocket client](../clients/websocket-client.md), and the [socks](../clients/socks5-client.md) client. - -The `coconut` component is currently being worked on. Right now it exposes logic allowing for the creation of coconut credentials on the Sandbox testnet. - -## Websocket client examples -> All the codeblocks below can be found in the `nym-sdk` [examples directory](https://github.com/nymtech/nym/tree/master/sdk/rust/nym-sdk/examples) in the monorepo. Just navigate to `nym/sdk/rust/nym-sdk/examples/` and run the files from there. If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. - -### Different message types -There are two methods for sending messages through the mixnet using your client: -* `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`. -* `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes). - -### Simple example -Lets look at a very simple example of how you can import and use the websocket client in a piece of Rust code (`examples/simple.rs`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/simple.rs}} -``` - -Simply importing the `nym_sdk` crate into your project allows you to create a client and send traffic through the mixnet. - -### Creating and storing keypairs -The example above involves ephemeral keys - if we want to create and then maintain a client identity over time, our code becomes a little more complex as we need to create, store, and conditionally load these keys (`examples/builder_with_storage`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} -``` - -As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple. - -Assuming our client config is stored in `/tmp/mixnet-client`, the following files are generated: -``` -$ tree /tmp/mixnet-client - -mixnet-client -├── ack_key.pem -├── db.sqlite -├── db.sqlite-shm -├── db.sqlite-wal -├── gateway_details.json -├── gateway_shared.pem -├── persistent_reply_store.sqlite -├── private_encryption.pem -├── private_identity.pem -├── public_encryption.pem -└── public_identity.pem - -1 directory, 11 files -``` - -### Manually handling storage -If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`) - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} -``` - -### Anonymous replies with SURBs -Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. - -The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). - - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} -``` - -You can read more about how SURBs function under the hood [here](../architecture/traffic-flow.md#private-replies-using-surbs). - -In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} -``` - -### Importing and using a custom network topology -If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html) (`examples/custom_topology_provider.rs`). - -There are two ways to do this: - -#### Import a custom Nym API endpoint -If you are also running a Validator and Nym API for your network, you can specify that endpoint as such and interact with it as clients usually do (under the hood): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} -``` - -#### Import a specific topology manually -If you aren't running a Validator and Nym API, and just want to import a specific sub-set of mix nodes, you can simply overwrite the grabbed topology manually: - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} -``` - -### Send and receive in different tasks -If you need to split the different actions of your client across different tasks, you can do so like this: - -```rust, noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} -``` - -## Socks client example -There is also the option to embed the [`socks5-client`](../clients/socks5-client.md) into your app code (`examples/socks5.rs`): - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/socks5.rs}} -``` - -```admonish info -If you are looking at implementing Nym as a transport layer for a crypto wallet or desktop app, this is probably the best place to start. -``` - -## Coconut credential generation -The following code shows how you can use the SDK to create and use a [credential](../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. - -```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} -``` - -You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../coconut.md). diff --git a/documentation/docs/src/sdk/rust/examples.md b/documentation/docs/src/sdk/rust/examples.md new file mode 100644 index 00000000000..648c32fa0dc --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples.md @@ -0,0 +1,12 @@ +# Examples + +All the following examples can be found in the `nym-sdk` [examples directory](https://github.com/nymtech/nym/tree/master/sdk/rust/nym-sdk/examples) in the monorepo. Just navigate to `nym/sdk/rust/nym-sdk/examples/` and run the files from there with: + +```sh +cargo run --example +``` + +If you wish to run these outside of the workspace - such as if you want to use one as the basis for your own project - then make sure to import the `sdk`, `tokio`, and `nym_bin_common` crates. + +An example `Cargo.toml` file can be found [here](examples/cargo.md). + diff --git a/documentation/docs/src/sdk/rust/examples/cargo.md b/documentation/docs/src/sdk/rust/examples/cargo.md new file mode 100644 index 00000000000..e425e124edb --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/cargo.md @@ -0,0 +1,35 @@ +# Example Cargo File +This file imports the basic requirements for running these pieces of example code, and can be used as the basis for your own cargo project. + +```toml +[package] +name = "your_app" +version = "x.y.z" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# Async runtime +tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } +# Used for (de)serialising incoming and outgoing messages +serde = "1.0.152" +serde_json = "1.0.91" +# Nym clients, addressing, etc +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" } +nym-sphinx-addressing = { 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" } +# Additional dependencies if you're interacting with Nyx or another Cosmos SDK blockchain +cosmrs = "=0.14.0" +nym-validator-client = { git = "https://github.com/nymtech/nym", branch = "master" } + +# If you're building an app with a client and server / serivce this might be a useful structure for your repo +[[bin]] +name = "client" +path = "bin/client.rs" + +[[bin]] +name = "service" +path = "bin/service.rs" +``` \ No newline at end of file diff --git a/documentation/docs/src/sdk/rust/examples/credential.md b/documentation/docs/src/sdk/rust/examples/credential.md new file mode 100644 index 00000000000..e62cfb454ac --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/credential.md @@ -0,0 +1,9 @@ +# Coconut credential generation +The following code shows how you can use the SDK to create and use a [credential](../../../bandwidth-credentials.md) representing paid bandwidth on the Sandbox testnet. + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} +``` + +You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](../../../coconut.md). + diff --git a/documentation/docs/src/sdk/rust/examples/custom-network.md b/documentation/docs/src/sdk/rust/examples/custom-network.md new file mode 100644 index 00000000000..ae0f145a3bf --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/custom-network.md @@ -0,0 +1,18 @@ +# Importing and using a custom network topology +If you want to send traffic through a sub-set of nodes (for instance, ones you control, or a small test setup) when developing, debugging, or performing research, you will need to import these nodes as a custom network topology, instead of grabbing it from the [`Mainnet Nym-API`](https://validator.nymtech.net/api/swagger/index.html) (`examples/custom_topology_provider.rs`). + +There are two ways to do this: + +## Import a custom Nym API endpoint +If you are also running a Validator and Nym API for your network, you can specify that endpoint as such and interact with it as clients usually do (under the hood): + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/custom_topology_provider.rs}} +``` + +## Import a specific topology manually +If you aren't running a Validator and Nym API, and just want to import a specific sub-set of mix nodes, you can simply overwrite the grabbed topology manually: + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/manually_overwrite_topology.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/keys.md b/documentation/docs/src/sdk/rust/examples/keys.md new file mode 100644 index 00000000000..84746dcfd69 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/keys.md @@ -0,0 +1,28 @@ +# Key Creation and Use +The previous example involves ephemeral keys - if we want to create and then maintain a client identity over time, our code becomes a little more complex as we need to create, store, and conditionally load these keys (`examples/builder_with_storage`): + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/builder_with_storage.rs}} +``` + +As seen in the example above, the `mixnet::MixnetClientBuilder::new()` function handles checking for keys in a storage location, loading them if present, or creating them and storing them if not, making client key management very simple. + +Assuming our client config is stored in `/tmp/mixnet-client`, the following files are generated: +``` +$ tree /tmp/mixnet-client + +mixnet-client +├── ack_key.pem +├── db.sqlite +├── db.sqlite-shm +├── db.sqlite-wal +├── gateway_details.json +├── gateway_shared.pem +├── persistent_reply_store.sqlite +├── private_encryption.pem +├── private_identity.pem +├── public_encryption.pem +└── public_identity.pem + +1 directory, 11 files +``` diff --git a/documentation/docs/src/sdk/rust/examples/simple.md b/documentation/docs/src/sdk/rust/examples/simple.md new file mode 100644 index 00000000000..20872ce96b4 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/simple.md @@ -0,0 +1,8 @@ +# Simple Send +Lets look at a very simple example of how you can import and use the websocket client in a piece of Rust code (`examples/simple.rs`). + +Simply importing the `nym_sdk` crate into your project allows you to create a client and send traffic through the mixnet. + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/simple.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/socks.md b/documentation/docs/src/sdk/rust/examples/socks.md new file mode 100644 index 00000000000..de027e9011d --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/socks.md @@ -0,0 +1,10 @@ +# Socks Proxy +There is also the option to embed the [`socks5-client`](../../../clients/socks5-client.md) into your app code (`examples/socks5.rs`): + +```admonish info +If you are looking at implementing Nym as a transport layer for a crypto wallet or desktop app, this is probably the best place to start if they can speak SOCKS5, 4a, or 4. +``` + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/socks5.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/split-send.md b/documentation/docs/src/sdk/rust/examples/split-send.md new file mode 100644 index 00000000000..6b7cf697899 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/split-send.md @@ -0,0 +1,6 @@ +# Send and Receive in Different Tasks +If you need to split the different actions of your client across different tasks, you can do so like this: + +```rust, noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/storage.md b/documentation/docs/src/sdk/rust/examples/storage.md new file mode 100644 index 00000000000..bc68bca9ffb --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/storage.md @@ -0,0 +1,6 @@ +# Manually Handled Storage +If you're integrating mixnet functionality into an existing app and want to integrate saving client configs and keys into your existing storage logic, you can manually perform the actions taken automatically above (`examples/manually_handle_keys_and_config.rs`) + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/manually_handle_storage.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/examples/surbs.md b/documentation/docs/src/sdk/rust/examples/surbs.md new file mode 100644 index 00000000000..404d74ba1d7 --- /dev/null +++ b/documentation/docs/src/sdk/rust/examples/surbs.md @@ -0,0 +1,16 @@ +# Anonymous Replies with SURBs (Single Use Reply Blocks) +Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. + +The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} +``` + +You can read more about how SURBs function under the hood [here](../../../architecture/traffic-flow.md#private-replies-using-surbs). + +In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: + +```rust,noplayground +{{#include ../../../../../../sdk/rust/nym-sdk/examples/surb-reply.rs}} +``` diff --git a/documentation/docs/src/sdk/rust/message-helpers.md b/documentation/docs/src/sdk/rust/message-helpers.md new file mode 100644 index 00000000000..e7ce201fa73 --- /dev/null +++ b/documentation/docs/src/sdk/rust/message-helpers.md @@ -0,0 +1,70 @@ +# Message Helpers + +## Handling incoming messages +As seen in the [Chain querier tutorial](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/) when listening out for a response to a sent message (e.g. if you have sent a request to a service, and are awaiting the response) you will want to await [non-empty messages (if you don't know why, read the info on this here)](troubleshooting.md#client-receives-empty-messages-when-listening-for-response). This can be done with something like the helper functions [here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/lib.rs#L71): + +```rust +use nym_sdk::mixnet::ReconstructedMessage; + +pub async fn wait_for_non_empty_message( + client: &mut MixnetClient, +) -> anyhow::Result { + while let Some(mut new_message) = client.wait_for_messages().await { + if !new_message.is_empty() { + return Ok(new_message.pop().unwrap()); + } + } + + bail!("did not receive any non-empty message") +} + +pub fn handle_response(message: ReconstructedMessage) -> anyhow::Result { + ResponseTypes::try_deserialize(message.message) +} + +// Note here that the only difference between handling a request and a response +// is that a request will have a sender_tag to parse. +// +// This is used for anonymous replies with SURBs. +pub fn handle_request( + message: ReconstructedMessage, +) -> anyhow::Result<(RequestTypes, Option)> { + let request = RequestTypes::try_deserialize(message.message)?; + Ok((request, message.sender_tag)) +} +``` + +The above helper functions are used as such by the client in tutorial example: it sends a message to the service (what the message is isn't important - just that your client has sent a message _somewhere_ and you are awaiting a response), waits for a _non_empty_ message, then handles it (then logs it - but you can do whatever you want, parse it, etc): + +```rust +// [snip] + +// Send serialised request to service via mixnet what is await-ed here is +// placing the message in the client's message queue, NOT the sending itself. +let _ = client + .send_message(sp_address, message.serialize(), Default::default()) + .await; + +// Await a non-empty message +let received = wait_for_non_empty_message(client).await?; + +// Handle the response received (the non-empty message awaited above) +let sp_response = handle_response(received)?; + +// Match JSON -> ResponseType +let res = match sp_response { + crate::ResponseTypes::Balance(response) => { + println!("{:#?}", response); + response.balance + } +}; + +// [snip] +``` +([repo code on Github here](https://github.com/nymtech/developer-tutorials/blob/0130ee5a61cd6801bdcfc84608b2a520b5392714/rust/chain-query-service/src/client.rs#L19)) + +## Iterating over incoming messages +It is recommended to use `nym_client.next().await` over `nym_client.wait_for_messages().await` as the latter will return one message at a time which will probably be easier to deal with. See the [parallel send and receive example](https://github.com/nymtech/nym/blob/2993e85c7a17bd5b68171751a48b731b2394ee03/sdk/rust/nym-sdk/examples/parallel_sending_and_receiving.rs#L23-L25) for an example. + +## Remember to disconnect your client +You should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage. diff --git a/documentation/docs/src/sdk/rust/message-types.md b/documentation/docs/src/sdk/rust/message-types.md new file mode 100644 index 00000000000..c5adf83377d --- /dev/null +++ b/documentation/docs/src/sdk/rust/message-types.md @@ -0,0 +1,5 @@ +# Message Types +[//]: # (TODO expand! ) +There are two methods for sending messages through the mixnet using your client: +* `send_plain_message()` is the most simple: pass the recipient address and the message you wish to send as a string (this was previously `send_str()`). This is a nicer-to-use wrapper around `send_message()`. +* `send_message()` allows you to also define the amount of SURBs to send along with your message (which is sent as bytes). diff --git a/documentation/docs/src/sdk/rust/rust.md b/documentation/docs/src/sdk/rust/rust.md new file mode 100644 index 00000000000..3062e1ff322 --- /dev/null +++ b/documentation/docs/src/sdk/rust/rust.md @@ -0,0 +1,48 @@ +# Rust SDK +The Rust SDK allows developers building applications in Rust to import and interact with Nym clients as they would any other dependency, instead of running the client as a separate process on their machine. This makes both developing and running applications much easier, reducing complexity in the development process (not having to restart another client in a separate console window/tab) and being able to have a single binary for other people to use. + +Currently developers can use the Rust SDK to import either websocket client ([`nym-client`](../../clients/websocket-client.md)) or [`socks-client`](../../clients/socks5-client.md) functionality into their Rust code. + +In the future the SDK will be made up of several components, each of which will allow developers to interact with different parts of Nym infrastructure. + +| Component | Functionality | Released | +|-----------|---------------------------------------------------------------------------------------|----------| +| Mixnet | Create / load clients & keypairs, subscribe to Mixnet events, send & receive messages | ✔️ | +| Coconut | Create & verify Coconut credentials | 🛠️ | +| Validator | Sign & broadcast Nyx blockchain transactions, query the blockchain | ❌ | + +The `mixnet` component currently exposes the logic of two clients: the [websocket client](../../clients/websocket-client.md), and the [socks](../../clients/socks5-client.md) client. + +The `coconut` component is currently being worked on. Right now it exposes logic allowing for the creation of coconut credentials on the Sandbox testnet. + +### Development status +The SDK is still somewhat a work in progress: interfaces are fairly stable but still may change in subsequent releases. + +### Installation +The `nym-sdk` crate is **not yet available via [crates.io](https://crates.io)**. As such, in order to import the crate you must specify the Nym monorepo in your `Cargo.toml` file: + +```toml +nym-sdk = { git = "https://github.com/nymtech/nym" } +``` + +By default the above command will import the current `HEAD` of the default branch, which in our case is `develop`. Assuming instead you wish to pull in another branch (e.g. `master` or a particular release) you can specify this like so: + +```toml +# importing HEAD of master branch +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "master" } +# importing HEAD of the third release of 2023, codename 'kinder' +nym-sdk = { git = "https://github.com/nymtech/nym", branch = "release/2023.3-kinder" } +``` + +You can also define a particular git commit to use as your import like so: + +```toml +nym-sdk = { git = "https://github.com/nymtech/nym", rev = "85a7ec9f02ca8262d47eebb6c3b19d832341b55d" } +``` + +Since the `HEAD` of `master` is always the most recent release, we recommend developers use that for their imports, unless they have a reason to pull in a specific historic version of the code. + +### Generate Crate Docs +In order to generate the crate docs run `cargo doc --open` from `nym/sdk/rust/nym-sdk/` + + diff --git a/documentation/docs/src/sdk/rust/troubleshooting.md b/documentation/docs/src/sdk/rust/troubleshooting.md new file mode 100644 index 00000000000..458a4eaab4c --- /dev/null +++ b/documentation/docs/src/sdk/rust/troubleshooting.md @@ -0,0 +1,115 @@ +# Troubleshooting +Below are several common issues or questions you may have. + +If you come across something that isn't explained here, [PRs are welcome](https://github.com/nymtech/nym/issues/new/choose). + +## Verbose `task client is being dropped` logging +### On client shutdown (expected) +If this is happening at the end of your code when disconnecting your client, this is fine; we just have a verbose client! When calling `client.disconnect().await` this is simply informing you that the client is shutting down. + +On client shutdown / disconnect this is to be expected - this can be seen in many of the code examples as well. We use the [`nym_bin_common::logging`](https://github.com/nymtech/nym/blob/develop/common/bin-common/src/logging/mod.rs) import to set logging in our example code. This defaults to `INFO` level. + +If you wish to quickly lower the verbosity of your client process logs when developing you can prepend your command with `RUST_LOG=`. + +If you want to run the `builder.rs` example with only `WARN` level logging and below: + +```sh +cargo run --example builder +``` + +Becomes: + +```sh +RUST_LOG=warn cargo run --example builder +``` + +You can also make the logging _more_ verbose with: + +```sh +RUST_LOG=debug cargo run --example builder +``` + +### Not on client shutdown (unexpected) +If this is happening unexpectedly then you might be shutting your client process down too early. See the [accidentally killing your client process](#accidentally-killing-your-client-process-too-early) below for possible explanations and how to fix this issue. + +[//]: # (TODO note on poisson dance and not immediately killing client process) +## Accidentally killing your client process too early +If you are seeing either of the following errors when trying to run a client, specifically sending a message, then you may be accidentally killing your client process. + +```sh + 2023-11-02T10:31:03.930Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-action_controller > the task client is getting dropped + 2023-11-02T10:31:04.625Z INFO TaskClient-BaseNymClient-received_messages_buffer-request_receiver > the task client is getting dropped + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control::acknowledgement_control::input_message_listener > InputMessageListener: Exiting + 2023-11-02T10:31:04.626Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > the task client is getting dropped + 2023-11-02T10:31:04.626Z INFO TaskClient-BaseNymClient-real_traffic_controller-reply_control > the task client is getting dropped + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control > The reply controller has finished execution! + 2023-11-02T10:31:04.626Z DEBUG nym_client_core::client::real_messages_control::acknowledgement_control > The input listener has finished execution! + 2023-11-02T10:31:04.626Z INFO nym_task::manager > All registered tasks succesfully shutdown +``` + +```sh + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-topology_refresher > Assuming this means we should shutdown... + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-mix_traffic_controller > Polling shutdown failed: channel closed + 2023-11-02T11:22:08.408Z INFO TaskClient-BaseNymClient-gateway_transceiver-child > the task client is getting dropped + 2023-11-02T11:22:08.408Z ERROR TaskClient-BaseNymClient-mix_traffic_controller > Assuming this means we should shutdown... +thread 'tokio-runtime-worker' panicked at 'action control task has died: TrySendError { kind: Disconnected }', /home/.local/share/cargo/git/checkouts/nym-fbd2f6ea2e760da9/a800cba/common/client-core/src/client/real_messages_control/message_handler.rs:634:14 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + 2023-11-02T11:22:08.477Z INFO TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > the task client is getting dropped + 2023-11-02T11:22:08.477Z ERROR TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > Polling shutdown failed: channel closed + 2023-11-02T11:22:08.477Z ERROR TaskClient-BaseNymClient-real_traffic_controller-ack_control-input_message_listener > Assuming this means we should shutdown... +``` + +Using the following piece of code as an example: + +```rust +use nym_sdk::mixnet::{MixnetClient, MixnetMessageSender, Recipient}; +use clap::Parser; + +#[derive(Debug, Clone, Parser)] +enum Opts { + Client { + recipient: Recipient + } +} + +#[tokio::main] +async fn main() { + let opts: Opts = Parser::parse(); + nym_bin_common::logging::setup_logging(); + + let mut nym_client = MixnetClient::connect_new().await.expect("Could not build Nym client"); + + match opts { + Opts::Client { recipient } => { + nym_client.send_plain_message(recipient, "some message string").await.expect("send failed"); + } + } +} +``` + +This is a simplified snippet of code for sending a simple hardcoded message with the following command: + +```sh +cargo run client +``` + +You might assume that `send`-ing your message would _just work_ as `nym_client.send_plain_message()` is an async function; you might expect that the client will block until the message is actually sent into the mixnet, then shutdown. + +However, this is not true. + +**This will only block until the message is put into client's internal queue**. Therefore in the above example, the client is being shut down before the message is _actually sent to the mixnet_; after being placed in the client's internal queue, there is still work to be done under the hood, such as route encrypting the message and placing it amongst the stream of cover traffic. + +The simple solution? Make sure the program/client stays active, either by calling `sleep`, or listening out for new messages. As sending a one-shot message without listening out for a response is likely not what you'll be doing, then you will be then awaiting a response (see the [message helpers page](message-helpers.md) for an example of this). + +Furthermore, you should always **manually disconnect your client** with `client.disconnect().await` as seen in the code examples. This is important as your client is writing to a local DB and dealing with SURB storage. + +## Client receives empty messages when listening for response +If you are sending out a message, it makes sense for your client to then listen out for incoming messages; this would probably be the reply you get from the service you've sent a message to. + +You might however be receiving messages without data attached to them / empty payloads. This is most likely because your client is receiving a message containing a [SURB request](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) - a SURB requesting more SURB packets to be sent to the service, in order for them to have enough packets (with a big enough overall payload) to split the entire response to your initial request across. + +Whether the `data` of a SURB request being empty is a feature or a bug is to be decided - there is some discussion surrounding whether we can use SURB requests to send additional data to streamline the process of sending large replies across the mixnet. + +You can find a few helper functions [here](message-helpers.md) to help deal with this issue in the meantime. + +> If you can think of a more succinct or different way of handling this do reach out - we're happy to hear other opinions \ No newline at end of file diff --git a/documentation/operators/src/SUMMARY.md b/documentation/operators/src/SUMMARY.md index 0e2cdb2323e..5d1a7049bbb 100644 --- a/documentation/operators/src/SUMMARY.md +++ b/documentation/operators/src/SUMMARY.md @@ -3,30 +3,33 @@ - [Introduction](introduction.md) # Binaries -- [Pre-built Binaries](./binaries/pre-built-binaries.md) - - [Binary Initialisation and Configuration](./binaries/init-and-config.md) -- [Building from Source](./binaries/building-nym.md) + +- [Pre-built Binaries](binaries/pre-built-binaries.md) + - [Binary Initialisation and Configuration](binaries/init-and-config.md) +- [Building from Source](binaries/building-nym.md) # Operators Guides -- [Mixnet Nodes Setup](./nodes/setup-guides.md) - - [Preliminary Steps](./preliminary-steps.md) - - [Mix Node](./nodes/mix-node-setup.md) - - [Gateway](./nodes/gateway-setup.md) - - [Network Requester](./nodes/network-requester-setup.md) -- [Nyx Validator Setup](./nodes/validator-setup.md) -- [Maintenance](./nodes/maintenance.md) -- [Troubleshooting](./nodes/troubleshooting.md) +- [Mixnet Nodes Setup](nodes/setup-guides.md) + - [Preliminary Steps](preliminary-steps.md) + - [Mix Node](nodes/mix-node-setup.md) + - [Gateway](nodes/gateway-setup.md) + - [Network Requester](nodes/network-requester-setup.md) +- [Nyx Validator Setup](nodes/validator-setup.md) +- [Maintenance](nodes/maintenance.md) +- [Troubleshooting](nodes/troubleshooting.md) # FAQ -- [Mix Nodes](./faq/mixnodes-faq.md) -- [Project Smoosh](./faq/smoosh-faq.md) +- [Mix Nodes](faq/mixnodes-faq.md) +- [Project Smoosh](faq/smoosh-faq.md) # Legal Forum -- [Exit Gateway](./legal/exit-gateway.md) +- [Exit Gateway](legal/exit-gateway.md) + - [Switzerland](legal/swiss.md) + - [United States](legal/united-states.md) --- # Misc. diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index 8bcc071e3ef..5c8705eb60c 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -2,8 +2,8 @@ > We aim on purpose to make minimal changes to reward scheme and software. We're just 'smooshing' together stuff we already debugged and know works. > -- Harry Halpin, Nym CEO -

+
This page refer to the changes which are planned to take place over Q3 and Q4 2023. As this is a transition period in the beginning (Q3 2023) the [Mix Nodes FAQ page](./mixnodes-faq.md) holds more answers to the current setup as project Smoosh refers to the eventual setup. As project Smoosh gets progressively implemented the answers on this page will become to be more relevant to the current state and eventually this FAQ page will be merged with the still relevant parts of the main Mix Nodes FAQ page. If any questions are not answered or it's not clear for you in which stage project Smoosh is right now, please reach out in Node Operators [Matrix room](https://matrix.to/#/#operators:nymtech.chat). @@ -16,51 +16,79 @@ As we shared in our blog post article [*What does it take to build the wolds mos > A nick-name by CTO Dave Hrycyszyn and Chief Scientist Claudia Diaz for the work they are currently doing to “smoosh” Nym nodes so that the same operator can serve alternately as mix node, gateway or VPN node. This requires careful calibration of the Nym token economics, for example, only nodes with the highest reputation for good quality service will be in the VPN set and have the chance to earn higher rewards. > By simplifying the components, adding VPN features and supporting new node operators, the aim is to widen the geographical coverage of nodes and have significant redundancy, meaning plenty of operators to be able to meet demand. This requires strong token economic incentives as well as training and support for new node operators. + ## Technical Questions ### What are the changes? Project smoosh will have three steps: -1. Combine the `gateway` and `network-requester`. -2. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. -3. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Not everyone will be able/want to run an exit `gateway` for example. +1. Combine the `gateway` and `network-requester` into one binary ✅ +2. Create [Exit Gateway](../legal/exit-gateway.md): Take the gateway binary including network requester combined in \#1 and switch from [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) ✅ +3. Combine all the nodes in the Nym Mixnet into one binary, that is `mixnode`, `gateway` (entry and exit) and `network-requester`. These three steps will be staggered over time - period of several months, and will be implemented one by one with enough time to take in feedback and fix bugs in between. Generally, the software will be the same, just instead of multiple binaries, there will be one Nym Mixnet node binary. Delegations will remain on as they are now, per our token economics (staking, saturation etc) +### What does it mean for Nym nodes operators? + +We are exploring two potential methods for implementing binary functionality in practice and will provide information in advance. The options are: + +1. Make a selection button (command/argument/flag) for operators to choose whether they want their node to provide all or just some of the functions nodes have in the Nym Mixnet. Nodes functioning as exit gateways (in that epoch) will then have bigger rewards due to their larger risk exposure and overhead work with the setup. + +2. All nodes will be required to have the exit gateway functionality. All nodes are rewarded the same as now, and the difference is that a node sometimes (some epochs) may be performing as exit gateway sometimes as mix node or entry gateway adjusted according the network demand by an algorithm. + +### Where can I read more about the exit gateway setup? + +We created an [entire page](../legal/exit-gateway.md) about the technical and legal questions around exit gateway. + ### What is the change from allow list to deny list? -The operators running `gateways` would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short allow list to a more permissive setup. An exit policy will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. + +### How will the Exit policy be implemented? + +The progression of exit policy on Gateways will have three steps: + +1. By default the [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) filtering will be disabled and the current [`allowed.list`](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) filtering is going to continue be used. This is to prevent operators getting surprised by upgrading their Gateways (or Network requesters) and suddenly be widely open to the internet. To enable the new exit policy, operators must use `--with-exit-policy` flag or modify the `config.toml` file. ✅ +2. Relatively soon the exit policy will be part of the Gateway setup by default. To disable this exit policy, operators must use `--disable-exit-policy` flag. +3. Further down the line, it will be the only option. Then the `allowed.list` will be completely removed. + +Keep in mind this only relates to changes happening on Gateway and Network Requester side. Whether this will be optional or mandatory depends on the chosen [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators). ### Can I run a mix node only? -Yes, to run a mix node only is an option. However it will be less rewarded as nodes providing option for `gateway` - meaning the *new smooshed gateway* (previously `gateway` and `network requester`) - due to the work and risk the operators have in comparison to running a `mixnode` only. +It depends which [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) will ultimately be used. In case of the first - yes. In case of the second option, all the nodes will be setup with Exit Gateway functionality turned on. ## Token Economics & Rewards +```admonish info +For any specifics on Nym token economics and Nym Mixnet reward system, please read the [Nym token economics paper](https://nymtech.net/nym-cryptoecon-paper.pdf). +``` + ### What are the incentives for the node operator? In the original setup there were no incentives to run a `network-requester`. After the transition all the users will buy multiple tickets of zkNyms credentials and use those as [anonymous e-cash](https://arxiv.org/abs/2303.08221) to pay for their data traffic ([`Nym API`](https://github.com/nymtech/nym/tree/master/nym-api) will do the do cryptographical checks to prevent double-spending). All collected fees get distributed to all active nodes proportionally to their work by the end of each epoch. ### How does this change the token economics? -The token economics will stay the same as they are, same goes for the reward algorithm. In practice the distribution of rewards will benefit more the operators who run open gateways. +The token economics will stay the same as they are, same goes for the reward algorithm. ### How are the rewards distributed? +This depends on [design](./smoosh-faq.md#what-does-it-mean-for-nym-nodes-operators) chosen. In case of \#1, it will look like this: + As each operator can choose what roles their nodes provide, the nodes which work as open gateways will have higher rewards because they are the most important to keep up and stable. Besides that the operators of gateways may be exposed to more complication and possible legal risks. The nodes which are initialized to run as mix nodes and gateways will be chosen to be on top of the active set before the ones working only as a mix node. -We are considering to turn off the rewards for non-open gateways to incentivize operators to run the open ones. Mix nodes on 'standby' will not be rewarded (as they are not being used). - -The more roles an operator will allow their node to provide the bigger reward ratio which will have huge performance benefits for the end-users. +I case we go with \#2, all nodes active in the epoch will be rewarded proportionally according their work. +In either way, Nym will share all the specifics beforehand. ### How will be the staking and inflation after project Smoosh? -We must run tests to see how many users pay. We may need to keep inflation on if not enough people pay to keep high quality gateways on in the early stage of the transition. That would mean keeping staking on for gateways. Staking will always be on for mix nodes. +Nym will run tests to count how much payment comes from the users of the Mixnet and if that covers the reward payments. If not, we may need to keep inflation on to secure incentives for high quality gateways in the early stage of the transition. ### When project smooth will be launched, it would be the mixmining pool that will pay for the gateway rewards based on amount of traffic routed ? diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index e011cc01e39..4cac80d7de7 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -1,4 +1,4 @@ -# Nym operators - Running Exit Gateway +# Nym Operators Legal Forum: Running Exit Gateway ```admonish info The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). @@ -6,8 +6,9 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating gateways and opening these to any online service with the safeguards of the [Tor Null ‘deny’ list](https://tornull.org/). +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +All the technical changes on the side of Nym nodes - ***Project Smoosh** - are described in the [FAQ section](../faq/smoosh-faq.md). ```admonish warning Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.com/invite/nym), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences. @@ -22,7 +23,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list (based on the [Tor Null advisory BL](https://tornull.org/)). +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the [Tor Null 'deny' list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. @@ -39,7 +40,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions To offer a better and more private everyday experience for its users, Nym would like them to use any online services they please, without limiting its access to a few messaging apps or crypto wallets. -To achieve this, operators running “gateways” would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. +To achieve this, operators running exit gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays following this [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). ## Pros and cons of the initiative @@ -54,7 +55,7 @@ Previous setup: Running nodes supporting strict SOCKS5 app-based traffic | Financial | | - Low revenues for operators due to limited product traction | -The new setup: Running nodes supporting traffic of any online service (with safeguards in the form of an denylist) +The new setup: Running nodes supporting traffic of any online service (with safeguards in the form of a denylist) | **Dimension** | **Pros** | **Cons** | | :--- | :--- | :--- | @@ -63,21 +64,17 @@ The new setup: Running nodes supporting traffic of any online service (with safe | Operational | | - Higher operational overhead, such as dealing with DMCA / abuse complaints, managing the VPS provider questions, or helping the community to maintain the denylist
- Administrative overhead if running nodes as a company or an entity | | Legal | | - Ideally requires to check legal environment with local privacy association or lawyer | Financial | - Higher revenue potential for operators due to the increase in network usage | - If not running VPS with an unlimited bandwidth plan, higher costs due to higher network usage | -## New gateway setup +## Exit gateways: New setup In our previous technical setup, network requesters acted as a proxy, and only made requests that match an allow list. That was a default IP based list of allowed domains stored at Nym page in a centralised fashion possibly re-defined by any Network requester operator. This restricts the hosts that the NymConnect app can connect to and has the effect of selectively supporting messaging services (e.g. Telegram, Matrix) or crypto wallets (e.g. Electrum or Monero). Operators of network requesters can have confidence that the infrastructure they run only connects to a limited set of public internet hosts. -In the new setup, the main change is to expand this short allow list to a more permissive setup. An exit policy will constrain the hosts that the users of the Nym Mixnet and Nym VPN can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). +The principal change in the new configuration is to make this short allow list more permissive. Nym's [Exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will restrict the hosts to which Nym Mixnet and Nym VPN users are permitted to connect. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). -As of now we the gateways will be defaulted to Tornull’s (note: Not affiliated with Tor) deny list - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*`. Whether we will stick with this list, do modifications (likely) or compile another one is still a subject of discussion. +As of now we the gateways will be defaulted to a combination of [Tor Null ‘deny’ list](https://tornull.org/) (note: Not affiliated with Tor) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). Whether we will stick with this list, do modifications or compile another one is still a subject of discussion. In all cases, this policy will remain the same for all the nodes, without any option to modify it by Nym node operators to secure stable and reliable service for the end users. -<:-- -These policies will be either reused without modification from Tor / Tornull (license permitting), or customized and updated in a Nym crowd-sourced community effort. ---> - -The Gateways will display an HTML page similar to that suggested by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html) for exit relays on port 80 and port 443. This will allow the operator to provide information about their Gateway, possibly including the currently configured exit policy, without having to actively communicate with law enforcement or regulatory authorities. It also makes the behaviour of the Gateway transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). +For exit relays on ports 80 and 443, the gateways will exhibit an HTML page resembling the one proposed by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html). By doing so, the operator will be able to disclose details regarding their gateway, including the currently configured exit policy, all without the need for direct correspondence with regulatory or law enforcement agencies. It also makes the behaviour of exit gateways transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). We also recommend operators to check the technical advice from [Tor](https://community.torproject.org/relay/setup/exit/). @@ -132,30 +129,14 @@ Useful links: ## Legal environment - Findings from our legal team -```admonish warning -Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the operator channels ([Element](https://matrix.to/#/#operators:nymtech.chat), [Discord](https://discord.com/invite/nym), [Telegram](https://t.me/nymchan_help_chat)) to share best practices and experiences. -``` - -The Swiss legal counsel and US legal counsel have so far provided the following advice: - -### Switzerland - -TBD soon. - -### United States - -A US counsel shared the following advice: - -The legal risk faced by VPN operators subject to United States jurisdiction depends on various statutes and regulations related to privacy, anonymity, and electronic communications. The key areas to consider are: intermediary liability and exceptions, data protection, copyright infringement, export controls, criminal law, government requests for data and assistance, and third party liability. - -As outlined in Part A, the United States treats VPNs as telecommunications networks subject to intermediary liability protection from wrongful conduct that occurs on its network. However, such protections do have exceptions including criminal law and copyright claims that are worth considering. In the United States, I am not aware of an individual ever being prosecuted or convicted for running a node for a dVPN or a Privacy Enhancing Network. - -However, as discussed in Part B-C, VPN operators are subject to law enforcement requests for access or assistance in obtaining access to data relevant to an investigation into allegedly unlawful conduct that was facilitated by the network as an intermediary. As shown in Part C, governments may also request assistance from node operators for certain high-level and national security targets. +The Node Operators Legal Forum pages are divided into pages according the region: -Finally, as outlined in Parts D-G, VPN operators may also be subject to non-criminal liability including (Part D) failing to respond to notices under the DMCA, (Part E) privacy and data protection law, (Part F) third party lawsuits stemming from wrongful acts committed using the network, and (G) export control violations. +- [Switzerland](./swiss.md) +- [United States](./united-states.md) +See the next chapter to learn how to edit information or add findings about your jurisdiction. -## How to add legal information +## How to edit or add legal information Our aim is to establish a strong community network, sharing legal findings with each other. We would like to encourage all the current and future operators to do research about the situation in the jurisdiction they operate and update this page. diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md new file mode 100644 index 00000000000..b879123d85a --- /dev/null +++ b/documentation/operators/src/legal/swiss.md @@ -0,0 +1,77 @@ +# Legal environment: Switzerland + +```admonish info +The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). +``` + +```admonish warning +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +``` + +## Findings from our legal team + +> **Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. + +### Operators of Exit Nodes + +#### Telecoms Law + +As well as operators of normal mixnet nodes, operators of exit nodes might be considered telecommunications providers according to the broad term of the telecommunications act (TCA). +The regulatory consequences have already been laid out in section 5.1.2.2.1 above. + +#### Telecoms Surveillance Law + +Unlike normal mixnet nodes, exit nodes might have information about the communication party which uses the respective exit node (in particular its IP address). They might therefore be a target for surveillance authorities, at least at first glance. + +However, as the IP address of the communications party is disguised on the other side of the communications through the Nym encryption infrastructure, the usual situation, where an IP address or another trace of an Internet user is found in the connection with a criminal activity (e.g., in a web server protocol), and then used in cooperation with the user’s provider to identify the user, is not going to take place. + +The same is true for the opposite side: The node operator does not see the communication party of his user. + +Experience has shown that Swiss investigative authorities are aware of these limitations and do not conduct investigations against individuals who operate TOR nodes, for example. In one specific case that I know of, the investigation was stopped by the police as soon as it was clear that a TOR node was being operated. + +I therefore consider the risk for an exit node operator to become involved in a SPTA proceeding as low. + +Nevertheless, in such a situation, exit node operators providers would have to provide the authorities with the information already available to them (Art. 22 Para. 3 SPTA), and they would have to tolerate monitoring by the authorities or by the persons commissioned by the service of the data which the monitored person transmits or stores using derived communications services (Art. 27 Para. 1 SPTA; see above, 5.1.1.2). There is no duty of data retention for providers of derived communication services, though. + +The the risk for exit node operators of being upgraded according to Art. 22 Para. 4 SPTA is low to non existent for the reasons mentioned above. + +#### Intelligence Service Law + +Operators of exit nodes do not provide wire-based telecommunications services either and therefore do not fall under the IntelSA. + +### Nym as VPN provider + +#### Telecoms Law + +Nym as a VPN operator might be considered a telecommunication provider under the newly revised TCA, as the term now also covers operators of Over-the-Top services which are carried out over the internet. + +However I consider possible administrative burdens arising from this qualification as negligible (see above, 5.1.2.1). + +#### Telecoms Surveillance Law + +VPN providers have information about the communication party which uses the respective exit node (in particular its IP address). They might therefore be a target for surveillance authorities, at least at first glance. + +However, for the same reason I see a risk low for exit node operators to become involved in a SPTA proceeding (the IP address is not visible to the communication partner, which is exactly the reason the Nym VPN is being used at all), I also see a low risk for Nym itself to become involved in such a proceeding (see above, 5.1.3.2). + +#### Intelligence Service Law + +VPN operators do not provide wire-based telecommunications services and therefore do not fall under the IntelSA. + +### EU chat control regulation in particular + +According to a EU commission proposal for a regulation laying down rules to prevent and combat child sexual abuse (https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX: 52022PC0209) hosting providers and providers of so-called interpersonal communication services should be obliged to perform an assessment of risks of online child sexual abuse. Additionally an obligation for certain providers should be established to detect such abuse, to report it via the EU Centre, to remove or disable access to, or to block online child sexual abuse material when so ordered. + +'Interpersonal communications service’ means a service normally provided for remuneration that enables direct interpersonal and interactive exchange of information via electronic communications networks between a finite number of persons, whereby the persons initiating or participating in the communication determine its recipient(s) and does not include services which enable interpersonal and interactive communication merely as a minor ancillary feature that is intrinsically linked to another service (Art. 2 Point 5 Directive (EU) 2018/1972, which is also relevant for the mentioned proposal). + +Interpersonal communications services are services that enable interpersonal and interactive exchange of information. Interactive communication entails that the service allows the recipient of the information to respond. The proposal therefore only covers services like traditional voice calls between two individuals but also all types of emails, messaging services, or group chats. Examples for services which do not meet those requirements are linear broadcasting, video on demand, websites, social networks, blogs, or exchange of information between machines (Directive (EU) 2018/1972, Consideration 17). + +Neither the Nym encryption infrastructure nor the NYM VPN are used as means for an interactive exchange of information in the aforementioned sense (of e-mail, messaging, chats or similar). + +I therefore consider the risk arising from the mentioned proposal for Nym as low, be it as software developer or VPN operator. + +However, an application provider which uses the Nym encryption infrastructure to provide encrypted chat services or similar could still fall under the proposal. This might pose a commercial risk for Nym as the provider of the basic infrastructure for such services, because such services might lose their commercial value for end customers. + +Currently the EU decision on chat control has been postponed because there is a blocking minority which can prevent the adoption of the respective parts of the law. In addition, even EU internal lawyers held that the proposal was clearly in violation of the EU charter of fundamental rights and would therefore be nullified by the EU courts in case it would still be enacted by the parliament. + +I therefore consider the risk that the mentioned proposal is enacted by the EU authorities and finally upheld by the courts in its planned form as low. + diff --git a/documentation/operators/src/legal/united-states.md b/documentation/operators/src/legal/united-states.md new file mode 100644 index 00000000000..ce541b30289 --- /dev/null +++ b/documentation/operators/src/legal/united-states.md @@ -0,0 +1,25 @@ +# Legal environment: United States + +```admonish info +The entire content of this page is under [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/). +``` + +```admonish warning +The following part is for informational purposes only. Nym core team cannot provide comprehensive legal advice across all jurisdictions. Knowledge and experience with the legalities are being built up with the help of our counsel and with you, the community of Nym node operators. We encourage Nym node operators to join the [Node Operator](https://matrix.to/#/#operators:nymtech.chat) and [Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) channels on Element to share best practices and experiences. +``` + +## Findings from our legal team + +> **Note:** The information shared below is in the stage of conclusions upon final confirmation. The text is a not edited exert from a legal counsel. Nym core team is asking for more clarifications. + +The US legal counsel have so far provided the following advice: + +The legal risk faced by VPN operators subject to United States jurisdiction depends on various statutes and regulations related to privacy, anonymity, and electronic communications. The key areas to consider are: intermediary liability and exceptions, data protection, copyright infringement, export controls, criminal law, government requests for data and assistance, and third party liability. + +As outlined in Part A, the United States treats VPNs as telecommunications networks subject to intermediary liability protection from wrongful conduct that occurs on its network. However, such protections do have exceptions including criminal law and copyright claims that are worth considering. In the United States, I am not aware of an individual ever being prosecuted or convicted for running a node for a dVPN or a Privacy Enhancing Network. + +However, as discussed in Part B-C, VPN operators are subject to law enforcement requests for access or assistance in obtaining access to data relevant to an investigation into allegedly unlawful conduct that was facilitated by the network as an intermediary. As shown in Part C, governments may also request assistance from node operators for certain high-level and national security targets. + +Finally, as outlined in Parts D-G, VPN operators may also be subject to non-criminal liability including (Part D) failing to respond to notices under the DMCA, (Part E) privacy and data protection law, (Part F) third party lawsuits stemming from wrongful acts committed using the network, and (G) export control violations. + + diff --git a/documentation/operators/src/nodes/gateway-setup.md b/documentation/operators/src/nodes/gateway-setup.md index 0c95db8b8a3..62ea6dbe65d 100644 --- a/documentation/operators/src/nodes/gateway-setup.md +++ b/documentation/operators/src/nodes/gateway-setup.md @@ -4,8 +4,9 @@ ```admonish info -As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of Nym exit gateway node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateways Page](../legal/exit-gateway.md). We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. +As a result of [Project Smoosh](../faq/smoosh-faq.md), the current version of `nym-gateway` binary also contains `nym-network-requester` functionality which can be enabled [by the operator](./gateway-setup.md#initialising-gateway-with-network-requester). This combination is a basis of ***Nym Exit Gateway*** node - an essential piece in our new setup. Please read more in our [Project Smoosh FAQ](../faq/smoosh-faq.md) and [Exit Gateway](../legal/exit-gateway.md) pages. We recommend operators begin to shift their setups to this new combined node, instead of operating two separate binaries. ``` + > Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version @@ -47,104 +48,128 @@ You can also check the various arguments required for individual commands with: ``` > Adding `--no-banner` startup flag will prevent Nym banner being printed even if run in tty environment. -### Initialising your gateway -To check available configuration options use: +## Initialising your Gateway -``` - ./nym-gateway init --help -``` +As Nym developers build towards [Exit Gateway](../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with in-build Network requester and include the our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. -~~~admonish example collapsible=true title="Console output" +```admonish warning +Before you start an Exit Gateway, read our [Operators Legal Forum](../legal/exit-gateway.md) page and [*Project Smoosh FAQ*](../faq/smoosh-faq.md). ``` - + +```admonish info +There has been an ongoing development with dynamic upgrades. Follow the status of the Project Smoosh [changes](../faq/smoosh-faq.md#what-are-the-changes) and the progression state of Exit policy [implementation](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented) to be up to date with the current design. ``` -~~~ -The following command returns a gateway on your current IP with the `` of `supergateway`: +### Initialising Exit Gateway + +An operator can initialise the Exit Gateway functionality by adding Network requester with the new exit policy option: ``` -./nym-gateway init --id supergateway --host $(curl ifconfig.me) +./nym-gateway init --id --host $(curl -4 https://ifconfig.me) --with-network-requester --with-exit-policy true ``` +If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` and `--with-exit-policy` flags, the outcome will be: + ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ -The `$(curl ifconfig.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. +You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own Exit Gateway. +Additionally -#### Initialising gateway with network requester +#### Add Network requester to an existing Gateway -As some of the [Project Smoosh](../faq/smoosh-faq.md) changes getting implemented, network requester is smooshed with gateways. Such combination creates an exit gateway node, needed for new more open setup. +If you already [upgraded](./maintenance.md#upgrading-your-node) your Gateway to the [latest version](./gateway-setup.md#current-version) and initialised without a Network requester, you can easily change its functionality to Exit Gateway with a command `setup-network-requester`. -An operator can initialise the exit gateway functionality by: +See the options: ``` -./nym-gateway init --id --host $(curl ifconfig.me) --with-network-requester +./nym-gateway setup-network-requester --help ``` -If we follow the previous example with `` chosen `superexitgateway`, adding the `--with-network-requester` flag, the outcome will be: - - ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ -You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own exit gateway. +To setup Exit Gateway functionality with our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) add a flag `--with-exit-policy true`. -#### Add network requester to existing gateway +``` +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id +``` -If you already run a gateway and got it [upgraded](./maintenance.md#upgrading-your-node) to the [newest version](./gateway-setup.md#current-version), you can easily change its functionality to exit gateway. PAuse the gateway and run a command `setup-network-requester`. +Say we have a gateway with `` as `new-gateway`, originally initialised and ran without the Exit Gateway functionality. To change the setup, run: -See the options: ``` -./nym-gateway setup-network-requester --help +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id new-gateway ``` ~~~admonish example collapsible=true title="Console output" ``` - + + ``` ~~~ -Run with `--enabled true` flag choosing `` as `supergateway`: +In case there are any unexpected problems, you can also change it manually by editing the Gateway config file stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. ``` -./nym-gateway setup-network-requester --enabled true --id supergateway +[network_requester] +# Specifies whether network requester service is enabled in this process. +enabled = true +``` + +Save, exit and restart your gateway. Now you are an operator of post-smooshed Exit gateway. + +All information about network requester part of your exit gateway is in `/home/user/.nym/gateways//config/network_requester_config.toml`. + +For now you can run Gateway without Network requester or with and without the new exit policy. This will soon change as we inform in our [Project Smoosh FAQ](../faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented). + +To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). + + +#### Initialising Gateway without Network requester + +In case you don't want to run your Gateway with the Exit Gateway functionality, you still can run a simple Gateway. + +To check available configuration options use: + +``` + ./nym-gateway init --help ``` ~~~admonish example collapsible=true title="Console output" ``` - + ``` ~~~ -In case there are any problems, you can also change it manually by editing the gateway config stored in `/home/user/.nym/gateways//config/config.toml` where the line under `[network_requester]` needs to be edited from `false` to `true`. +The following command returns a gateway on your current IP with the `` of `simple-gateway`: ``` -[network_requester] -# Specifies whether network requester service is enabled in this process. -enabled = true +./nym-gateway init --id simple-gateway --host $(curl -4 https://ifconfig.me) ``` -Save, exit and restart your gateway. Now it is a post-smooshed exit gateway. +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ -All information about network requester part of your exit gateway is in `/home/user/.nym/gateways/snus/config/network_requester_config.toml`. +The `$(curl -4 https://ifconfig.me)` command above returns your IP automatically using an external service. Alternatively, you can enter your IP manually if you wish. If you do this, remember to enter your IP **without** any port information. -To read more about the configuration like whitelisted outbound requesters in `allowed.list` and other useful information, see the page [*Network Requester Whitelist*](network-requester-setup.md#using-your-network-requester). +### Bonding your gateway ```admonish info -Before you bond and run your gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. +Before you bond and re-run your Gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your gateway can be reached from the outside. You can also setup WSS on your Gateway, the steps are on the [Maintenance page](./maintenance.md#configure-your-firewall) below. ``` -### Bonding your gateway - #### Via the Desktop wallet You can bond your gateway via the Desktop wallet. @@ -156,7 +181,7 @@ You can bond your gateway via the Desktop wallet. 3. You will be asked to run a the `sign` command with your `gateway` - copy and paste the long signature as the value of `--contract-msg` and run it. ``` -./nym-gatewway sign --id --contract-msg +./nym-gateway sign --id --contract-msg ``` It will look something like this: @@ -172,7 +197,7 @@ It will look something like this: |_| |_|\__, |_| |_| |_| |___/ - (nym-gateway - version v1.1.29) + (nym-gateway - version v1.1.31) >>> attempting to sign 2Mf8xYytgEeyJke9LA7TjhHoGQWNBEfgHZtTyy2krFJfGHSiqy7FLgTnauSkQepCZTqKN5Yfi34JQCuog9k6FGA2EjsdpNGAWHZiuUGDipyJ6UksNKRxnFKhYW7ri4MRduyZwbR98y5fQMLAwHne1Tjm9cXYCn8McfigNt77WAYwBk5bRRKmC34BJMmWcAxphcLES2v9RdSR68tkHSpy2C8STfdmAQs3tZg8bJS5Qa8pQdqx14TnfQAPLk3QYCynfUJvgcQTrg29aqCasceGRpKdQ3Tbn81MLXAGAs7JLBbiMEAhCezAr2kEN8kET1q54zXtKz6znTPgeTZoSbP8rzf4k2JKHZYWrHYF9JriXepuZTnyxAKAxvGFPBk8Z6KAQi33NRQkwd7MPyttatHna6kG9x7knffV6ebGzgRBf7NV27LurH8x4L1uUXwm1v1UYCA1WSBQ9Pp2JW69k5v5v7G9gBy8RUcZnMbeL26Qqb8WkuGcmuHhaFfoqSfV7PRHPpPT4M8uRqUyR4bjUtSJJM1yh6QSeZk9BEazzoJqPeYeGoiFDZ3LMj2jesbJweQR4caaYuRczK92UGSSqu9zBKmE45a @@ -194,7 +219,7 @@ It will look something like this: * Your gateway is now bonded. -> You are asked to `sign` a transaction on bonding so that the mixnet smart contract is able to map your nym address to your node. This allows us to create a nonce for each account and defend against replay attacks. +> You are asked to `sign` a transaction on bonding so that the Mixnet smart contract is able to map your Nym address to your node. This allows us to create a nonce for each account and defend against replay attacks. #### Via the CLI (power users) If you want to bond your mix node via the CLI, then check out the [relevant section in the Nym CLI](https://nymtech.net/docs/tools/nym-cli.html#bond-a-mix-node) docs. diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 03bb33a0f3d..5a08724d618 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -103,36 +103,120 @@ Running the command `df -H` will return the size of the various partitions of yo If the `/dev/sda` partition is almost full, try pruning some of the `.gz` syslog archives and restart your validator process. -## Moving a node -In case of a need to move a node from one machine to another and avoiding to lose the delegation, here are few steps how to do it. +## Run Web Secure Socket (WSS) on Gateway -The following examples transfers a mix node (in case of other nodes, change the `mixnodes` in the command for the `` of your desire. +Now you can run WSS on your Gateway. -* Pause your node process. +### WSS on an existing Gateway -Assuming both machines are remote VPS. +In case you already run a working Gateway and want to add WSS on it, here are the pre-requisites to running WSS on Gateways: -* Make sure your `~/.ssh/.pub` is in both of the machines `~/.ssh/authorized_keys` file -* Create a `mixnodes` folder in the target VPS. Ssh in from your terminal and run: +* You need to use the latest `nym-gateway` binary [version](./gateway-setup.md#current-version) and restart it. +* That will add the relevant fields to update your config. +* These two values will be added and need to be amended in your config.toml: ```sh -# in case none of the nym configs was created previously -mkdir ~/.nym +clients_wss_port = 0 +hostname = "" +``` -#in case no nym mix node was initialized previously -mkdir ~/.nym/mixnodes +Then you can run this: + +```sh +port=$1 // in the example below we will use 9001 +host=$2 = // this would be a domain name registered for your Gateway for example: mainnet-gateway2.nymtech.net + + +sed -i "s/clients_wss_port = 0/clients_wss_port = ${port}/" ${HOME}/.nym/gateways/*/config/config.toml +sed -i "s|hostname = ''|hostname = '${host}'|" ${HOME}/.nym/gateways/*/config/config.toml ``` -* Move the node data (keys) and config file to the new machine by opening a local terminal (as that one's ssh key is authorized in both of the machines) and running: +The following shell script can be run: + ```sh -scp -r -3 @:~/.nym/mixnodes/ @:~/.nym/mixnodes/ +#!/bin/bash + +if [ "$#" -ne 2 ]; then + echo "Usage: sudo ./install_run_caddy.sh " + exit 1 +fi + +host=$1 +port_value=$2 + +apt install -y debian-keyring debian-archive-keyring apt-transport-https +apt --fix-broken install + +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg + +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list + +apt update +apt install caddy + +systemctl enable caddy.service + +cd /etc/caddy + +# check if Caddyfile exists, if it does, remove and insert a new one +if [ -f Caddyfile ]; then + echo "removing caddyfile inserting a new one" + rm -f Caddyfile +fi + +cat <> Caddyfile +${host}:${port_value} { + @websockets { + header Connection *Upgrade* + header Upgrade websocket + } + reverse_proxy @websockets localhost:9000 +} +EOF + +cat Caddyfile + +echo "script completed successfully!" + +systemctl restart caddy.service +echo "have a nice day!" +exit 0 + ``` -* Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc. -* Change the node smart contract info via the wallet interface. Otherwise the keys will point to the old IP address in the smart contract, and the node will not be able to be connected, and it will fail up-time checks. -* Re-run the node from the new location. -## VPS Setup and Automation -### Configure your firewall +Although your gateway is Now ready to use its `wss_port`, your server may not be ready - the following commands will allow you to set up a properly configured firewall using `ufw`: + +```sh +ufw allow 9001/tcp +``` + +Lastly don't forget to restart your Gateway, now the API will render the WSS details for this gateway: + + +### WSS on a new Gateway + +These steps are for an operator who is setting up a Gateway for the first time and wants to run it with WSS. + +New flags will need to be added to the `init` and `run` command. The `--host` option is still accepted for now, but can and should be replaced with `--listening-address`, this is the IP address which is used for receiving sphinx packets and listening to client data. + +Another flag `--public-ips` is required; it's a comma separated list of IP’s that are announced to the `nym-api`, it is usually the address which is used for bonding. + +If the operator wishes to run WSS, an optional `--hostname` flag is also required, that can be something like `mainnet-gateway2.nymtech.net`. Make sure to enable all necessary [ports](maintenance.md#configure-your-firewall) on the Gateway. + +The gateway will then be accessible on something like: *http://85.159.211.99:8080/api/v1/swagger/index.html* + +Are you seeing something like: *this node attempted to announce an invalid public address: 0.0.0.0.*? + +Please modify `[host.public_ips]` section of your config file stored as `~/.nym/gateways//config/config.toml`. + +If so the flags are going to be slightly different: + +``` +--listening-address "0.0.0.0" --public-ips "$(curl -4 https://ifconfig.me)" +``` + +## Configure your firewall + Although your `` is now ready to receive traffic, your server may not be. The following commands will allow you to set up a firewall using `ufw`. ```sh @@ -153,7 +237,10 @@ Finally open your `` p2p port, as well as ports for ssh and ports for verl ```sh # for mix node, gateway and network requester -sudo ufw allow 1789,1790,8000,9000,22/tcp +sudo ufw allow 1789,1790,8000,9000,9001,22/tcp + +# In case of reverse proxy for the Gateway swagger page add: +sudo ufw allow 8080,80/443 # for validator sudo ufw allow 1317,26656,26660,22,80,443/tcp @@ -166,6 +253,8 @@ sudo ufw status For more information about your node's port configuration, check the [port reference table](./maintenance.md#gateway-port-reference) below. +## VPS Setup and Automation + ### Automating your node with nohup, tmux and systemd Although it’s not totally necessary, it's useful to have the mix node automatically start at system boot time. @@ -398,7 +487,7 @@ Failed to accept incoming connection - Os { code: 24, kind: Other, message: "Too This means that the operating system is preventing network connections from being made. -#### Set the ulimit via `systemd` service file +#### Set the `ulimit` via `systemd` service file > Replace `` variable with `nym-mixnode`, `nym-gateway` or `nym-network-requester` according the node you running on your machine. @@ -481,6 +570,35 @@ username soft nofile 4096 Then reboot your server and restart your mix node. +## Moving a node + +In case of a need to move a node from one machine to another and avoiding to lose the delegation, here are few steps how to do it. + +The following examples transfers a mix node (in case of other nodes, change the `mixnodes` in the command for the `` of your desire. + +* Pause your node process. + +Assuming both machines are remote VPS. + +* Make sure your `~/.ssh/.pub` is in both of the machines `~/.ssh/authorized_keys` file +* Create a `mixnodes` folder in the target VPS. Ssh in from your terminal and run: + +```sh +# in case none of the nym configs was created previously +mkdir ~/.nym + +#in case no nym mix node was initialized previously +mkdir ~/.nym/mixnodes +``` +* Move the node data (keys) and config file to the new machine by opening a local terminal (as that one's ssh key is authorized in both of the machines) and running: +```sh +scp -r -3 @:~/.nym/mixnodes/ @:~/.nym/mixnodes/ +``` +* Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc. +* Change the node smart contract info via the wallet interface. Otherwise the keys will point to the old IP address in the smart contract, and the node will not be able to be connected, and it will fail up-time checks. +* Re-run the node from the new location. + + ## Virtual IPs and hosting via Google & AWS For true internet decentralization we encourage operators to use diverse VPS providers instead of the largest companies offering such services. If for some reasons you have already running AWS or Google and want to setup a `` there, please read the following. @@ -680,6 +798,7 @@ All ``-specific port configuration can be found in `$HOME/.nym// Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets. ## Current version diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 16c55da6c55..aadfc916d7b 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.30" +version = "1.1.31" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index ed502528b16..3ee6a136436 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "1.1.30" +version = "1.1.31" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs index f4ef8640e9d..23ebd77afdd 100644 --- a/gateway/src/commands/helpers.rs +++ b/gateway/src/commands/helpers.rs @@ -302,6 +302,7 @@ pub(crate) async fn initialise_local_network_requester( enabled: gateway_config.network_requester.enabled, identity_key: address.identity().to_string(), encryption_key: address.encryption_key().to_string(), + exit_policy: !nr_cfg.network_requester.use_deprecated_allow_list, open_proxy: nr_cfg.network_requester.open_proxy, enabled_statistics: nr_cfg.network_requester.enabled_statistics, address: address.to_string(), diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 9f00e66b457..4ae56f813c3 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::node::storage::error::StorageError; -use nym_ip_packet_router::error::IpForwarderError; +use nym_ip_packet_router::error::IpPacketRouterError; use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; @@ -110,7 +110,7 @@ pub(crate) enum GatewayError { #[error("there was an issue with the local ip packet router: {source}")] IpPacketRouterFailure { #[from] - source: IpForwarderError, + source: IpPacketRouterError, }, #[error("failed to startup local network requester")] diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs index 0b8fc9c9949..d3cf2fdae49 100644 --- a/gateway/src/node/helpers.rs +++ b/gateway/src/node/helpers.rs @@ -60,6 +60,7 @@ pub(crate) fn node_details(config: &Config) -> Result Gateway { // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. let (on_start_tx, on_start_rx) = oneshot::channel(); - let mut ip_builder = nym_ip_packet_router::IpForwarderBuilder::new(ip_opts.config.clone()) - .with_shutdown(shutdown) - .with_custom_gateway_transceiver(Box::new(transceiver)) - .with_wait_for_gateway(true) - .with_on_start(on_start_tx); + let mut ip_builder = + nym_ip_packet_router::IpPacketRouterBuilder::new(ip_opts.config.clone()) + .with_shutdown(shutdown) + .with_custom_gateway_transceiver(Box::new(transceiver)) + .with_wait_for_gateway(true) + .with_on_start(on_start_tx); if let Some(custom_mixnet) = &ip_opts.custom_mixnet_path { ip_builder = ip_builder.with_stored_topology(custom_mixnet)? diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 751aa06e042..2c8636f94b7 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "1.1.31" +version = "1.1.32" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 85c20d6e592..47ea4d056df 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.31" +version = "1.1.32" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index 86ee9de5f99..aee9afb118c 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extension-storage" -version = "1.2.0" +version = "1.2.1" edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index e14caee0279..1d29030497a 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +## [v1.2.10] (2023-10-31) + +- Add loading model on initial load of delegations ([#4039]) +- remove any whitespace from input field when bonding host ([#4062]) + +[#4039]: https://github.com/nymtech/nym/pull/4039 +[#4062]: https://github.com/nymtech/nym/pull/4062 + ## [v1.2.9] (2023-10-10) - Wallet: Introduce edit account name ([#3895]) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index ec32ea6a33b..77fbfe47ebf 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3706,7 +3706,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.2.9" +version = "1.2.10" dependencies = [ "async-trait", "base64 0.13.1", diff --git a/nym-wallet/package.json b/nym-wallet/package.json index c930554e2b0..93b1793711e 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-wallet-app", - "version": "1.2.9", + "version": "1.2.10", "main": "index.js", "license": "MIT", "scripts": { @@ -124,4 +124,4 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" } -} +} \ No newline at end of file diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 24c79219b75..eaced888a4f 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym_wallet" -version = "1.2.9" +version = "1.2.10" description = "Nym Native Wallet" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 9b87728fd43..43330b25871 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-wallet", - "version": "1.2.9" + "version": "1.2.10" }, "build": { "distDir": "../dist", diff --git a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx index 04b50f37851..620a21ae8ad 100644 --- a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx @@ -21,7 +21,8 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle } /> - If you don’t have a password set for your account, go to the Settings, under Security tab create a password + If you don’t have a password set for your account, log out, click on login with password and follow the forgot + my password flow If you already have a password, log in to the wallet using your password then try create/import accounts diff --git a/package.json b/package.json index cd357e15a02..bd928a454ef 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,11 @@ "sdk/typescript/packages/validator-client", "sdk/typescript/packages/mix-fetch-node", "sdk/typescript/packages/nodejs-client", + "sdk/typescript/packages/node-tester", + "sdk/typescript/packages/sdk-react", + "sdk/typescript/packages/mix-fetch", + "sdk/typescript/packages/sdk", + "sdk/typescript/codegen/contract-clients", "ts-packages/*", "nym-wallet", "nym-connect/**", @@ -36,7 +41,7 @@ "prebuild:ci": "yarn dev:on && yarn", "build:ci": "run-s build:types build:packages build:wasm build:ci:sdk", "postbuild:ci": "yarn dev:off", - "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream", + "build:ci:sdk": "lerna run --scope '{@nymproject/sdk,@nymproject/node-tester,@nymproject/contract-clients,@nymproject/sdk-react,@nymproject/mix-fetch,@nymproject/nodejs-client,@nymproject/mix-fetch-node}' build --stream", "docs:prod:build": "run-s docs:prod:build:ws", "docs:prod:build:ws": "lerna run docs:prod:build --stream", "sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh", diff --git a/sdk/typescript/codegen/contract-clients/package.json b/sdk/typescript/codegen/contract-clients/package.json index 856942d6219..49e3d1fc998 100644 --- a/sdk/typescript/codegen/contract-clients/package.json +++ b/sdk/typescript/codegen/contract-clients/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/contract-clients", - "version": "1.2.0", + "version": "1.2.1", "description": "A client for all Nym smart contracts", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -27,4 +27,4 @@ }, "private": false, "types": "./dist/index.d.ts" -} \ No newline at end of file +} diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.client.ts b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts index 5f5444f0fc4..a92b351fb1f 100644 --- a/sdk/typescript/codegen/contract-clients/src/NameService.client.ts +++ b/sdk/typescript/codegen/contract-clients/src/NameService.client.ts @@ -6,8 +6,8 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Address, NymName, MessageSignature, NameDetails, QueryMsg, MigrateMsg, Addr, PagedNamesListResponse, RegisteredName, NamesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./NameService.types"; import { GetCw2ContractVersionResponse } from './types'; +import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Address, NymName, MessageSignature, NameDetails, NymAddressInner, QueryMsg, MigrateMsg, Addr, PagedNamesListResponse, RegisteredName, NamesListResponse, ConfigResponse, ContractVersion, ContractBuildInformation, Uint32 } from "./NameService.types"; export interface NameServiceReadOnlyInterface { contractAddress: string; nameId: ({ diff --git a/sdk/typescript/codegen/contract-clients/src/NameService.types.ts b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts index c9d80b59361..e80cdfc8439 100644 --- a/sdk/typescript/codegen/contract-clients/src/NameService.types.ts +++ b/sdk/typescript/codegen/contract-clients/src/NameService.types.ts @@ -32,7 +32,7 @@ export type ExecuteMsg = { }; }; export type Address = { - nym_address: string; + nym_address: NymAddressInner; }; export type NymName = string; export type MessageSignature = number[]; @@ -41,6 +41,11 @@ export interface NameDetails { identity_key: string; name: NymName; } +export interface NymAddressInner { + client_enc: string; + client_id: string; + gateway_id: string; +} export type QueryMsg = { name_id: { name_id: number; diff --git a/sdk/typescript/docs/package.json b/sdk/typescript/docs/package.json index 0fcfab0d3da..580a99614e5 100644 --- a/sdk/typescript/docs/package.json +++ b/sdk/typescript/docs/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/ts-sdk-docs", - "version": "1.2.0", + "version": "1.2.1", "description": "Nym Typescript SDK Docs", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,10 +28,10 @@ "@mui/icons-material": "^5.14.9", "@mui/lab": "^5.0.0-alpha.145", "@mui/material": "^5.14.8", - "@nymproject/contract-clients": ">=1.2.0-rc.10 || ^1", - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1", - "@nymproject/mix-fetch-full-fat": ">=1.2.0-rc.10 || ^1", - "@nymproject/sdk-full-fat": ">=1.2.0-rc.10 || ^1", + "@nymproject/contract-clients": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", + "@nymproject/mix-fetch-full-fat": ">=1.2.1-rc.0 || ^1", + "@nymproject/sdk-full-fat": ">=1.2.1-rc.0 || ^1", "chain-registry": "^1.19.0", "cosmjs-types": "^0.8.0", "next": "^13.4.19", @@ -51,4 +51,4 @@ "typescript": "^4.9.3" }, "private": false -} +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/parcel/package.json b/sdk/typescript/examples/chat-app/parcel/package.json index bf72e13983b..646d5610fe2 100644 --- a/sdk/typescript/examples/chat-app/parcel/package.json +++ b/sdk/typescript/examples/chat-app/parcel/package.json @@ -1,12 +1,21 @@ { "name": "@nymproject/sdk-example-plain-html-parcel", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", - "version": "1.0.0", "license": "Apache-2.0", - "source": "src/index.html", - "browserslist": "> 0.5%, last 2 versions, not dead", + "scripts": { + "build": "npx parcel build", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "npx parcel", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", @@ -29,15 +38,7 @@ "ts-jest": "^27.0.5", "typescript": "^4.6.2" }, - "scripts": { - "start": "npx parcel", - "build": "npx parcel build", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false, + "browserslist": "> 0.5%, last 2 versions, not dead", + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/plain-html/package.json b/sdk/typescript/examples/chat-app/plain-html/package.json index 5e6774c951f..7cdf5deddcb 100644 --- a/sdk/typescript/examples/chat-app/plain-html/package.json +++ b/sdk/typescript/examples/chat-app/plain-html/package.json @@ -1,10 +1,22 @@ { "name": "@nymproject/sdk-example-plain-html", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -49,16 +61,5 @@ "webpack-dev-server": "^4.5.0", "webpack-merge": "^5.8.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json index 47fedbf21de..48813124ddc 100644 --- a/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json +++ b/sdk/typescript/examples/chat-app/react-webpack-with-theme-example/package.json @@ -1,15 +1,26 @@ { "name": "@nymproject/sdk-example-react-webpack-wasm", + "version": "1.0.1", "description": "An example project that uses WASM, React, Webpack, Typescript and the Nym theme + components library", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { "@mui/icons-material": "^5.5.0", "@mui/lab": "^5.0.0-alpha.72", "@mui/material": "^5.0.1", "@mui/styles": "^5.0.1", - "react-mui-dropzone": "^4.0.6", - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1", + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", @@ -72,22 +83,11 @@ "webpack-favicons": "^1.3.8", "webpack-merge": "^5.8.0" }, + "private": false, "overrides": { - "react": "^18.2.0", - "react-dom": "^18.2.0", "@types/react": "^18.0.26", - "@types/react-dom": "^18.0.10" - }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" + "@types/react-dom": "^18.0.10", + "react": "^18.2.0", + "react-dom": "^18.2.0" } -} +} \ No newline at end of file diff --git a/sdk/typescript/examples/chrome-extension/package.json b/sdk/typescript/examples/chrome-extension/package.json index 507b9cdec87..5880b8d4e81 100644 --- a/sdk/typescript/examples/chrome-extension/package.json +++ b/sdk/typescript/examples/chrome-extension/package.json @@ -1,20 +1,21 @@ { "name": "@nymproject/sdk-example-chrome-extension", - "version": "1.0.0", + "version": "1.0.1", "description": "This is an example of how Nym can be used within the context of a Chrome extension.", + "license": "ISC", + "author": "", "main": "index.js", "scripts": { "build": "webpack" }, - "author": "", - "license": "ISC", + "dependencies": { + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + }, "devDependencies": { "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^11.0.0", "webpack": "^5.88.1", "webpack-cli": "^5.1.4" }, - "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/firefox-extension/package.json b/sdk/typescript/examples/firefox-extension/package.json index 1d14e425a53..9615a1cf04c 100644 --- a/sdk/typescript/examples/firefox-extension/package.json +++ b/sdk/typescript/examples/firefox-extension/package.json @@ -1,20 +1,21 @@ { "name": "@nymproject/sdk-example-firefox-extension", - "version": "1.0.0", + "version": "1.0.1", "description": "This is an example of how Nym can be used within the context of a Firefox extension.", - "main": "index.js", - "author": "", "license": "ISC", + "author": "", + "main": "index.js", + "scripts": { + "build": "yarn webpack" + }, + "dependencies": { + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" + }, "devDependencies": { "copy-webpack-plugin": "^11.0.0", "webpack": "^5.88.1", "webpack-cli": "^5.1.4", "worker-loader": "^3.0.8" }, - "scripts": { - "build": "yarn webpack" - }, - "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/mix-fetch/browser/package.json b/sdk/typescript/examples/mix-fetch/browser/package.json index 1ec0e2d6c69..4de1922b388 100644 --- a/sdk/typescript/examples/mix-fetch/browser/package.json +++ b/sdk/typescript/examples/mix-fetch/browser/package.json @@ -1,15 +1,16 @@ { "name": "@nymproject/mix-fetch-example-parcel", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", - "source": "src/index.html", - "dependencies": { - "parcel": "^2.9.3", - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" - }, "scripts": { - "start": "parcel --no-cache", "build": "parcel build --no-cache --no-content-hash", - "serve": "serve dist" - } -} + "serve": "serve dist", + "start": "parcel --no-cache" + }, + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1", + "parcel": "^2.9.3" + }, + "private": false, + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/parcel/package.json b/sdk/typescript/examples/node-tester/parcel/package.json index 905b3747eb4..015b816fda4 100644 --- a/sdk/typescript/examples/node-tester/parcel/package.json +++ b/sdk/typescript/examples/node-tester/parcel/package.json @@ -1,12 +1,21 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html-parcel", + "version": "1.0.1", "description": "An example project that uses WASM and plain HTML bundled with Parcel v2", - "version": "1.0.0", "license": "Apache-2.0", - "source": "src/index.html", - "browserslist": "> 0.5%, last 2 versions, not dead", + "scripts": { + "build": "npx parcel build", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "npx parcel", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@types/jest": "^27.0.1", @@ -29,15 +38,7 @@ "ts-jest": "^27.0.5", "typescript": "^4.6.2" }, - "scripts": { - "start": "npx parcel", - "build": "npx parcel build", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false, + "browserslist": "> 0.5%, last 2 versions, not dead", + "source": "src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/plain-html/package.json b/sdk/typescript/examples/node-tester/plain-html/package.json index 225060d8137..bf59e74f0da 100644 --- a/sdk/typescript/examples/node-tester/plain-html/package.json +++ b/sdk/typescript/examples/node-tester/plain-html/package.json @@ -1,10 +1,22 @@ { "name": "@nymproject/sdk-example-node-tester-plain-html", + "version": "1.0.1", "description": "An example project that uses WASM node tester and plain HTML", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "build:dev": "webpack build --progress", + "build:serve": "npx serve dist", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "webpack serve --progress --port 3000", + "test": "jest", + "test:watch": "jest --watch", + "tsc": "tsc", + "tsc:watch": "tsc --watch" + }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.15.0", @@ -49,16 +61,5 @@ "webpack-dev-server": "^4.5.0", "webpack-merge": "^5.8.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "build:dev": "webpack build --progress", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc", - "tsc:watch": "tsc --watch", - "lint": "eslint src", - "lint:fix": "eslint src --fix" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/examples/node-tester/react/package.json b/sdk/typescript/examples/node-tester/react/package.json index e07e69ad32d..9f3b2394e7c 100644 --- a/sdk/typescript/examples/node-tester/react/package.json +++ b/sdk/typescript/examples/node-tester/react/package.json @@ -1,19 +1,20 @@ { "name": "@nymproject/sdk-example-node-tester-react", + "version": "1.0.1", "description": "An example project that uses WASM node tester and React", - "version": "1.0.0", "license": "Apache-2.0", + "scripts": { + "start": "parcel index.html" + }, "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.14.0", "@mui/material": "^5.14.0", - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1", + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1", "parcel": "^2.9.3", "react": "^18.2.0", "react-dom": "^18.2.0" }, - "scripts": { - "start": "parcel index.html" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch-node/internal/index.js b/sdk/typescript/packages/mix-fetch-node/internal/index.js new file mode 100644 index 00000000000..5804f8c6317 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch-node/internal/index.js @@ -0,0 +1,54 @@ +const { createMixFetch, disconnectMixFetch } = require('../dist/cjs/index.js'); + +/** + * The main entry point + */ +(async () => { + console.log('Tester is starting up...'); + + const addr = + 'D274yd1h3L3pNJzdxE5VgJ7izAsAVMsDrQtFSkKUegfk.8J67cGbcwvrJKF3Kb16HVWWc9AnrFnEibNCm9zCkuVFu@Emswx6KXyjRfq1c2k4d4uD2e6nBSbH1biorCZUei8UNS'; + + console.log('About to set up mixFetch...'); + const { mixFetch } = await createMixFetch({ + preferredNetworkRequester: addr, + clientId: 'node-client1', + clientOverride: { + coverTraffic: { disableLoopCoverTrafficStream: true }, + traffic: { disableMainPoissonPacketDistribution: true }, + }, + mixFetchOverride: { requestTimeoutMs: 60000 }, + responseBodyConfigMap: {}, + extra: {}, + }); + + globalThis.mixFetch = mixFetch; + + if (!globalThis.mixFetch) { + console.error('Oh no! Could not create mixFetch'); + } else { + console.log('Ready!'); + } + + let url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + console.log(`Using mixFetch to get ${url}...`); + const args = { mode: 'unsafe-ignore-cors' }; + + let resp = await mixFetch(url, args); + console.log({ resp }); + const text = await resp.text(); + + console.log('disconnecting'); + await disconnectMixFetch(); + console.log('disconnected! all further usages should fail'); + + // get an image + url = 'https://nymtech.net/favicon.svg'; + resp = await mixFetch(url, args); + console.log({ resp }); + const buffer = await resp.arrayBuffer(); + const type = resp.headers.get('Content-Type') || 'image/svg'; + const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + console.log(JSON.stringify({ bufferBytes: buffer.byteLength, blobUrl }, null, 2)); + console.log(blobUrl); +})(); diff --git a/sdk/typescript/packages/mix-fetch-node/package.json b/sdk/typescript/packages/mix-fetch-node/package.json index 2df56711def..3efd987e43b 100644 --- a/sdk/typescript/packages/mix-fetch-node/package.json +++ b/sdk/typescript/packages/mix-fetch-node/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch-node", - "version": "1.2.1-rc.2", + "version": "1.2.1", "description": "This package is a drop-in replacement for `fetch` in NodeJS to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -28,7 +28,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm-node": ">=1.2.0 || ^1", + "@nymproject/mix-fetch-wasm-node": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^5.0.0", "node-fetch": "^3.3.2", diff --git a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs index bc10b36ad16..a4712235211 100644 --- a/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs +++ b/sdk/typescript/packages/mix-fetch-node/rollup-worker.config.mjs @@ -11,7 +11,7 @@ export default { dir: 'dist/cjs', format: 'cjs', }, - onwarn, + external: ['util', 'fake-indexeddb'], plugins: [ resolve({ browser: false, @@ -19,10 +19,18 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 modify({ find: 'getObject(arg0).require(getStringFromWasm0(arg1, arg2));', replace: 'require("crypto");' }), + modify({ + find: 'getObject(arg0).getRandomValues(getObject(arg1));', + replace: 'require("crypto").getRandomValues(getObject(arg1));', + }), wasm({ targetEnv: 'node', maxFileSize: 0, fileName: '[name].wasm' }), typescript({ compilerOptions: { @@ -33,11 +41,3 @@ export default { }), ], }; - -function onwarn(warning) { - // fake-indexeddb has a circular dependency that triggers a warning when rolled up - if (warning.code !== 'CIRCULAR_DEPENDENCY') { - // eslint-disable-next-line no-console - console.error(`(!) ${warning.message}`); - } -} diff --git a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts index 58cfb41a51d..ee3a86ad3f6 100644 --- a/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts +++ b/sdk/typescript/packages/mix-fetch-node/src/worker/main.ts @@ -1,9 +1,9 @@ /* eslint-disable no-console */ -import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import * as Comlink from 'comlink'; import { parentPort } from 'node:worker_threads'; import { setupMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch-wasm-node'; +import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import nodeEndpoint from '../node-adapter'; import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/package.json index 18d4c82220a..9965510bdb1 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/package.json @@ -1,9 +1,14 @@ { "name": "@nymproject/mix-fetch-tester-webpack", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", + "scripts": { + "build": "webpack build --progress --config webpack.prod.js", + "serve": "npx serve dist", + "start": "webpack serve --progress --port 3000" + }, "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.22.10", @@ -49,9 +54,5 @@ "webpack-dev-server": "^4.15.1", "webpack-merge": "^5.9.0" }, - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "serve": "npx serve dist" - } -} + "private": false +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json index 1983ca9c068..6849466cd3a 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json @@ -1,14 +1,15 @@ { "name": "@nymproject/mix-fetch-tester-parcel", - "version": "1.0.0", + "version": "1.0.1", "license": "Apache-2.0", - "source": "../src/index.html", - "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.10 || ^1" - }, "scripts": { - "start": "npx parcel --no-cache", "build": "npx parcel build --no-cache --no-content-hash", - "serve": "npx serve dist" - } -} + "serve": "npx serve dist", + "start": "npx parcel --no-cache" + }, + "dependencies": { + "@nymproject/mix-fetch": ">=1.2.1-rc.0 || ^1" + }, + "private": false, + "source": "../src/index.html" +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch/package.json b/sdk/typescript/packages/mix-fetch/package.json index a5350b90128..f58088197ba 100644 --- a/sdk/typescript/packages/mix-fetch/package.json +++ b/sdk/typescript/packages/mix-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch", - "version": "1.2.0", + "version": "1.2.1", "description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -33,7 +33,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/mix-fetch-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/node-tester/package.json b/sdk/typescript/packages/node-tester/package.json index f01028da1fc..acb32c0b192 100644 --- a/sdk/typescript/packages/node-tester/package.json +++ b/sdk/typescript/packages/node-tester/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/node-tester", - "version": "1.2.0", + "version": "1.2.1", "description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-node-tester-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/nym-node-tester-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json index 7a30d73cc38..d1d46f532d5 100644 --- a/sdk/typescript/packages/nodejs-client/package.json +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nodejs-client", - "version": "1.2.1-rc.3", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm-node": ">=1.2.0 || ^1", + "@nymproject/nym-client-wasm-node": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1", "fake-indexeddb": "^4.0.2", "rollup-plugin-polyfill": "^4.2.0", diff --git a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs index 7a4af49fc20..a1b3701df44 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-cjs.config.mjs @@ -12,6 +12,7 @@ export default { format: 'cjs', }, plugins: [ + resolve({ browser: false, extensions: ['.js', '.ts'] }), webWorkerLoader({ targetPlatform: 'node', inline: false }), replace({ values: { @@ -21,7 +22,6 @@ export default { delimiters: ['', ''], preventAssignment: true, }), - resolve({ browser: false, extensions: ['.js', '.ts'] }), wasm({ targetEnv: 'node', maxFileSize: 0 }), typescript({ compilerOptions: { outDir: 'dist/cjs', target: 'es5' }, diff --git a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs index b1b40b0a0ba..484b55d0100 100644 --- a/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs +++ b/sdk/typescript/packages/nodejs-client/rollup-worker.config.mjs @@ -11,6 +11,7 @@ export default { dir: 'dist/cjs', format: 'cjs', }, + external: ['util', 'fake-indexeddb'], plugins: [ resolve({ browser: false, @@ -18,6 +19,11 @@ export default { extensions: ['.js', '.ts'], }), commonjs(), + // TODO: One of the wasm functions calls `new WebSocket` at one point, which we aren't able to polyfill correctly yet. + modify({ + find: 'const ret = new WebSocket(getStringFromWasm0(arg0, arg1));', + replace: 'const ws = require("ws"); const ret = new ws.WebSocket(getStringFromWasm0(arg0, arg1));', + }), // TODO: `getObject(...).require` seems to generate a warning on Webpack but with Rollup we get a panic since it can't require. // By hard coding the require here, we can workaround that. // Reference: https://github.com/rust-random/getrandom/issues/224 diff --git a/sdk/typescript/packages/nodejs-client/src/polyfill.ts b/sdk/typescript/packages/nodejs-client/src/polyfill.ts index 425b49b5faf..3dceb23ba94 100644 --- a/sdk/typescript/packages/nodejs-client/src/polyfill.ts +++ b/sdk/typescript/packages/nodejs-client/src/polyfill.ts @@ -1,6 +1,6 @@ import * as crypto from 'node:crypto'; import * as fs from 'node:fs'; -import ws from 'ws'; +import WebSocket from 'ws'; import { TextDecoder, TextEncoder } from 'node:util'; import { Worker } from 'node:worker_threads'; import { indexedDB } from 'fake-indexeddb'; @@ -10,7 +10,7 @@ import { performance } from 'node:perf_hooks'; (globalThis as any).TextDecoder = TextDecoder; (globalThis as any).fs = fs; (globalThis as any).crypto = crypto; -(globalThis as any).ws = ws; +(globalThis as any).WebSocket = WebSocket; (globalThis as any).Worker = Worker; globalThis.process = process; diff --git a/sdk/typescript/packages/sdk-react/package.json b/sdk/typescript/packages/sdk-react/package.json index aa298a5a9d6..b6dafc5d23f 100644 --- a/sdk/typescript/packages/sdk-react/package.json +++ b/sdk/typescript/packages/sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-react", - "version": "1.2.0", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -20,7 +20,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.10 || ^1" + "@nymproject/sdk": ">=1.2.1-rc.0 || ^1" }, "devDependencies": { "@babel/core": "^7.17.5", @@ -67,4 +67,4 @@ "private": false, "type": "module", "types": "./dist/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index 62102504ac9..23e4b803ce0 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk", - "version": "1.2.0", + "version": "1.2.1", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -30,7 +30,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm": ">=1.2.0-rc.10 || ^1", + "@nymproject/nym-client-wasm": ">=1.2.1-rc.0 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index dabea53c6c9..3c599537761 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -10,9 +10,46 @@ set -o pipefail cd dist +#packages=( +#chat-app/parcel +#chat-app/plain-html +#chat-app/react-webpack-with-theme-example +#chrome-extension +#firefox-extension +#node-tester/parcel +#node-tester/plain-html +#node-tester/react +#react/mui-theme +#react/sdk-react +#) packages=( +"wasm/client" +"wasm/mix-fetch" +"wasm/node-tester" +"wasm/extension-storage" + +"node/wasm/client" +"node/wasm/mix-fetch" + +"ts/sdk/mix-fetch/cjs" +"ts/sdk/mix-fetch/cjs-full-fat" +"ts/sdk/mix-fetch/esm" +"ts/sdk/mix-fetch/esm-full-fat" + "ts/sdk/nodejs-client/cjs" "ts/sdk/mix-fetch-node/cjs" + +"ts/sdk/node-tester/cjs" +"ts/sdk/node-tester/cjs-full-fat" +"ts/sdk/node-tester/esm" +"ts/sdk/node-tester/esm-full-fat" + +"ts/sdk/sdk/cjs" +"ts/sdk/sdk/cjs-full-fat" +"ts/sdk/sdk/esm" +"ts/sdk/sdk/esm-full-fat" + +"ts/sdk/contract-clients" ) pushd () { @@ -39,14 +76,13 @@ COUNTER=0 for item in "${packages[@]}" do - (( COUNTER++ )) + (( COUNTER+=1 )) pushd "$item" echo "🚀 Publishing $item... (${COUNTER} of ${#packages[@]})" - jq -r '. | .name + " " +.version' < package.json - npm publish --access=public --verbose + cat package.json | jq -r '. | .name + " " +.version' + npm publish --access=public --verbose --workspaces false || true popd echo "" done echo "" echo "✅ Done" - diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index c01c13cfb4a..3aa52688f49 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -9,6 +9,7 @@ edition.workspace = true license.workspace = true [dependencies] +etherparse = "0.13.0" futures = { workspace = true } log = { workspace = true } nym-bin-common = { path = "../../common/bin-common" } @@ -18,6 +19,10 @@ nym-sdk = { path = "../../sdk/rust/nym-sdk" } nym-service-providers-common = { path = "../common" } nym-sphinx = { path = "../../common/nymsphinx" } nym-task = { path = "../../common/task" } +nym-wireguard = { path = "../../common/wireguard" } +nym-wireguard-types = { path = "../../common/wireguard-types" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +tap.workspace = true thiserror = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] } diff --git a/service-providers/ip-packet-router/src/config/mod.rs b/service-providers/ip-packet-router/src/config/mod.rs index 19bcaedc49c..4b6b811bda4 100644 --- a/service-providers/ip-packet-router/src/config/mod.rs +++ b/service-providers/ip-packet-router/src/config/mod.rs @@ -12,28 +12,28 @@ use std::{ path::{Path, PathBuf}, }; -use crate::config::persistence::IpForwarderPaths; +use crate::config::persistence::IpPacketRouterPaths; use self::template::CONFIG_TEMPLATE; mod persistence; mod template; -const DEFAULT_IP_FORWARDERS_DIR: &str = "ip-forwarder"; +const DEFAULT_IP_PACKET_ROUTER_DIR: &str = "ip-packet-router"; -/// Derive default path to ip forwarder's config directory. -/// It should get resolved to `$HOME/.nym/service-providers/ip-forwareder//config` +/// Derive default path to ip packet routers' config directory. +/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router//config` pub fn default_config_directory>(id: P) -> PathBuf { must_get_home() .join(NYM_DIR) .join(DEFAULT_SERVICE_PROVIDERS_DIR) - .join(DEFAULT_IP_FORWARDERS_DIR) + .join(DEFAULT_IP_PACKET_ROUTER_DIR) .join(id) .join(DEFAULT_CONFIG_DIR) } -/// Derive default path to ip forwarder's config file. -/// It should get resolved to `$HOME/.nym/service-providers/ip-forwarder//config/config.toml` +/// Derive default path to ip packet routers' config file. +/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router//config/config.toml` pub fn default_config_filepath>(id: P) -> PathBuf { default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) } @@ -44,7 +44,7 @@ pub fn default_data_directory>(id: P) -> PathBuf { must_get_home() .join(NYM_DIR) .join(DEFAULT_SERVICE_PROVIDERS_DIR) - .join(DEFAULT_IP_FORWARDERS_DIR) + .join(DEFAULT_IP_PACKET_ROUTER_DIR) .join(id) .join(DEFAULT_DATA_DIR) } @@ -55,7 +55,7 @@ pub struct Config { #[serde(flatten)] pub base: BaseClientConfig, - pub storage_paths: IpForwarderPaths, + pub storage_paths: IpPacketRouterPaths, pub logging: LoggingSettings, } @@ -70,13 +70,13 @@ impl Config { pub fn new>(id: S) -> Self { Config { base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")), - storage_paths: IpForwarderPaths::new_base(default_data_directory(id.as_ref())), + storage_paths: IpPacketRouterPaths::new_base(default_data_directory(id.as_ref())), logging: Default::default(), } } pub fn with_data_directory>(mut self, data_directory: P) -> Self { - self.storage_paths = IpForwarderPaths::new_base(data_directory); + self.storage_paths = IpPacketRouterPaths::new_base(data_directory); self } diff --git a/service-providers/ip-packet-router/src/config/persistence.rs b/service-providers/ip-packet-router/src/config/persistence.rs index 17276d36b3b..7f60a98f8c9 100644 --- a/service-providers/ip-packet-router/src/config/persistence.rs +++ b/service-providers/ip-packet-router/src/config/persistence.rs @@ -8,21 +8,21 @@ use std::path::{Path, PathBuf}; pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)] -pub struct IpForwarderPaths { +pub struct IpPacketRouterPaths { #[serde(flatten)] pub common_paths: CommonClientPaths, /// Location of the file containing our description - pub ip_forwarder_description: PathBuf, + pub ip_packet_router_description: PathBuf, } -impl IpForwarderPaths { +impl IpPacketRouterPaths { pub fn new_base>(base_data_directory: P) -> Self { let base_dir = base_data_directory.as_ref(); Self { common_paths: CommonClientPaths::new_base(base_dir), - ip_forwarder_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), + ip_packet_router_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), } } } diff --git a/service-providers/ip-packet-router/src/config/template.rs b/service-providers/ip-packet-router/src/config/template.rs index 2da118a5800..bbd9e18d5de 100644 --- a/service-providers/ip-packet-router/src/config/template.rs +++ b/service-providers/ip-packet-router/src/config/template.rs @@ -76,7 +76,7 @@ allowed_list_location = '{{ storage_paths.allowed_list_location }}' unknown_list_location = '{{ storage_paths.unknown_list_location }}' # Path to file containing description of this network-requester. -ip_forwarder_description = '{{ storage_paths.ip_forwarder_description }}' +ip_packet_router_description = '{{ storage_paths.ip_packet_router_description }}' ##### logging configuration options ##### diff --git a/service-providers/ip-packet-router/src/error.rs b/service-providers/ip-packet-router/src/error.rs index 7a0268fb614..8bf599e2323 100644 --- a/service-providers/ip-packet-router/src/error.rs +++ b/service-providers/ip-packet-router/src/error.rs @@ -1,7 +1,7 @@ pub use nym_client_core::error::ClientCoreError; #[derive(thiserror::Error, Debug)] -pub enum IpForwarderError { +pub enum IpPacketRouterError { #[error("I/O error: {0}")] IoError(#[from] std::io::Error), @@ -12,7 +12,7 @@ pub enum IpForwarderError { FailedToLoadConfig(String), // TODO: add more details here - #[error("Failed to validate the loaded config")] + #[error("failed to validate the loaded config")] ConfigValidationFailure, #[error("failed local version check, client and config mismatch")] @@ -26,4 +26,10 @@ pub enum IpForwarderError { #[error("the entity wrapping the network requester has disconnected")] DisconnectedParent, + + #[error("failed to parse incoming packet: {source}")] + PacketParseFailed { source: etherparse::ReadError }, + + #[error("parsed packet is missing IP header")] + PacketMissingHeader, } diff --git a/service-providers/ip-packet-router/src/lib.rs b/service-providers/ip-packet-router/src/lib.rs index 9aadf5f50a5..4957c2c02dc 100644 --- a/service-providers/ip-packet-router/src/lib.rs +++ b/service-providers/ip-packet-router/src/lib.rs @@ -1,13 +1,18 @@ -use std::path::Path; +use std::{net::IpAddr, path::Path}; -use error::IpForwarderError; -use futures::channel::oneshot; +use error::IpPacketRouterError; +use futures::{channel::oneshot, StreamExt}; use nym_client_core::{ client::mix_traffic::transceiver::GatewayTransceiver, config::disk_persistence::CommonClientPaths, HardcodedTopologyProvider, TopologyProvider, }; -use nym_sdk::{mixnet::Recipient, NymNetworkDetails}; -use nym_task::{TaskClient, TaskHandle}; +use nym_sdk::{ + mixnet::{InputMessage, MixnetMessageSender, Recipient}, + NymNetworkDetails, +}; +use nym_sphinx::receiver::ReconstructedMessage; +use nym_task::{connections::TransmissionLane, TaskClient, TaskHandle}; +use tap::TapFallible; use crate::config::BaseClientConfig; @@ -27,7 +32,8 @@ impl OnStartData { } } -pub struct IpForwarderBuilder { +pub struct IpPacketRouterBuilder { + #[allow(unused)] config: Config, wait_for_gateway: bool, custom_topology_provider: Option>, @@ -36,7 +42,7 @@ pub struct IpForwarderBuilder { on_start: Option>, } -impl IpForwarderBuilder { +impl IpPacketRouterBuilder { pub fn new(config: Config) -> Self { Self { config, @@ -87,20 +93,26 @@ impl IpForwarderBuilder { pub fn with_stored_topology>( mut self, file: P, - ) -> Result { + ) -> Result { self.custom_topology_provider = Some(Box::new(HardcodedTopologyProvider::new_from_file(file)?)); Ok(self) } - pub async fn run_service_provider(self) -> Result<(), IpForwarderError> { + #[cfg(not(target_os = "linux"))] + pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> { + todo!("service provider is not yet supported on this platform") + } + + #[cfg(target_os = "linux")] + pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> { // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). - let shutdown: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); + let task_handle: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); // Connect to the mixnet let mixnet_client = create_mixnet_client( &self.config.base, - shutdown.get_handle().named("nym_sdk::MixnetClient"), + task_handle.get_handle().named("nym_sdk::MixnetClient"), self.custom_gateway_transceiver, self.custom_topology_provider, self.wait_for_gateway, @@ -110,17 +122,140 @@ impl IpForwarderBuilder { let self_address = *mixnet_client.nym_address(); + // Create the TUN device that we interact with the rest of the world with + let (tun, tun_task_tx, tun_task_response_rx) = nym_wireguard::tun_device::TunDevice::new( + nym_wireguard::tun_device::RoutingMode::new_nat(), + ); + tun.start(); + + let ip_packet_router_service = IpPacketRouter { + _config: self.config, + // tun, + tun_task_tx, + tun_task_response_rx, + mixnet_client, + task_handle, + }; + log::info!("The address of this client is: {self_address}"); log::info!("All systems go. Press CTRL-C to stop the server."); if let Some(on_start) = self.on_start { if on_start.send(OnStartData::new(self_address)).is_err() { // the parent has dropped the channel before receiving the response - return Err(IpForwarderError::DisconnectedParent); + return Err(IpPacketRouterError::DisconnectedParent); + } + } + + ip_packet_router_service.run().await + } +} + +#[allow(unused)] +struct IpPacketRouter { + _config: Config, + // tun: nym_wireguard::tun_device::TunDevice, + tun_task_tx: nym_wireguard::tun_task_channel::TunTaskTx, + tun_task_response_rx: nym_wireguard::tun_task_channel::TunTaskResponseRx, + mixnet_client: nym_sdk::mixnet::MixnetClient, + task_handle: TaskHandle, +} + +#[allow(unused)] +impl IpPacketRouter { + async fn run(mut self) -> Result<(), IpPacketRouterError> { + let mut task_client = self.task_handle.fork("main_loop"); + + while !task_client.is_shutdown() { + tokio::select! { + _ = task_client.recv() => { + log::debug!("IpPacketRouter [main loop]: received shutdown"); + }, + msg = self.mixnet_client.next() => { + if let Some(msg) = msg { + self.on_message(msg).await.ok(); + } else { + log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); + break; + }; + }, + packet = self.tun_task_response_rx.recv() => { + if let Some((_tag, packet)) = packet { + // Read recipient from env variable NYM_CLIENT_ADDR which is a base58 + // string of the nym-address of the client that the packet should be + // sent back to. + // + // In the near future we will let the client expose it's nym-address + // directly, and after that, provide SURBS + let recipient = std::env::var("NYM_CLIENT_ADDR").ok().and_then(|addr| { + Recipient::try_from_base58_string(addr).ok() + }); + + if let Some(recipient) = recipient { + let lane = TransmissionLane::General; + let packet_type = None; + let input_message = InputMessage::new_regular(recipient, packet, lane, packet_type); + + self.mixnet_client + .send(input_message) + .await + .tap_err(|err| { + log::error!("IpPacketRouter [main loop]: failed to send packet to mixnet: {err}"); + }) + .ok(); + } else { + log::error!("NYM_CLIENT_ADDR not set or invalid"); + } + } else { + log::trace!("IpPacketRouter [main loop]: stopping since channel closed"); + break; + } + } + } } + log::info!("IpPacketRouter: stopping"); + Ok(()) + } + + async fn on_message( + &mut self, + reconstructed: ReconstructedMessage, + ) -> Result<(), IpPacketRouterError> { + log::info!("Received message: {:?}", reconstructed.sender_tag); + + let headers = etherparse::SlicedPacket::from_ip(&reconstructed.message).map_err(|err| { + log::warn!("Received non-IP packet: {err}"); + IpPacketRouterError::PacketParseFailed { source: err } + })?; + + let (src_addr, dst_addr): (IpAddr, IpAddr) = match headers.ip { + Some(etherparse::InternetSlice::Ipv4(ipv4_header, _)) => ( + ipv4_header.source_addr().into(), + ipv4_header.destination_addr().into(), + ), + Some(etherparse::InternetSlice::Ipv6(ipv6_header, _)) => ( + ipv6_header.source_addr().into(), + ipv6_header.destination_addr().into(), + ), + None => { + log::warn!("Received non-IP packet"); + return Err(IpPacketRouterError::PacketMissingHeader); + } + }; + log::info!("Received packet: {src_addr} -> {dst_addr}"); + + // TODO: set the tag correctly. Can we just reuse sender_tag? + let peer_tag = 0; + self.tun_task_tx + .send((peer_tag, reconstructed.message)) + .await + .tap_err(|err| { + log::error!("Failed to send packet to tun device: {err}"); + }) + .ok(); - todo!(); + Ok(()) } } @@ -128,6 +263,7 @@ impl IpForwarderBuilder { // This is NOT in the SDK since we don't want to expose any of the client-core config types. // We could however consider moving it to a crate in common in the future. // TODO: refactor this function and its arguments +#[allow(unused)] async fn create_mixnet_client( config: &BaseClientConfig, shutdown: TaskClient, @@ -135,7 +271,7 @@ async fn create_mixnet_client( custom_topology_provider: Option>, wait_for_gateway: bool, paths: &CommonClientPaths, -) -> Result { +) -> Result { let debug_config = config.debug; let storage_paths = nym_sdk::mixnet::StoragePaths::from(paths.clone()); @@ -143,7 +279,7 @@ async fn create_mixnet_client( let mut client_builder = nym_sdk::mixnet::MixnetClientBuilder::new_with_default_storage(storage_paths) .await - .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })? + .map_err(|err| IpPacketRouterError::FailedToSetupMixnetClient { source: err })? .network_details(NymNetworkDetails::new_from_env()) .debug_config(debug_config) .custom_shutdown(shutdown) @@ -160,10 +296,10 @@ async fn create_mixnet_client( let mixnet_client = client_builder .build() - .map_err(|err| IpForwarderError::FailedToSetupMixnetClient { source: err })?; + .map_err(|err| IpPacketRouterError::FailedToSetupMixnetClient { source: err })?; mixnet_client .connect_to_mixnet() .await - .map_err(|err| IpForwarderError::FailedToConnectToMixnet { source: err }) + .map_err(|err| IpPacketRouterError::FailedToConnectToMixnet { source: err }) } diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index a13ee1fed47..9ea3693ab45 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-network-requester" -version = "1.1.30" +version = "1.1.31" authors.workspace = true edition.workspace = true rust-version = "1.65" diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index 280a2313091..e2f5d56ae1f 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-network-statistics" -version = "1.1.30" +version = "1.1.31" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index e6472ca6761..85c82c1d3c5 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -186,12 +186,14 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_json("sdk/typescript/examples/node-tester/plain-html"); packages.register_json("sdk/typescript/examples/node-tester/react"); packages.register_json("sdk/typescript/packages/mix-fetch"); + packages.register_json("sdk/typescript/packages/mix-fetch-node"); packages.register_json("sdk/typescript/packages/mix-fetch/internal-dev"); packages.register_json("sdk/typescript/packages/mix-fetch/internal-dev/parcel"); packages.register_json("sdk/typescript/packages/node-tester"); packages.register_json("sdk/typescript/packages/nodejs-client"); packages.register_json("sdk/typescript/packages/sdk"); packages.register_json("sdk/typescript/packages/sdk-react"); + packages.register_json("sdk/typescript/codegen/contract-clients"); // dependencies that will have their versions adjusted in the above packages packages.register_known_js_dependency("@nymproject/mix-fetch"); diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index 5640b968408..a537c80b1c3 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.30" +version = "1.1.31" authors.workspace = true edition = "2021" diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 5b8dda73dae..8651e223d55 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client-wasm" authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index d2cd98d808b..0902eb625c8 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-wasm-sdk" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 50e5d61af29..3416758a3a3 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mix-fetch-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml index 7c75e6c9b18..0397d64349b 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-node-tester-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0" +version = "1.2.1" edition = "2021" keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" diff --git a/yarn.lock b/yarn.lock index 3309ce67f69..1602bf83557 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13227,6 +13227,17 @@ jest@^29.5.0: import-local "^3.0.2" jest-cli "^29.7.0" +joi@^17.11.0: + version "17.11.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" + integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"