Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 039c599c20 | |||
| 2cd38b6937 |
@@ -1,2 +0,0 @@
|
|||||||
[target.wasm32-unknown-unknown]
|
|
||||||
rustflags = ["--cfg=getrandom_backend=\"wasm_js\""]
|
|
||||||
@@ -25,14 +25,14 @@ jobs:
|
|||||||
echo "file2=$(ls nym-vpn*.deb)" >> $GITHUB_ENV
|
echo "file2=$(ls nym-vpn*.deb)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Upload nym-repo-setup
|
- name: Upload nym-repo-setup
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: ${{ env.file1 }}
|
name: ${{ env.file1 }}
|
||||||
path: ppa/packages/nym-repo-setup*.deb
|
path: ppa/packages/nym-repo-setup*.deb
|
||||||
retention-days: 10
|
retention-days: 10
|
||||||
|
|
||||||
- name: Upload nym-vpn
|
- name: Upload nym-vpn
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: ${{ env.file2 }}
|
name: ${{ env.file2 }}
|
||||||
path: ppa/packages/nym-vpn*.deb
|
path: ppa/packages/nym-vpn*.deb
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v5.0.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
with:
|
with:
|
||||||
version: 11.1.2
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -37,13 +37,8 @@ jobs:
|
|||||||
command: build
|
command: build
|
||||||
args: --workspace --release
|
args: --workspace --release
|
||||||
|
|
||||||
- name: Verify doc versions
|
|
||||||
run: ${{ github.workspace }}/documentation/scripts/verify-doc-versions.sh
|
|
||||||
working-directory: ${{ github.workspace }}
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
run: pnpm i
|
run: pnpm i
|
||||||
- name: Generate llms-full.txt
|
|
||||||
run: pnpm run generate:llms
|
|
||||||
- name: Build project
|
- name: Build project
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
- name: Generate sitemap
|
- name: Generate sitemap
|
||||||
|
|||||||
@@ -17,16 +17,13 @@ jobs:
|
|||||||
run: sudo apt-get install rsync
|
run: sudo apt-get install rsync
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v5.0.0
|
|
||||||
with:
|
|
||||||
version: 11.1.2
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: pnpm
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
- name: Build
|
- name: Build
|
||||||
run: pnpm install && pnpm build && pnpm build:ci:storybook
|
run: yarn && yarn build && yarn build:ci:storybook
|
||||||
- name: Deploy branch to CI www (storybook)
|
- name: Deploy branch to CI www (storybook)
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: easingthemes/ssh-deploy@main
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [arc-ubuntu-22.04]
|
platform: [ubuntu-22.04]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
env:
|
env:
|
||||||
@@ -110,7 +110,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: nym-binaries-artifacts
|
name: nym-binaries-artifacts
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
name: ci-build-upload-network-monitor-agent
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-upload:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
platform: [arc-ubuntu-22.04]
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Prepare build output directory
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
|
||||||
run: |
|
|
||||||
rm -rf ci-builds || true
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
- name: Install Dependencies (Linux)
|
|
||||||
run: sudo apt-get update && sudo apt-get -y install libudev-dev
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@master
|
|
||||||
with:
|
|
||||||
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
|
||||||
|
|
||||||
- name: Build nym-network-monitor-agent
|
|
||||||
shell: bash
|
|
||||||
run: cargo build -p nym-network-monitor-agent --release
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: nym-network-monitor-agent
|
|
||||||
path: target/release/nym-network-monitor-agent
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- name: Prepare build output
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
OUTPUT_DIR: ci-builds/${{ github.ref_name }}
|
|
||||||
run: cp target/release/nym-network-monitor-agent "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
- name: Deploy to CI www
|
|
||||||
uses: easingthemes/ssh-deploy@main
|
|
||||||
env:
|
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
|
||||||
ARGS: "-avzr"
|
|
||||||
SOURCE: "ci-builds/"
|
|
||||||
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
|
||||||
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
|
||||||
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/builds/
|
|
||||||
EXCLUDE: "/dist/, /node_modules/"
|
|
||||||
@@ -23,6 +23,7 @@ on:
|
|||||||
- 'sdk/ffi/**'
|
- 'sdk/ffi/**'
|
||||||
- 'sdk/rust/**'
|
- 'sdk/rust/**'
|
||||||
- 'service-providers/**'
|
- 'service-providers/**'
|
||||||
|
- 'nym-browser-extension/storage/**'
|
||||||
- 'tools/**'
|
- 'tools/**'
|
||||||
- 'wasm/**'
|
- 'wasm/**'
|
||||||
- 'Cargo.toml'
|
- 'Cargo.toml'
|
||||||
@@ -89,7 +90,7 @@ jobs:
|
|||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --workspace --all-targets --exclude nym-gateway-probe --exclude nym-node-status-api --exclude nym-node-status-agent --exclude nym-node-status-client -- -D warnings
|
args: --workspace --all-targets --exclude nym-gateway-probe --exclude nym-node-status-api -- -D warnings
|
||||||
|
|
||||||
- name: Clippy (non-macos)
|
- name: Clippy (non-macos)
|
||||||
if: contains(matrix.os, 'linux') || contains(matrix.os, 'windows')
|
if: contains(matrix.os, 'linux') || contains(matrix.os, 'windows')
|
||||||
@@ -103,15 +104,14 @@ jobs:
|
|||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --workspace --exclude nym-gateway-probe --exclude nym-node-status-api --exclude nym-node-status-agent --exclude nym-node-status-client
|
|
||||||
|
|
||||||
# Build Go FFI-dependent crates separately (requires Go, only available on Linux CI)
|
# only build on linux because of wg FFI bindings of its dependency (network probe)
|
||||||
- name: Build nym-node-status-api and nym-node-status-agent (linux only)
|
- name: Build nym-node-status-api (linux only)
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: -p nym-node-status-api -p nym-node-status-agent
|
args: -p nym-node-status-api
|
||||||
|
|
||||||
- name: Build all examples
|
- name: Build all examples
|
||||||
if: contains(matrix.os, 'linux')
|
if: contains(matrix.os, 'linux')
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
name: ci-crates-preflight
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'Cargo.toml'
|
|
||||||
- '**/Cargo.toml'
|
|
||||||
- 'tools/internal/check_publish_preflight.py'
|
|
||||||
- '.github/workflows/ci-crates-preflight.yml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
preflight:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Preflight publish checks
|
|
||||||
run: python3 tools/internal/check_publish_preflight.py
|
|
||||||
@@ -15,9 +15,6 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
publish-dry-run:
|
publish-dry-run:
|
||||||
runs-on: arc-linux-latest
|
runs-on: arc-linux-latest
|
||||||
timeout-minutes: 35
|
|
||||||
env:
|
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
@@ -40,7 +37,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: "20"
|
||||||
|
|
||||||
- name: Validate version format
|
- name: Validate version format
|
||||||
run: |
|
run: |
|
||||||
@@ -57,66 +54,25 @@ jobs:
|
|||||||
|
|
||||||
- name: Update workspace dependencies
|
- name: Update workspace dependencies
|
||||||
run: |
|
run: |
|
||||||
# Match any semver version on lines with `path = `, not just the current workspace version.
|
sed -i '/path = /s/version = "${{ steps.current_version.outputs.version }}"/version = "${{ inputs.version }}"/g' Cargo.toml
|
||||||
sed -i '/path = /s/version = "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"/version = "${{ inputs.version }}"/g' Cargo.toml
|
|
||||||
|
|
||||||
- name: Bump versions (local only)
|
- name: Bump versions (local only)
|
||||||
run: |
|
run: |
|
||||||
cargo workspaces version custom ${{ inputs.version }} \
|
cargo workspaces version custom ${{ inputs.version }} \
|
||||||
|
--allow-branch ${{ github.ref_name }} \
|
||||||
--no-git-commit \
|
--no-git-commit \
|
||||||
--yes
|
|
||||||
|
|
||||||
- name: Preflight publish checks
|
|
||||||
run: |
|
|
||||||
python3 tools/internal/check_publish_preflight.py
|
|
||||||
|
|
||||||
# Dry run may show cascading dependency errors because packages aren't
|
# Dry run may show cascading dependency errors because packages aren't
|
||||||
# actually uploaded - these are expected and ignored. We check for real
|
# actually uploaded - these are expected and ignored. We check for real
|
||||||
# errors like packaging failures, missing metadata, or invalid Cargo.toml.
|
# errors like packaging failures, missing metadata, or invalid Cargo.toml.
|
||||||
- name: Publish (dry run)
|
- name: Publish (dry run)
|
||||||
run: |
|
run: |
|
||||||
set +e
|
output=$(cargo workspaces publish --dry-run --allow-dirty 2>&1) || true
|
||||||
publish_status=1
|
echo "$output"
|
||||||
max_attempts=2
|
|
||||||
attempt=1
|
|
||||||
rm -f /tmp/publish-dry-run.log
|
|
||||||
|
|
||||||
while [ "$attempt" -le "$max_attempts" ]; do
|
# Check for real errors (not cascading dependency errors)
|
||||||
echo "Dry-run publish attempt ${attempt}/${max_attempts}"
|
# Cascading errors mention "crates.io index", real errors mention "Cargo.toml"
|
||||||
cargo workspaces publish --dry-run --allow-dirty 2>&1 | tee /tmp/publish-dry-run.log
|
echo "$output" | grep -i "Cargo.toml" && exit 1 || true
|
||||||
publish_status=${PIPESTATUS[0]}
|
|
||||||
|
|
||||||
if [ "$publish_status" -eq 0 ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Retry once for interruption/runner issues.
|
|
||||||
if [ "$attempt" -lt "$max_attempts" ] && \
|
|
||||||
{ [ "$publish_status" -eq 130 ] || [ "$publish_status" -eq 137 ]; }; then
|
|
||||||
echo "Publish dry-run interrupted (exit ${publish_status}), retrying in 10s..."
|
|
||||||
sleep 10
|
|
||||||
attempt=$((attempt + 1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
break
|
|
||||||
done
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if grep -Eiq \
|
|
||||||
"failed to verify manifest|failed to parse manifest|invalid Cargo.toml|error: package .* has no (description|license|repository)" \
|
|
||||||
/tmp/publish-dry-run.log; then
|
|
||||||
echo "Detected real packaging/manifest errors"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# In dry-run mode, non-zero publish status is expected due to
|
|
||||||
# dependency-cascade failures against crates.io index.
|
|
||||||
if [ "$publish_status" -ne 0 ]; then
|
|
||||||
echo "Dry-run publish returned non-zero (${publish_status}) but no real manifest blockers were detected."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Only expected dry-run dependency cascade errors detected (if any)."
|
|
||||||
|
|
||||||
# Show the list of packages published
|
# Show the list of packages published
|
||||||
- name: Show package versions
|
- name: Show package versions
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: arc-linux-latest
|
runs-on: arc-linux-latest
|
||||||
env:
|
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
runs-on: arc-linux-latest
|
runs-on: arc-linux-latest
|
||||||
env:
|
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
@@ -33,11 +31,7 @@ jobs:
|
|||||||
- name: Install cargo-workspaces
|
- name: Install cargo-workspaces
|
||||||
run: cargo install cargo-workspaces
|
run: cargo install cargo-workspaces
|
||||||
|
|
||||||
- name: Preflight publish checks
|
# `--publish-as-is` skips version bumping since that's done in a separate CI job.
|
||||||
run: |
|
|
||||||
python3 tools/internal/check_publish_preflight.py
|
|
||||||
|
|
||||||
# --publish-as-is skips version bumping since that's done in a separate CI job.
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
env:
|
env:
|
||||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
version-bump:
|
version-bump:
|
||||||
runs-on: arc-linux-latest
|
runs-on: arc-linux-latest
|
||||||
env:
|
|
||||||
RUSTUP_PERMIT_COPY_RENAME: 1
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
@@ -42,7 +39,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: "20"
|
||||||
|
|
||||||
- name: Validate version format
|
- name: Validate version format
|
||||||
run: |
|
run: |
|
||||||
@@ -59,9 +56,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Update workspace dependencies
|
- name: Update workspace dependencies
|
||||||
run: |
|
run: |
|
||||||
# Match any semver version on lines with `path = `, not just the current workspace version.
|
sed -i '/path = /s/version = "${{ steps.current_version.outputs.version }}"/version = "${{ inputs.version }}"/g' Cargo.toml
|
||||||
# This catches entries whose version has drifted (e.g. nym-sqlx-pool-guard at 1.2.0).
|
|
||||||
sed -i '/path = /s/version = "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"/version = "${{ inputs.version }}"/g' Cargo.toml
|
|
||||||
|
|
||||||
- name: Bump versions
|
- name: Bump versions
|
||||||
run: |
|
run: |
|
||||||
@@ -71,33 +66,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Commit and push version bump
|
- name: Commit and push version bump
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
|
||||||
BASE_BRANCH="${GITHUB_REF_NAME}"
|
|
||||||
PR_BRANCH="ci/crates-version-bump-${{ inputs.version }}-${GITHUB_RUN_ID}"
|
|
||||||
|
|
||||||
git checkout -b "$PR_BRANCH"
|
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "crates release: bump version to ${{ inputs.version }}"
|
git commit -m "crates release: bump version to ${{ inputs.version }}"
|
||||||
git push -u origin "$PR_BRANCH"
|
git push
|
||||||
|
|
||||||
cat > /tmp/crates-version-bump-pr-body.md <<'EOF'
|
|
||||||
This PR was created by CI because direct pushes to the release branch are blocked by branch protection rules.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
- Bump workspace crate versions to the requested release version.
|
|
||||||
- Update workspace dependency versions accordingly.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
- Merge this PR to proceed with crates.io publishing.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
gh pr create \
|
|
||||||
--base "$BASE_BRANCH" \
|
|
||||||
--head "$PR_BRANCH" \
|
|
||||||
--title "crates release: bump version to ${{ inputs.version }}" \
|
|
||||||
--body-file /tmp/crates-version-bump-pr-body.md
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Show package versions
|
- name: Show package versions
|
||||||
run: cargo workspaces list --long
|
run: cargo workspaces list --long
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ on:
|
|||||||
branches-ignore: [master]
|
branches-ignore: [master]
|
||||||
paths:
|
paths:
|
||||||
- "documentation/docs/**"
|
- "documentation/docs/**"
|
||||||
- "sdk/typescript/packages/sdk/src/**"
|
|
||||||
- "sdk/typescript/packages/mix-fetch/src/**"
|
|
||||||
- ".github/workflows/ci-docs.yml"
|
- ".github/workflows/ci-docs.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -28,12 +26,12 @@ jobs:
|
|||||||
run: sudo apt-get install -y rsync
|
run: sudo apt-get install -y rsync
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v5.0.0
|
uses: pnpm/action-setup@v4.2.0
|
||||||
with:
|
with:
|
||||||
version: 11.1.2
|
version: 9
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -44,30 +42,8 @@ jobs:
|
|||||||
command: build
|
command: build
|
||||||
args: --workspace --release
|
args: --workspace --release
|
||||||
|
|
||||||
- name: Check if TypeScript SDK source changed
|
|
||||||
id: check-ts-sdk
|
|
||||||
run: |
|
|
||||||
if git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep -qE '^sdk/typescript/packages/(sdk|mix-fetch)/src/'; then
|
|
||||||
echo "changed=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "changed=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
working-directory: ${{ github.workspace }}
|
|
||||||
|
|
||||||
- name: Regenerate TypeDoc API reference
|
|
||||||
if: steps.check-ts-sdk.outputs.changed == 'true'
|
|
||||||
run: |
|
|
||||||
npm install -g typedoc@0.25.13 typedoc-plugin-markdown@4.0.3
|
|
||||||
cd ${{ github.workspace }}/sdk/typescript/packages/sdk && typedoc --skipErrorChecking
|
|
||||||
cd ${{ github.workspace }}/sdk/typescript/packages/mix-fetch && typedoc --skipErrorChecking
|
|
||||||
|
|
||||||
- name: Verify doc versions
|
|
||||||
run: ${{ github.workspace }}/documentation/scripts/verify-doc-versions.sh
|
|
||||||
working-directory: ${{ github.workspace }}
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
run: pnpm i
|
run: pnpm i
|
||||||
- name: Generate llms-full.txt
|
|
||||||
run: pnpm run generate:llms
|
|
||||||
- name: Build project
|
- name: Build project
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
- name: Generate sitemap
|
- name: Generate sitemap
|
||||||
|
|||||||
@@ -20,14 +20,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
- uses: rlespinasse/github-slug-action@v3.x
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v5.0.0
|
|
||||||
with:
|
|
||||||
version: 11.1.2
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: pnpm
|
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
@@ -46,16 +44,16 @@ jobs:
|
|||||||
go-version: "1.24.6"
|
go-version: "1.24.6"
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: pnpm i
|
run: yarn
|
||||||
|
|
||||||
- name: Build packages
|
- name: Build packages
|
||||||
run: pnpm build:ci
|
run: yarn build:ci
|
||||||
|
|
||||||
- name: Install again
|
- name: Install again
|
||||||
run: pnpm i
|
run: yarn
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: pnpm lint
|
run: yarn lint
|
||||||
|
|
||||||
- name: Typecheck with tsc
|
- name: Typecheck with tsc
|
||||||
run: pnpm tsc
|
run: yarn tsc
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
name: ci-nym-wallet-frontend
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'nym-wallet/**'
|
|
||||||
- '.github/workflows/ci-nym-wallet-frontend.yml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
types-lint:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v5.0.0
|
|
||||||
with:
|
|
||||||
version: 11.1.2
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: nym-wallet/.nvmrc
|
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Build TypeScript packages (wallet depends on @nymproject/types, etc.)
|
|
||||||
run: pnpm build:types
|
|
||||||
|
|
||||||
- name: Build @nymproject/mui-theme and @nymproject/react (wallet imports subpaths)
|
|
||||||
run: pnpm build:packages
|
|
||||||
|
|
||||||
- name: Typecheck nym-wallet
|
|
||||||
run: pnpm --filter @nymproject/nym-wallet-app tsc
|
|
||||||
|
|
||||||
- name: Lint nym-wallet
|
|
||||||
run: pnpm --filter @nymproject/nym-wallet-app lint
|
|
||||||
|
|
||||||
- name: pnpm audit (workspace lockfile; informational)
|
|
||||||
run: pnpm audit --audit-level critical
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Unit tests (nym-wallet)
|
|
||||||
run: pnpm --filter @nymproject/nym-wallet-app test
|
|
||||||
@@ -41,9 +41,6 @@ jobs:
|
|||||||
sed -i.bak '1s/^/\[profile.dev\]\ndebug = false\n\n/' Cargo.toml
|
sed -i.bak '1s/^/\[profile.dev\]\ndebug = false\n\n/' Cargo.toml
|
||||||
git diff
|
git diff
|
||||||
|
|
||||||
- name: Ensure nym-wallet/dist exists for Tauri
|
|
||||||
run: mkdir -p nym-wallet/dist
|
|
||||||
|
|
||||||
- name: Build all binaries
|
- name: Build all binaries
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
@@ -74,16 +71,3 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features --all-targets -- -D warnings
|
args: --manifest-path nym-wallet/Cargo.toml --workspace --all-features --all-targets -- -D warnings
|
||||||
|
|
||||||
- name: Install cargo-audit
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: cargo-audit --locked
|
|
||||||
|
|
||||||
- name: Cargo audit (nym-wallet workspace)
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: audit
|
|
||||||
working-directory: nym-wallet
|
|
||||||
continue-on-error: true
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
name: ci-nym-wallet-storybook
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'nym-wallet/**'
|
||||||
|
- '.github/workflows/ci-nym-wallet-storybook.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: arc-linux-latest-dind
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Install rsync
|
||||||
|
run: sudo apt-get install rsync
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- uses: rlespinasse/github-slug-action@v3.x
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
|
||||||
|
- name: Install Rust toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
||||||
|
|
||||||
|
- name: Install wasm-pack
|
||||||
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
|
|
||||||
|
- name: Build dependencies
|
||||||
|
run: yarn && yarn build
|
||||||
|
|
||||||
|
- name: Build storybook
|
||||||
|
run: yarn storybook:build
|
||||||
|
working-directory: ./nym-wallet
|
||||||
|
|
||||||
|
- name: Deploy branch to CI www (storybook)
|
||||||
|
continue-on-error: true
|
||||||
|
uses: easingthemes/ssh-deploy@main
|
||||||
|
env:
|
||||||
|
SSH_PRIVATE_KEY: ${{ secrets.CI_WWW_SSH_PRIVATE_KEY }}
|
||||||
|
ARGS: "-rltgoDzvO --delete"
|
||||||
|
SOURCE: "nym-wallet/storybook-static/"
|
||||||
|
REMOTE_HOST: ${{ secrets.CI_WWW_REMOTE_HOST }}
|
||||||
|
REMOTE_USER: ${{ secrets.CI_WWW_REMOTE_USER }}
|
||||||
|
TARGET: ${{ secrets.CI_WWW_REMOTE_TARGET }}/wallet-${{ env.GITHUB_REF_SLUG }}
|
||||||
|
EXCLUDE: "/dist/, /node_modules/"
|
||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Install Dependencies (Linux)
|
- name: Install Dependencies (Linux)
|
||||||
run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
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-22.04'
|
if: matrix.os == 'ubuntu-22.04'
|
||||||
|
|
||||||
- name: Install rust toolchain
|
- name: Install rust toolchain
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
find . -name Cargo.toml -exec cargo deny --manifest-path {} check \
|
find . -name Cargo.toml -exec cargo deny --manifest-path {} check \
|
||||||
advisories -A advisory-not-detected --hide-inclusion-graph \; &> \
|
advisories -A advisory-not-detected --hide-inclusion-graph \; &> \
|
||||||
>(uniq &> .github/workflows/support-files/notifications/deny.message )
|
>(uniq &> .github/workflows/support-files/notifications/deny.message )
|
||||||
- uses: actions/upload-artifact@v7
|
- uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: report
|
name: report
|
||||||
path: .github/workflows/support-files/notifications/deny.message
|
path: .github/workflows/support-files/notifications/deny.message
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: arc-ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
args: --workspace --release ${{ env.CARGO_FEATURES }}
|
args: --workspace --release ${{ env.CARGO_FEATURES }}
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: my-artifact
|
name: my-artifact
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ jobs:
|
|||||||
run: make contracts
|
run: make contracts
|
||||||
|
|
||||||
- name: Upload Mixnet Contract Artifact
|
- name: Upload Mixnet Contract Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: mixnet_contract.wasm
|
name: mixnet_contract.wasm
|
||||||
path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm
|
path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
- name: Upload Vesting Contract Artifact
|
- name: Upload Vesting Contract Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: vesting_contract.wasm
|
name: vesting_contract.wasm
|
||||||
path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
|
path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm
|
||||||
|
|||||||
@@ -23,13 +23,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Node
|
||||||
uses: pnpm/action-setup@v5.0.0
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
version: 11.1.2
|
node-version: 21
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -71,17 +68,17 @@ jobs:
|
|||||||
fileName: '.env'
|
fileName: '.env'
|
||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
- name: pnpm cache clean
|
- name: Yarn cache clean
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && pnpm cache delete
|
run: cd .. && yarn cache clean
|
||||||
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && pnpm i
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Build
|
- name: Yarn build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && pnpm build
|
run: cd .. && yarn build
|
||||||
|
|
||||||
- name: Install dependencies and build it
|
- name: Install dependencies and build it
|
||||||
env:
|
env:
|
||||||
@@ -100,7 +97,7 @@ jobs:
|
|||||||
TAURI_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
TAURI_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||||
TAURI_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
TAURI_NOTARIZATION_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
run: |
|
run: |
|
||||||
pnpm build-macx86
|
yarn build-macx86
|
||||||
|
|
||||||
- name: Create app tarball
|
- name: Create app tarball
|
||||||
run: |
|
run: |
|
||||||
@@ -111,7 +108,7 @@ jobs:
|
|||||||
cd -
|
cd -
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: nym-wallet.app.tar.gz
|
name: nym-wallet.app.tar.gz
|
||||||
path: nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/nym-wallet.app.tar.gz
|
path: nym-wallet/target/x86_64-apple-darwin/release/bundle/macos/nym-wallet.app.tar.gz
|
||||||
|
|||||||
@@ -26,17 +26,12 @@ jobs:
|
|||||||
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev jq \
|
||||||
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
libgtk-3-dev squashfs-tools libayatana-appindicator3-dev make libfuse2 unzip librsvg2-dev file \
|
||||||
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v5.0.0
|
|
||||||
with:
|
|
||||||
version: 11.1.2
|
|
||||||
|
|
||||||
- name: Node
|
- name: Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 21
|
||||||
cache: 'pnpm'
|
cache: 'yarn'
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -45,10 +40,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && pnpm i
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
run: pnpm
|
run: yarn
|
||||||
|
|
||||||
- name: Create env file
|
- name: Create env file
|
||||||
uses: timheuer/base64-to-file@v1.2
|
uses: timheuer/base64-to-file@v1.2
|
||||||
@@ -57,7 +52,7 @@ jobs:
|
|||||||
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }}
|
||||||
|
|
||||||
- name: Build app
|
- name: Build app
|
||||||
run: pnpm build
|
run: yarn build
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
@@ -77,41 +72,6 @@ jobs:
|
|||||||
find target/release/bundle -type d -name "*appimage*" -o -name "*AppImage*" || echo "No AppImage directories found"
|
find target/release/bundle -type d -name "*appimage*" -o -name "*AppImage*" || echo "No AppImage directories found"
|
||||||
find target/release/bundle -name "*.AppImage" -o -name "*.appimage" || echo "No AppImage files found"
|
find target/release/bundle -name "*.AppImage" -o -name "*.appimage" || echo "No AppImage files found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Inspect AppImage (hook + bundled graphics libs)
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
APPIMAGE_REL=$(find target/release/bundle -name '*.AppImage' | head -n 1)
|
|
||||||
if [ -z "${APPIMAGE_REL}" ]; then
|
|
||||||
echo "No AppImage under target/release/bundle"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
APPIMAGE_ABS="${GITHUB_WORKSPACE}/nym-wallet/${APPIMAGE_REL}"
|
|
||||||
chmod +x "${APPIMAGE_ABS}"
|
|
||||||
EXTRACT_DIR=$(mktemp -d)
|
|
||||||
cd "${EXTRACT_DIR}"
|
|
||||||
"${APPIMAGE_ABS}" --appimage-extract
|
|
||||||
# Tauri only stages appimage "files" under /usr/ into the AppDir; paths like /apprun-hooks/ never reach the image.
|
|
||||||
# Wayland + WEBKIT_DISABLE_DMABUF_RENDERER defaults are applied in main() instead (see configure_linux_wayland_defaults).
|
|
||||||
HOOK=$(find squashfs-root -name '99-nym-wayland.sh' 2>/dev/null | head -n 1)
|
|
||||||
if [ -n "${HOOK}" ]; then
|
|
||||||
echo "Found legacy apprun hook at ${HOOK}"
|
|
||||||
else
|
|
||||||
echo "No apprun-hooks/99-nym-wayland.sh (expected): Wayland defaults are set in-process."
|
|
||||||
fi
|
|
||||||
find squashfs-root/usr/lib -maxdepth 6 \
|
|
||||||
\( -name 'libwayland-client.so*' -o -name 'libEGL.so*' -o -name 'libgbm.so*' \) \
|
|
||||||
2>/dev/null | sort > "${GITHUB_WORKSPACE}/nym-wallet/appimage-bundled-graphics-libs.txt"
|
|
||||||
wc -l "${GITHUB_WORKSPACE}/nym-wallet/appimage-bundled-graphics-libs.txt"
|
|
||||||
head -50 "${GITHUB_WORKSPACE}/nym-wallet/appimage-bundled-graphics-libs.txt" || true
|
|
||||||
|
|
||||||
- name: Upload AppImage graphics lib inventory
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: nym-wallet-appimage-lib-inventory
|
|
||||||
path: nym-wallet/appimage-bundled-graphics-libs.txt
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- name: Create AppImage tarball if needed
|
- name: Create AppImage tarball if needed
|
||||||
run: |
|
run: |
|
||||||
@@ -137,7 +97,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: nym-wallet-appimage.tar.gz
|
name: nym-wallet-appimage.tar.gz
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
release_tag: ${{ github.ref_name }}
|
release_tag: ${{ github.ref_name }}
|
||||||
|
|
||||||
env:
|
|
||||||
SIGN_WINDOWS: ${{ github.event_name == 'release' || inputs.sign }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -38,88 +35,57 @@ jobs:
|
|||||||
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
toolchain: ${{ vars.REQUIRED_RUSTC_VERSION }}
|
||||||
|
|
||||||
- name: Setup MSBuild.exe
|
- name: Setup MSBuild.exe
|
||||||
uses: microsoft/setup-msbuild@v3
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Node
|
||||||
uses: pnpm/action-setup@v5.0.0
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
version: 11.1.2
|
node-version: 21
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
|
|
||||||
- name: Strip Authenticode thumbprint (avoid signtool on runner)
|
|
||||||
working-directory: nym-wallet/src-tauri
|
|
||||||
if: ${{ env.SIGN_WINDOWS == 'true' || (github.event_name == 'workflow_dispatch' && !inputs.sign) }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! command -v yq >/dev/null 2>&1; then
|
|
||||||
echo "yq is required on this runner to edit tauri.conf.json"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
yq eval --inplace '
|
|
||||||
del(.bundle.windows.certificateThumbprint) |
|
|
||||||
del(.bundle.windows.digestAlgorithm) |
|
|
||||||
del(.bundle.windows.timestampUrl)
|
|
||||||
' tauri.conf.json
|
|
||||||
|
|
||||||
- name: Download EV CodeSignTool from ssl.com
|
- name: Download EV CodeSignTool from ssl.com
|
||||||
working-directory: nym-wallet/src-tauri
|
working-directory: nym-wallet/src-tauri
|
||||||
if: env.SIGN_WINDOWS == 'true'
|
if: ${{ inputs.sign }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -L0 https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o codesigntool.zip
|
curl -L0 https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o codesigntool.zip
|
||||||
unzip codesigntool.zip
|
unzip codesigntool.zip
|
||||||
- name: Get EV certificate credential id
|
- name: Get EV certificate credential id
|
||||||
working-directory: nym-wallet/src-tauri
|
working-directory: nym-wallet/src-tauri
|
||||||
if: env.SIGN_WINDOWS == 'true'
|
if: ${{ inputs.sign }}
|
||||||
id: get_credential_ids
|
id: get_credential_ids
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "SSL_COM_CREDENTIAL_ID=$(./CodeSignTool.sh get_credential_ids -username=${{ secrets.SSL_COM_USERNAME }} -password=${{ secrets.SSL_COM_PASSWORD }} | sed -n '1!p' | sed 's/- //')" >> "$GITHUB_OUTPUT"
|
echo "SSL_COM_CREDENTIAL_ID=$(./CodeSignTool.sh get_credential_ids -username=${{ secrets.SSL_COM_USERNAME }} -password=${{ secrets.SSL_COM_PASSWORD }} | sed -n '1!p' | sed 's/- //')" >> "$GITHUB_OUTPUT"
|
||||||
- name: Add custom sign command to tauri.conf.json
|
- name: Add custom sign command to tauri.conf.json
|
||||||
working-directory: nym-wallet/src-tauri
|
working-directory: nym-wallet/src-tauri
|
||||||
if: env.SIGN_WINDOWS == 'true'
|
if: ${{ inputs.sign }}
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
|
||||||
SSL_SIGN_USER: ${{ secrets.SSL_COM_USERNAME }}
|
|
||||||
SSL_SIGN_PASS: ${{ secrets.SSL_COM_PASSWORD }}
|
|
||||||
SSL_SIGN_CRED: ${{ steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}
|
|
||||||
SSL_SIGN_TOTP: ${{ secrets.SSL_COM_TOTP_SECRET }}
|
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
yq eval --inplace '.bundle.windows +=
|
||||||
if ! command -v cygpath >/dev/null 2>&1; then
|
{
|
||||||
echo "cygpath not found; install Git for Windows or use bash from Git SDK"
|
"signCommand": {
|
||||||
exit 1
|
"cmd": "C:\Program Files\Git\bin\bash.EXE",
|
||||||
fi
|
"args": [
|
||||||
export SCRIPT_UNIX="$(cygpath -u "$GITHUB_WORKSPACE/nym-wallet/src-tauri/CodeSignTool.sh")"
|
"/c/actions-runner/_work/nym/nym/nym-wallet/src-tauri/CodeSignTool.sh",
|
||||||
yq eval --inplace '
|
"sign",
|
||||||
.bundle.windows += {
|
"-username ${{ secrets.SSL_COM_USERNAME }}",
|
||||||
"signCommand": {
|
"-password ${{ secrets.SSL_COM_PASSWORD }}",
|
||||||
"cmd": "C:/Program Files/Git/bin/bash.exe",
|
"-credential_id ${{ steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}",
|
||||||
"args": [
|
"-totp_secret ${{ secrets.SSL_COM_TOTP_SECRET }}",
|
||||||
strenv(SCRIPT_UNIX),
|
"-program_name NymWallet",
|
||||||
"sign",
|
"-input_file_path",
|
||||||
("-username " + strenv(SSL_SIGN_USER)),
|
"%1",
|
||||||
("-password " + strenv(SSL_SIGN_PASS)),
|
"-override"
|
||||||
("-credential_id " + strenv(SSL_SIGN_CRED)),
|
]
|
||||||
("-totp_secret " + strenv(SSL_SIGN_TOTP)),
|
|
||||||
"-program_name NymWallet",
|
|
||||||
"-input_file_path",
|
|
||||||
"%1",
|
|
||||||
"-override"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
' tauri.conf.json
|
}' tauri.conf.json
|
||||||
- name: Install project dependencies
|
- name: Install project dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cd .. && pnpm i
|
run: cd .. && yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Install app dependencies
|
- name: Install app dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: pnpm i
|
run: yarn --network-timeout 100000
|
||||||
|
|
||||||
- name: Build and sign it
|
- name: Build and sign it
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -127,13 +93,13 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
SSL_COM_USERNAME: ${{ env.SIGN_WINDOWS == 'true' && secrets.SSL_COM_USERNAME }}
|
SSL_COM_USERNAME: ${{ inputs.sign && secrets.SSL_COM_USERNAME }}
|
||||||
SSL_COM_PASSWORD: ${{ env.SIGN_WINDOWS == 'true' && secrets.SSL_COM_PASSWORD }}
|
SSL_COM_PASSWORD: ${{ inputs.sign && secrets.SSL_COM_PASSWORD }}
|
||||||
SSL_COM_CREDENTIAL_ID: ${{ env.SIGN_WINDOWS == 'true' && steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}
|
SSL_COM_CREDENTIAL_ID: ${{ inputs.sign && steps.get_credential_ids.outputs.SSL_COM_CREDENTIAL_ID }}
|
||||||
SSL_COM_TOTP_SECRET: ${{ env.SIGN_WINDOWS == 'true' && secrets.SSL_COM_TOTP_SECRET }}
|
SSL_COM_TOTP_SECRET: ${{ inputs.sign && secrets.SSL_COM_TOTP_SECRET }}
|
||||||
run: |
|
run: |
|
||||||
echo "Starting build process..."
|
echo "Starting build process..."
|
||||||
pnpm build
|
yarn build
|
||||||
|
|
||||||
- name: Check bundle directory
|
- name: Check bundle directory
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -162,7 +128,7 @@ jobs:
|
|||||||
find . -name "*.msi" -type f
|
find . -name "*.msi" -type f
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: nym-wallet.msi
|
name: nym-wallet.msi
|
||||||
path: |
|
path: |
|
||||||
@@ -201,4 +167,4 @@ jobs:
|
|||||||
needs: publish-tauri
|
needs: publish-tauri
|
||||||
with:
|
with:
|
||||||
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
release_tag: ${{ needs.publish-tauri.outputs.release_tag || github.ref_name }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -76,7 +76,7 @@ jobs:
|
|||||||
apk/nyms5-arch64-release.apk
|
apk/nyms5-arch64-release.apk
|
||||||
|
|
||||||
- name: Upload APKs
|
- name: Upload APKs
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: nyms5-apk-arch64
|
name: nyms5-apk-arch64
|
||||||
path: |
|
path: |
|
||||||
@@ -91,7 +91,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
- name: Download binary artifact
|
- name: Download binary artifact
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/download-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: nyms5-apk-arch64
|
name: nyms5-apk-arch64
|
||||||
path: apk
|
path: apk
|
||||||
|
|||||||
@@ -8,17 +8,15 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v5.0.0
|
|
||||||
with:
|
|
||||||
version: 11.1.2
|
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
|
- name: Setup yarn
|
||||||
|
run: npm install -g yarn
|
||||||
|
|
||||||
- name: Install rust toolchain
|
- name: Install rust toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
@@ -42,10 +40,10 @@ jobs:
|
|||||||
run: ./wasm/mix-fetch/go-mix-conn/scripts/update-root-certs.sh
|
run: ./wasm/mix-fetch/go-mix-conn/scripts/update-root-certs.sh
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm i
|
run: yarn
|
||||||
|
|
||||||
- name: Build WASM and Typescript SDK
|
- name: Build WASM and Typescript SDK
|
||||||
run: pnpm sdk:build
|
run: yarn sdk:build
|
||||||
|
|
||||||
- name: Publish to NPM
|
- name: Publish to NPM
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-linux-latest-dind
|
runs-on: arc-linux-latest-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-linux-latest-dind
|
runs-on: arc-linux-latest-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
name: Build and upload Network Monitor Agent container to harbor.nymte.ch
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
release_image:
|
|
||||||
description: 'Tag image as a release (prefix with golden-)'
|
|
||||||
required: true
|
|
||||||
default: false
|
|
||||||
type: boolean
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-network-monitor-v3/nym-network-monitor-agent"
|
|
||||||
CONTAINER_NAME: "network-monitor-agent"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-linux-latest-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from Cargo.toml
|
|
||||||
id: get_version
|
|
||||||
run: |
|
|
||||||
VERSION=$(yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml)
|
|
||||||
echo "result=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Set GIT_TAG variable
|
|
||||||
run: echo "GIT_TAG=${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Initialize RELEASE_TAG
|
|
||||||
run: echo "RELEASE_TAG=" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set RELEASE_TAG for release
|
|
||||||
if: github.event.inputs.release_image == 'true'
|
|
||||||
run: echo "RELEASE_TAG=golden-" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set IMAGE_NAME_AND_TAGS variable
|
|
||||||
run: echo "IMAGE_NAME_AND_TAGS=${{ env.CONTAINER_NAME }}:${{ env.RELEASE_TAG }}${{ steps.get_version.outputs.result }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: New env vars
|
|
||||||
run: echo "RELEASE_TAG='$RELEASE_TAG' GIT_TAG='$GIT_TAG' IMAGE_NAME_AND_TAGS='$IMAGE_NAME_AND_TAGS'"
|
|
||||||
|
|
||||||
- name: Build and push image to Harbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.IMAGE_NAME_AND_TAGS }}
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
name: Build and upload Network Monitor Orchestrator container to harbor.nymte.ch
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
release_image:
|
|
||||||
description: 'Tag image as a release (prefix with golden-)'
|
|
||||||
required: true
|
|
||||||
default: false
|
|
||||||
type: boolean
|
|
||||||
|
|
||||||
env:
|
|
||||||
WORKING_DIRECTORY: "nym-network-monitor-v3/nym-network-monitor-orchestrator"
|
|
||||||
CONTAINER_NAME: "network-monitor-orchestrator"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-container:
|
|
||||||
runs-on: arc-linux-latest-dind
|
|
||||||
steps:
|
|
||||||
- name: Login to Harbor
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: harbor.nymte.ch
|
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
|
||||||
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Configure git identity
|
|
||||||
run: |
|
|
||||||
git config --global user.email "lawrence@nymtech.net"
|
|
||||||
git config --global user.name "Lawrence Stalder"
|
|
||||||
|
|
||||||
- name: Get version from Cargo.toml
|
|
||||||
id: get_version
|
|
||||||
run: |
|
|
||||||
VERSION=$(yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml)
|
|
||||||
echo "result=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Initialize RELEASE_TAG
|
|
||||||
run: echo "RELEASE_TAG=" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set RELEASE_TAG for release
|
|
||||||
if: github.event.inputs.release_image == 'true'
|
|
||||||
run: echo "RELEASE_TAG=golden-" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set IMAGE_NAME_AND_TAGS variable
|
|
||||||
run: echo "IMAGE_NAME_AND_TAGS=${{ env.CONTAINER_NAME }}:${{ env.RELEASE_TAG }}${{ steps.get_version.outputs.result }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Log image name
|
|
||||||
run: echo "RELEASE_TAG='$RELEASE_TAG' IMAGE_NAME_AND_TAGS='$IMAGE_NAME_AND_TAGS'"
|
|
||||||
|
|
||||||
- name: Build and push image to Harbor
|
|
||||||
run: |
|
|
||||||
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.IMAGE_NAME_AND_TAGS }}
|
|
||||||
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
|
|
||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-ubuntu-22.04-dind
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
runs-on: arc-linux-latest-dind
|
runs-on: arc-linux-latest-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
runs-on: arc-linux-latest-dind
|
runs-on: arc-linux-latest-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-ubuntu-22.04-dind
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-ubuntu-22.04-dind
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-linux-latest-dind
|
runs-on: arc-linux-latest-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: arc-ubuntu-22.04-dind
|
runs-on: arc-ubuntu-22.04-dind
|
||||||
steps:
|
steps:
|
||||||
- name: Login to Harbor
|
- name: Login to Harbor
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: harbor.nymte.ch
|
registry: harbor.nymte.ch
|
||||||
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ jobs:
|
|||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
- uses: nymtech/nym/.github/actions/nym-hash-releases@develop
|
- uses: nymtech/nym/.github/actions/nym-hash-releases@develop
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
release-tag-or-name-or-id: ${{ inputs.release_tag }}
|
release-tag-or-name-or-id: ${{ inputs.release_tag }}
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v7
|
- uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: Asset Hashes
|
name: Asset Hashes
|
||||||
path: hashes.json
|
path: hashes.json
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ jobs:
|
|||||||
- name: Install cargo-workspaces
|
- name: Install cargo-workspaces
|
||||||
run: cargo install cargo-workspaces
|
run: cargo install cargo-workspaces
|
||||||
|
|
||||||
- name: Preflight publish checks
|
|
||||||
run: |
|
|
||||||
python3 tools/internal/check_publish_preflight.py
|
|
||||||
|
|
||||||
- name: Publish remaining crates
|
- name: Publish remaining crates
|
||||||
env:
|
env:
|
||||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ v6-topology.json
|
|||||||
/explorer/public/downloads/mixmining.json
|
/explorer/public/downloads/mixmining.json
|
||||||
/explorer/public/downloads/topology.json
|
/explorer/public/downloads/topology.json
|
||||||
/nym-wallet/dist/*
|
/nym-wallet/dist/*
|
||||||
/nym-wallet/appimage-bundled-graphics-libs.txt
|
|
||||||
/clients/validator/examples/nym-driver-example/current-contract.txt
|
/clients/validator/examples/nym-driver-example/current-contract.txt
|
||||||
validator-api/v4.json
|
validator-api/v4.json
|
||||||
validator-api/v6.json
|
validator-api/v6.json
|
||||||
@@ -78,8 +77,3 @@ CLAUDE.md
|
|||||||
|
|
||||||
/notes
|
/notes
|
||||||
/target-otel
|
/target-otel
|
||||||
test-tutorials/
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
.pnpm-store/
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
shamefully-hoist=false
|
|
||||||
prefer-workspace-packages=true
|
|
||||||
hoist-pattern[]=*eslint*
|
|
||||||
hoist-pattern[]=*prettier*
|
|
||||||
hoist-pattern[]=*typescript*
|
|
||||||
hoist-pattern[]=*@types*
|
|
||||||
|
|
||||||
auto-install-peers=true
|
|
||||||
strict-peer-dependencies=false
|
|
||||||
-184
@@ -4,190 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [2026.11-xynomizithra] (2026-06-08)
|
|
||||||
|
|
||||||
- bugfix: allow re-inviting expired members ([#6863])
|
|
||||||
- feat: disable Nagle's algorithm for LP between nym-nodes ([#6857])
|
|
||||||
- Keep peer in wg table when updating psk ([#6856])
|
|
||||||
- chore: minor nym-node improvements ([#6850])
|
|
||||||
- chore: LP registration adjustments ([#6845])
|
|
||||||
- crates release: bump version to 1.21.1 ([#6844])
|
|
||||||
- fix gateways being penalised for no stress testing ([#6843])
|
|
||||||
- fix score inflation for throttled nodes ([#6842])
|
|
||||||
- Bugfix/cherry pick/waterloo stres testing floats ([#6841])
|
|
||||||
- bugfix: NMv3 race condition ([#6837])
|
|
||||||
- feat: implement UpdateFamily for the node families contract ([#6834])
|
|
||||||
- Bugfix/cherry pick/waterloo ns api ([#6833])
|
|
||||||
- experiment: attempt to retroactively generate specs for node families and ecash contracts ([#6813])
|
|
||||||
- moving lp packets in lp-data crate ([#6810])
|
|
||||||
- upgrade axum to 0.8.9 (and side deps) ([#6808])
|
|
||||||
- chore: expose admin method for migrating vesting delegations/mixnodes ([#6795])
|
|
||||||
- [chore] fix clippy 1.95 lints for future version update ([#6794])
|
|
||||||
- Handle Rate Limit Challenge Response ([#6786])
|
|
||||||
- NYM-583: Avoid corrupted database on Windows. ([#6785])
|
|
||||||
- Max/smolmix wasm ([#6784])
|
|
||||||
- Chore/bugfixes ([#6783])
|
|
||||||
- Switch from yarn to pnpm ([#6779])
|
|
||||||
- feat: Node Families: expose stake information inside DVpnGateway ([#6778])
|
|
||||||
- feat: Node Families: expose family information for NS API consumers ([#6777])
|
|
||||||
- feat: Node Families: cache and expose family data within nym API ([#6774])
|
|
||||||
- Re-order default API urls for network details ([#6767])
|
|
||||||
- add ci for NM agent binary ([#6764])
|
|
||||||
- feat/refactor: introduce shared contract caches within Nym API ([#6760])
|
|
||||||
- chore: removed dead code for redundant mixnet-vesting integration tests ([#6759])
|
|
||||||
- feat: Node Families: remove nodes upon unbonding ([#6752])
|
|
||||||
- feat: Node Families: contract transactions ([#6750])
|
|
||||||
- feat: Node Families: contract queries ([#6731])
|
|
||||||
- feat: Node Families: initial contract storage ([#6717])
|
|
||||||
- start node families topic branch ([#6715])
|
|
||||||
- Bump rand from 0.8.5 to 0.8.6 in /contracts ([#6702])
|
|
||||||
- Testing port checks in NS Agents ([#6694])
|
|
||||||
- build(deps): bump microsoft/setup-msbuild from 2 to 3 ([#6602])
|
|
||||||
- build(deps): bump tar from 0.4.44 to 0.4.45 ([#6595])
|
|
||||||
- build(deps): bump quinn-proto from 0.11.12 to 0.11.14 ([#6549])
|
|
||||||
- build(deps): bump docker/login-action from 3 to 4 ([#6518])
|
|
||||||
- build(deps): bump actions/download-artifact from 7 to 8 ([#6497])
|
|
||||||
- build(deps): bump actions/upload-artifact from 6 to 7 ([#6496])
|
|
||||||
|
|
||||||
[#6863]: https://github.com/nymtech/nym/pull/6863
|
|
||||||
[#6857]: https://github.com/nymtech/nym/pull/6857
|
|
||||||
[#6856]: https://github.com/nymtech/nym/pull/6856
|
|
||||||
[#6850]: https://github.com/nymtech/nym/pull/6850
|
|
||||||
[#6845]: https://github.com/nymtech/nym/pull/6845
|
|
||||||
[#6844]: https://github.com/nymtech/nym/pull/6844
|
|
||||||
[#6843]: https://github.com/nymtech/nym/pull/6843
|
|
||||||
[#6842]: https://github.com/nymtech/nym/pull/6842
|
|
||||||
[#6841]: https://github.com/nymtech/nym/pull/6841
|
|
||||||
[#6837]: https://github.com/nymtech/nym/pull/6837
|
|
||||||
[#6834]: https://github.com/nymtech/nym/pull/6834
|
|
||||||
[#6833]: https://github.com/nymtech/nym/pull/6833
|
|
||||||
[#6813]: https://github.com/nymtech/nym/pull/6813
|
|
||||||
[#6810]: https://github.com/nymtech/nym/pull/6810
|
|
||||||
[#6808]: https://github.com/nymtech/nym/pull/6808
|
|
||||||
[#6795]: https://github.com/nymtech/nym/pull/6795
|
|
||||||
[#6794]: https://github.com/nymtech/nym/pull/6794
|
|
||||||
[#6786]: https://github.com/nymtech/nym/pull/6786
|
|
||||||
[#6785]: https://github.com/nymtech/nym/pull/6785
|
|
||||||
[#6784]: https://github.com/nymtech/nym/pull/6784
|
|
||||||
[#6783]: https://github.com/nymtech/nym/pull/6783
|
|
||||||
[#6779]: https://github.com/nymtech/nym/pull/6779
|
|
||||||
[#6778]: https://github.com/nymtech/nym/pull/6778
|
|
||||||
[#6777]: https://github.com/nymtech/nym/pull/6777
|
|
||||||
[#6774]: https://github.com/nymtech/nym/pull/6774
|
|
||||||
[#6767]: https://github.com/nymtech/nym/pull/6767
|
|
||||||
[#6764]: https://github.com/nymtech/nym/pull/6764
|
|
||||||
[#6760]: https://github.com/nymtech/nym/pull/6760
|
|
||||||
[#6759]: https://github.com/nymtech/nym/pull/6759
|
|
||||||
[#6752]: https://github.com/nymtech/nym/pull/6752
|
|
||||||
[#6750]: https://github.com/nymtech/nym/pull/6750
|
|
||||||
[#6731]: https://github.com/nymtech/nym/pull/6731
|
|
||||||
[#6717]: https://github.com/nymtech/nym/pull/6717
|
|
||||||
[#6715]: https://github.com/nymtech/nym/pull/6715
|
|
||||||
[#6702]: https://github.com/nymtech/nym/pull/6702
|
|
||||||
[#6694]: https://github.com/nymtech/nym/pull/6694
|
|
||||||
[#6602]: https://github.com/nymtech/nym/pull/6602
|
|
||||||
[#6595]: https://github.com/nymtech/nym/pull/6595
|
|
||||||
[#6549]: https://github.com/nymtech/nym/pull/6549
|
|
||||||
[#6518]: https://github.com/nymtech/nym/pull/6518
|
|
||||||
[#6497]: https://github.com/nymtech/nym/pull/6497
|
|
||||||
[#6496]: https://github.com/nymtech/nym/pull/6496
|
|
||||||
|
|
||||||
## [2026.10-waterloo] (2026-05-27)
|
|
||||||
|
|
||||||
- Re-order default API urls for network details - Waterloo release ([#6799])
|
|
||||||
- [bugfix] IPR v8<->v9 mismatch on Waterloo ([#6772])
|
|
||||||
- Migrate to hickory 0.26.1 ([#6751])
|
|
||||||
- add workflows for NM3 ([#6729])
|
|
||||||
- credential proxy pool ([#6726])
|
|
||||||
- chore: made sphinx version threshold assertion a compile time check ([#6718])
|
|
||||||
- Feat/nmv3 updated performance calculation ([#6714])
|
|
||||||
- feat: NMv3: submission of stress testing result into nym-api ([#6709])
|
|
||||||
- feat: NMv3: Prometheus metrics for network monitor ([#6693])
|
|
||||||
- feat: NMv3: add read-only results API to orchestrator ([#6689])
|
|
||||||
- feat: NMv3: Eviction of stale testrun data ([#6685])
|
|
||||||
- feat: NMv3: Wire up testrun assignment and result submission flow ([#6680])
|
|
||||||
- feat: NMv3: Support multiple network monitor agents per host ([#6679])
|
|
||||||
- Feat/nmv3 agent announcement ([#6673])
|
|
||||||
- add node refresher for periodic scraping of bonded nym-node details ([#6626])
|
|
||||||
- Feat/nmv3 orchestrator queue ([#6597])
|
|
||||||
- feat: network monitor agent - standalone node stress-testing ([#6582])
|
|
||||||
- [feat] propagate NM agent noise keys to nym-node routing ([#6577])
|
|
||||||
- start mix stress testing topic branch ([#6575])
|
|
||||||
- Feat/nmv3 agents subscription ([#6567])
|
|
||||||
- Feat/nmv3 agents contract ([#6555])
|
|
||||||
|
|
||||||
[#6799]: https://github.com/nymtech/nym/pull/6799
|
|
||||||
[#6772]: https://github.com/nymtech/nym/pull/6772
|
|
||||||
[#6751]: https://github.com/nymtech/nym/pull/6751
|
|
||||||
[#6729]: https://github.com/nymtech/nym/pull/6729
|
|
||||||
[#6726]: https://github.com/nymtech/nym/pull/6726
|
|
||||||
[#6718]: https://github.com/nymtech/nym/pull/6718
|
|
||||||
[#6714]: https://github.com/nymtech/nym/pull/6714
|
|
||||||
[#6709]: https://github.com/nymtech/nym/pull/6709
|
|
||||||
[#6693]: https://github.com/nymtech/nym/pull/6693
|
|
||||||
[#6689]: https://github.com/nymtech/nym/pull/6689
|
|
||||||
[#6685]: https://github.com/nymtech/nym/pull/6685
|
|
||||||
[#6680]: https://github.com/nymtech/nym/pull/6680
|
|
||||||
[#6679]: https://github.com/nymtech/nym/pull/6679
|
|
||||||
[#6673]: https://github.com/nymtech/nym/pull/6673
|
|
||||||
[#6626]: https://github.com/nymtech/nym/pull/6626
|
|
||||||
[#6597]: https://github.com/nymtech/nym/pull/6597
|
|
||||||
[#6582]: https://github.com/nymtech/nym/pull/6582
|
|
||||||
[#6577]: https://github.com/nymtech/nym/pull/6577
|
|
||||||
[#6575]: https://github.com/nymtech/nym/pull/6575
|
|
||||||
[#6567]: https://github.com/nymtech/nym/pull/6567
|
|
||||||
[#6555]: https://github.com/nymtech/nym/pull/6555
|
|
||||||
|
|
||||||
## [2026.9-venaco] (2026-05-06)
|
|
||||||
|
|
||||||
- Fix for v9 IPR ([#6710])
|
|
||||||
- Only init SHARED_CLIENT if requested ([#6708])
|
|
||||||
- Fixes to crates and CI ([#6686])
|
|
||||||
- Return ipv6 addresses as well ([#6684])
|
|
||||||
- Fix invalid ticket spend ([#6683])
|
|
||||||
- Block non-public IPR/NR checks ([#6670])
|
|
||||||
|
|
||||||
[#6710]: https://github.com/nymtech/nym/pull/6710
|
|
||||||
[#6708]: https://github.com/nymtech/nym/pull/6708
|
|
||||||
[#6686]: https://github.com/nymtech/nym/pull/6686
|
|
||||||
[#6684]: https://github.com/nymtech/nym/pull/6684
|
|
||||||
[#6683]: https://github.com/nymtech/nym/pull/6683
|
|
||||||
[#6670]: https://github.com/nymtech/nym/pull/6670
|
|
||||||
|
|
||||||
## [2026.8-urda] (2026-04-20)
|
|
||||||
|
|
||||||
- Include all gateways in the returned list ([#6649])
|
|
||||||
- Optimize GW probe in NS agent ([#6636])
|
|
||||||
- Max/sdk docrs ([#6566])
|
|
||||||
- Max/sdk stream wrapper ([#6320])
|
|
||||||
|
|
||||||
[#6649]: https://github.com/nymtech/nym/pull/6649
|
|
||||||
[#6636]: https://github.com/nymtech/nym/pull/6636
|
|
||||||
[#6566]: https://github.com/nymtech/nym/pull/6566
|
|
||||||
[#6320]: https://github.com/nymtech/nym/pull/6320
|
|
||||||
|
|
||||||
## [2026.7-tola] (2026-04-07)
|
|
||||||
|
|
||||||
- Simon/ecash contract serde fix ([#6634])
|
|
||||||
- Update Fallback IP for Nym API ([#6622])
|
|
||||||
- Nym Node spam logging ([#6621])
|
|
||||||
- feat: multiple deposit prices ([#6608])
|
|
||||||
- move format_debug_bytes in common crate ([#6580])
|
|
||||||
- bugfix: make sure client keys are generated before requesting credentials ([#6579])
|
|
||||||
- Fix socks5 GW probe regression ([#6576])
|
|
||||||
- Max/lp stream framing ([#6573])
|
|
||||||
- HTTP domain rotation conditions ([#6570])
|
|
||||||
|
|
||||||
[#6634]: https://github.com/nymtech/nym/pull/6634
|
|
||||||
[#6622]: https://github.com/nymtech/nym/pull/6622
|
|
||||||
[#6621]: https://github.com/nymtech/nym/pull/6621
|
|
||||||
[#6608]: https://github.com/nymtech/nym/pull/6608
|
|
||||||
[#6580]: https://github.com/nymtech/nym/pull/6580
|
|
||||||
[#6579]: https://github.com/nymtech/nym/pull/6579
|
|
||||||
[#6576]: https://github.com/nymtech/nym/pull/6576
|
|
||||||
[#6573]: https://github.com/nymtech/nym/pull/6573
|
|
||||||
[#6570]: https://github.com/nymtech/nym/pull/6570
|
|
||||||
|
|
||||||
## [2026.6-stilton] (2026-03-25)
|
## [2026.6-stilton] (2026-03-25)
|
||||||
|
|
||||||
- lp fixes ([#6601])
|
- lp fixes ([#6601])
|
||||||
|
|||||||
Generated
+2163
-2695
File diff suppressed because it is too large
Load Diff
+153
-172
@@ -31,6 +31,7 @@ members = [
|
|||||||
"common/client-libs/mixnet-client",
|
"common/client-libs/mixnet-client",
|
||||||
"common/client-libs/validator-client",
|
"common/client-libs/validator-client",
|
||||||
"common/commands",
|
"common/commands",
|
||||||
|
"common/nym-common",
|
||||||
"common/config",
|
"common/config",
|
||||||
"common/cosmwasm-smart-contracts/coconut-dkg",
|
"common/cosmwasm-smart-contracts/coconut-dkg",
|
||||||
"common/cosmwasm-smart-contracts/contracts-common",
|
"common/cosmwasm-smart-contracts/contracts-common",
|
||||||
@@ -40,11 +41,9 @@ members = [
|
|||||||
"common/cosmwasm-smart-contracts/group-contract",
|
"common/cosmwasm-smart-contracts/group-contract",
|
||||||
"common/cosmwasm-smart-contracts/mixnet-contract",
|
"common/cosmwasm-smart-contracts/mixnet-contract",
|
||||||
"common/cosmwasm-smart-contracts/multisig-contract",
|
"common/cosmwasm-smart-contracts/multisig-contract",
|
||||||
"common/cosmwasm-smart-contracts/node-families-contract",
|
|
||||||
"common/cosmwasm-smart-contracts/nym-performance-contract",
|
"common/cosmwasm-smart-contracts/nym-performance-contract",
|
||||||
"common/cosmwasm-smart-contracts/nym-pool-contract",
|
"common/cosmwasm-smart-contracts/nym-pool-contract",
|
||||||
"common/cosmwasm-smart-contracts/vesting-contract",
|
"common/cosmwasm-smart-contracts/vesting-contract",
|
||||||
"common/cosmwasm-smart-contracts/network-monitors-contract",
|
|
||||||
"common/credential-proxy",
|
"common/credential-proxy",
|
||||||
"common/credential-storage",
|
"common/credential-storage",
|
||||||
"common/credential-utils",
|
"common/credential-utils",
|
||||||
@@ -71,15 +70,11 @@ members = [
|
|||||||
"common/node-tester-utils",
|
"common/node-tester-utils",
|
||||||
"common/nonexhaustive-delayqueue",
|
"common/nonexhaustive-delayqueue",
|
||||||
"common/nym-cache",
|
"common/nym-cache",
|
||||||
"common/nym-common",
|
|
||||||
"common/nym-connection-monitor",
|
"common/nym-connection-monitor",
|
||||||
"common/nym-id",
|
"common/nym-id",
|
||||||
"common/nym-kcp",
|
"common/nym-kcp",
|
||||||
"common/nym-kkt",
|
|
||||||
"common/nym-kkt-ciphersuite",
|
|
||||||
"common/nym-kkt-context",
|
|
||||||
"common/nym-lp",
|
"common/nym-lp",
|
||||||
"common/nym-lp-data",
|
"common/nym-kkt",
|
||||||
"common/nym-metrics",
|
"common/nym-metrics",
|
||||||
"common/nym_offline_compact_ecash",
|
"common/nym_offline_compact_ecash",
|
||||||
"common/nymnoise",
|
"common/nymnoise",
|
||||||
@@ -95,9 +90,9 @@ members = [
|
|||||||
"common/nymsphinx/params",
|
"common/nymsphinx/params",
|
||||||
"common/nymsphinx/routing",
|
"common/nymsphinx/routing",
|
||||||
"common/nymsphinx/types",
|
"common/nymsphinx/types",
|
||||||
|
"common/nyxd-scraper-sqlite",
|
||||||
"common/nyxd-scraper-psql",
|
"common/nyxd-scraper-psql",
|
||||||
"common/nyxd-scraper-shared",
|
"common/nyxd-scraper-shared",
|
||||||
"common/nyxd-scraper-sqlite",
|
|
||||||
"common/pemstore",
|
"common/pemstore",
|
||||||
"common/registration",
|
"common/registration",
|
||||||
"common/serde-helpers",
|
"common/serde-helpers",
|
||||||
@@ -127,14 +122,13 @@ members = [
|
|||||||
"common/zulip-client",
|
"common/zulip-client",
|
||||||
"documentation/autodoc",
|
"documentation/autodoc",
|
||||||
"gateway",
|
"gateway",
|
||||||
"integration-tests",
|
|
||||||
"nym-api",
|
"nym-api",
|
||||||
"nym-api/nym-api-requests",
|
"nym-api/nym-api-requests",
|
||||||
"nym-authenticator-client",
|
"nym-authenticator-client",
|
||||||
|
"nym-browser-extension/storage",
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
"nym-credential-proxy/nym-credential-proxy",
|
||||||
"nym-credential-proxy/nym-credential-proxy-requests",
|
"nym-credential-proxy/nym-credential-proxy-requests",
|
||||||
"nym-data-observatory",
|
"nym-data-observatory",
|
||||||
"nym-gateway-probe",
|
|
||||||
"nym-ip-packet-client",
|
"nym-ip-packet-client",
|
||||||
"nym-network-monitor",
|
"nym-network-monitor",
|
||||||
"nym-node",
|
"nym-node",
|
||||||
@@ -146,7 +140,6 @@ members = [
|
|||||||
"nym-outfox",
|
"nym-outfox",
|
||||||
"nym-registration-client",
|
"nym-registration-client",
|
||||||
"nym-signers-monitor",
|
"nym-signers-monitor",
|
||||||
"nym-sqlx-pool-guard",
|
|
||||||
"nym-statistics-api",
|
"nym-statistics-api",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nyx-chain-watcher",
|
"nyx-chain-watcher",
|
||||||
@@ -157,15 +150,15 @@ members = [
|
|||||||
"service-providers/common",
|
"service-providers/common",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"smolmix/core",
|
"nym-sqlx-pool-guard",
|
||||||
"tools/echo-server",
|
"tools/echo-server",
|
||||||
"tools/internal/contract-state-importer/importer-cli",
|
"tools/internal/contract-state-importer/importer-cli",
|
||||||
"tools/internal/contract-state-importer/importer-contract",
|
"tools/internal/contract-state-importer/importer-contract",
|
||||||
"tools/internal/localnet-orchestrator",
|
|
||||||
"tools/internal/localnet-orchestrator/dkg-bypass-contract",
|
|
||||||
"tools/internal/mixnet-connectivity-check",
|
"tools/internal/mixnet-connectivity-check",
|
||||||
# "tools/internal/sdk-version-bump",
|
# "tools/internal/sdk-version-bump",
|
||||||
"tools/internal/ssl-inject",
|
"tools/internal/ssl-inject",
|
||||||
|
"tools/internal/localnet-orchestrator",
|
||||||
|
"tools/internal/localnet-orchestrator/dkg-bypass-contract",
|
||||||
"tools/internal/validator-status-check",
|
"tools/internal/validator-status-check",
|
||||||
"tools/nym-cli",
|
"tools/nym-cli",
|
||||||
"tools/nym-id-cli",
|
"tools/nym-id-cli",
|
||||||
@@ -174,31 +167,32 @@ members = [
|
|||||||
"tools/nymvisor",
|
"tools/nymvisor",
|
||||||
"tools/ts-rs-cli",
|
"tools/ts-rs-cli",
|
||||||
"wasm/client",
|
"wasm/client",
|
||||||
|
# "wasm/full-nym-wasm", # If we uncomment this again, remember to also uncomment the profile settings below
|
||||||
"wasm/mix-fetch",
|
"wasm/mix-fetch",
|
||||||
"wasm/smolmix",
|
"wasm/node-tester",
|
||||||
"wasm/zknym-lib",
|
"wasm/zknym-lib",
|
||||||
"nym-network-monitor-v3/nym-network-monitor-orchestrator",
|
"nym-gateway-probe",
|
||||||
"nym-network-monitor-v3/nym-network-monitor-agent",
|
"integration-tests",
|
||||||
"nym-network-monitor-v3/nym-network-monitor-orchestrator-requests",
|
"common/nym-kkt-ciphersuite",
|
||||||
|
"common/nym-kkt-context",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
"clients/native",
|
"clients/native",
|
||||||
"clients/socks5",
|
"clients/socks5",
|
||||||
"nym-api",
|
|
||||||
"nym-authenticator-client",
|
"nym-authenticator-client",
|
||||||
|
"nym-api",
|
||||||
"nym-credential-proxy/nym-credential-proxy",
|
"nym-credential-proxy/nym-credential-proxy",
|
||||||
"nym-node",
|
"nym-node",
|
||||||
"nym-registration-client",
|
"nym-node-status-api/nym-node-status-agent",
|
||||||
"nym-statistics-api",
|
"nym-statistics-api",
|
||||||
"nym-validator-rewarder",
|
"nym-validator-rewarder",
|
||||||
"nyx-chain-watcher",
|
"nyx-chain-watcher",
|
||||||
"service-providers/ip-packet-router",
|
"service-providers/ip-packet-router",
|
||||||
"service-providers/network-requester",
|
"service-providers/network-requester",
|
||||||
"tools/internal/localnet-orchestrator",
|
|
||||||
"tools/nymvisor",
|
"tools/nymvisor",
|
||||||
"nym-network-monitor-v3/nym-network-monitor-orchestrator",
|
"nym-registration-client",
|
||||||
"nym-network-monitor-v3/nym-network-monitor-agent",
|
"tools/internal/localnet-orchestrator"
|
||||||
]
|
]
|
||||||
|
|
||||||
exclude = ["contracts", "nym-wallet", "cpu-cycles"]
|
exclude = ["contracts", "nym-wallet", "cpu-cycles"]
|
||||||
@@ -212,7 +206,7 @@ edition = "2024"
|
|||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
rust-version = "1.87.0"
|
rust-version = "1.87.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
version = "1.21.1"
|
version = "1.20.4"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
addr = "0.15.6"
|
addr = "0.15.6"
|
||||||
@@ -226,17 +220,16 @@ anyhow = "1.0.98"
|
|||||||
arc-swap = "1.7.1"
|
arc-swap = "1.7.1"
|
||||||
argon2 = "0.5.0"
|
argon2 = "0.5.0"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.88"
|
||||||
async-tungstenite = { version = "0.24", default-features = false }
|
axum = "0.7.5"
|
||||||
axum = "0.8.9"
|
axum-client-ip = "0.6.1"
|
||||||
axum-client-ip = "1.3.1"
|
axum-extra = "0.9.4"
|
||||||
axum-extra = "0.12.6"
|
axum-test = "16.2.0"
|
||||||
axum-test = "20.0.0"
|
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
base85rs = "0.1.3"
|
base85rs = "0.1.3"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||||
bitvec = "1.0.0"
|
bitvec = "1.0.0"
|
||||||
blake3 = ">=1.7, <1.8.4" # blake3 1.8.4+ requires digest 0.11; workspace is on 0.10
|
blake3 = "1.7.0"
|
||||||
bloomfilter = "3.0.1"
|
bloomfilter = "3.0.1"
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
bytecodec = "0.4.15"
|
bytecodec = "0.4.15"
|
||||||
@@ -255,7 +248,7 @@ clap_complete_fig = "4.5"
|
|||||||
colored = "2.2"
|
colored = "2.2"
|
||||||
comfy-table = "7.1.4"
|
comfy-table = "7.1.4"
|
||||||
console = "0.16.0"
|
console = "0.16.0"
|
||||||
console-subscriber = "0.5.0"
|
console-subscriber = "0.4.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
const-str = "0.5.6"
|
const-str = "0.5.6"
|
||||||
const_format = "0.2.34"
|
const_format = "0.2.34"
|
||||||
@@ -280,27 +273,23 @@ eyre = "0.6.9"
|
|||||||
fastrand = "2.1.1"
|
fastrand = "2.1.1"
|
||||||
flate2 = "1.1.1"
|
flate2 = "1.1.1"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
futures-rustls = { version = "0.26", default-features = false }
|
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
generic-array = "0.14.7"
|
generic-array = "0.14.7"
|
||||||
getrandom = "0.2.10"
|
getrandom = "0.2.10"
|
||||||
getrandom03 = { package = "getrandom", version = "=0.3.3" }
|
getrandom03 = { package = "getrandom", version = "=0.3.3" }
|
||||||
getrandom04 = { package = "getrandom", version = "0.4" }
|
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
handlebars = "3.5.5"
|
handlebars = "3.5.5"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
hickory-proto = { version = "0.26.1", default-features = false }
|
hickory-resolver = "0.25.2"
|
||||||
hickory-resolver = "0.26.1"
|
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
http = "1"
|
http = "1"
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
httparse = "1.10"
|
|
||||||
httpcodec = "0.2.3"
|
httpcodec = "0.2.3"
|
||||||
human-repr = "1.1.0"
|
human-repr = "1.1.0"
|
||||||
humantime = "2.2.0"
|
humantime = "2.2.0"
|
||||||
humantime-serde = "1.1.1"
|
humantime-serde = "1.1.1"
|
||||||
hyper = { version = "1.6.0", default-features = false }
|
hyper = "1.6.0"
|
||||||
hyper-util = "0.1"
|
hyper-util = "0.1"
|
||||||
indicatif = "0.18.0"
|
indicatif = "0.18.0"
|
||||||
inquire = "0.6.2"
|
inquire = "0.6.2"
|
||||||
@@ -335,7 +324,7 @@ pnet_packet = "0.35.0"
|
|||||||
publicsuffix = "2.3.0"
|
publicsuffix = "2.3.0"
|
||||||
proc_pidinfo = "0.1.3"
|
proc_pidinfo = "0.1.3"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
rand = "0.8.6"
|
rand = "0.8.5"
|
||||||
rand09 = { package = "rand", version = "=0.9.2" }
|
rand09 = { package = "rand", version = "=0.9.2" }
|
||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
rand_chacha09 = { package = "rand_chacha", version = "=0.9.0" }
|
rand_chacha09 = { package = "rand_chacha", version = "=0.9.0" }
|
||||||
@@ -346,14 +335,12 @@ regex = "1.10.6"
|
|||||||
reqwest = { version = "0.13.1", default-features = false }
|
reqwest = { version = "0.13.1", default-features = false }
|
||||||
rs_merkle = "1.5.0"
|
rs_merkle = "1.5.0"
|
||||||
rustls = { version = "0.23.37", default-features = false }
|
rustls = { version = "0.23.37", default-features = false }
|
||||||
rustls-pki-types = "1"
|
|
||||||
rustls-rustcrypto = "0.0.2-alpha"
|
|
||||||
schemars = "0.8.22"
|
schemars = "0.8.22"
|
||||||
semver = "1.0.26"
|
semver = "1.0.26"
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
serde_bytes = "0.11.17"
|
serde_bytes = "0.11.17"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = { version = "1.0.140", features = ["float_roundtrip"] }
|
serde_json = "1.0.140"
|
||||||
serde_json_path = "0.7.2"
|
serde_json_path = "0.7.2"
|
||||||
serde_repr = "0.1"
|
serde_repr = "0.1"
|
||||||
serde_with = "3.9.0"
|
serde_with = "3.9.0"
|
||||||
@@ -361,8 +348,6 @@ serde_yaml = "0.9.25"
|
|||||||
serde_plain = "1.0.2"
|
serde_plain = "1.0.2"
|
||||||
sha2 = "0.10.3"
|
sha2 = "0.10.3"
|
||||||
si-scale = "0.2.3"
|
si-scale = "0.2.3"
|
||||||
simple-dns = "0.7"
|
|
||||||
smoltcp = "0.12"
|
|
||||||
snow = "0.9.6"
|
snow = "0.9.6"
|
||||||
sphinx-packet = "=0.6.0"
|
sphinx-packet = "=0.6.0"
|
||||||
sqlx = "0.8.6"
|
sqlx = "0.8.6"
|
||||||
@@ -372,7 +357,7 @@ subtle-encoding = "0.5"
|
|||||||
syn = "2"
|
syn = "2"
|
||||||
sysinfo = "0.37.0"
|
sysinfo = "0.37.0"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
tar = "0.4.45"
|
tar = "0.4.44"
|
||||||
test-with = { version = "0.15.4", default-features = false }
|
test-with = { version = "0.15.4", default-features = false }
|
||||||
tempfile = "3.20"
|
tempfile = "3.20"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
@@ -383,9 +368,7 @@ tokio-postgres = "0.7"
|
|||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.17"
|
||||||
tokio-test = "0.4.4"
|
tokio-test = "0.4.4"
|
||||||
tokio-tun = "0.11.5"
|
tokio-tun = "0.11.5"
|
||||||
tokio-rustls = "0.26"
|
tokio-tungstenite = { version = "0.20.1" }
|
||||||
tokio-smoltcp = "0.5"
|
|
||||||
tokio-tungstenite = "0.20.1"
|
|
||||||
tokio-util = "0.7.15"
|
tokio-util = "0.7.15"
|
||||||
toml = "0.8.22"
|
toml = "0.8.22"
|
||||||
tower = "0.5.2"
|
tower = "0.5.2"
|
||||||
@@ -403,141 +386,133 @@ uniffi = "0.29.2"
|
|||||||
uniffi_build = "0.29.0"
|
uniffi_build = "0.29.0"
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
utoipa = "5.2"
|
utoipa = "5.2"
|
||||||
utoipa-swagger-ui = "9.0.2"
|
utoipa-swagger-ui = "8.1"
|
||||||
utoipauto = "0.2"
|
utoipauto = "0.2"
|
||||||
uuid = "1.19.0"
|
uuid = "1.19.0"
|
||||||
vergen = { version = "=8.3.1", default-features = false }
|
vergen = { version = "=8.3.1", default-features = false }
|
||||||
|
vergen-gitcl = { version = "1.0.8", default-features = false }
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
zeroize = "1.7.0"
|
zeroize = "1.7.0"
|
||||||
|
|
||||||
prometheus = { version = "0.14.0" }
|
prometheus = { version = "0.14.0" }
|
||||||
|
|
||||||
# recreating lioness
|
|
||||||
# we don't care about particular versions - just pull whatever is used by sphinx
|
|
||||||
lioness = "*"
|
|
||||||
arrayref = "*"
|
|
||||||
|
|
||||||
# libcrux
|
# libcrux
|
||||||
libcrux-kem = "0.0.7"
|
libcrux-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-ecdh = "0.0.6"
|
libcrux-ecdh = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-curve25519 = "0.0.6"
|
libcrux-curve25519 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-chacha20poly1305 = "0.0.7"
|
libcrux-chacha20poly1305 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-psq = "0.0.8"
|
libcrux-psq = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-ml-kem = "0.0.8"
|
libcrux-ml-kem = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-sha3 = "0.0.8"
|
libcrux-sha3 = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
libcrux-traits = "0.0.6"
|
libcrux-traits = { git = "https://github.com/cryspen/libcrux", rev = "b17f8687b67cdcfc10b55aeecc998bbbca28f775" }
|
||||||
|
|
||||||
# Workspace dep definitions required by crates.io publication - we need a workspace version since `cargo workspaces` doesn't work with path imports from crate manifests
|
# Workspace dep definitions required by crates.io publication - we need a workspace version since `cargo workspaces` doesn't work with path imports from crate manifests
|
||||||
nym-api-requests = { version = "1.21.1", path = "nym-api/nym-api-requests" }
|
nym-api-requests = { version = "1.20.4", path = "nym-api/nym-api-requests" }
|
||||||
nym-authenticator-requests = { version = "1.21.1", path = "common/authenticator-requests" }
|
nym-authenticator-requests = { version = "1.20.4", path = "common/authenticator-requests" }
|
||||||
nym-async-file-watcher = { version = "1.21.1", path = "common/async-file-watcher" }
|
nym-async-file-watcher = { version = "1.20.4", path = "common/async-file-watcher" }
|
||||||
nym-authenticator-client = { version = "1.21.1", path = "nym-authenticator-client" }
|
nym-authenticator-client = { version = "1.20.4", path = "nym-authenticator-client" }
|
||||||
nym-bandwidth-controller = { version = "1.21.1", path = "common/bandwidth-controller" }
|
nym-bandwidth-controller = { version = "1.20.4", path = "common/bandwidth-controller" }
|
||||||
nym-bin-common = { version = "1.21.1", path = "common/bin-common" }
|
nym-bin-common = { version = "1.20.4", path = "common/bin-common" }
|
||||||
nym-cache = { version = "1.21.1", path = "common/nym-cache" }
|
nym-cache = { version = "1.20.4", path = "common/nym-cache" }
|
||||||
nym-client-core = { version = "1.21.1", path = "common/client-core", default-features = false }
|
nym-client-core = { version = "1.20.4", path = "common/client-core", default-features = false }
|
||||||
nym-client-core-config-types = { version = "1.21.1", path = "common/client-core/config-types" }
|
nym-client-core-config-types = { version = "1.20.4", path = "common/client-core/config-types" }
|
||||||
nym-client-core-gateways-storage = { version = "1.21.1", path = "common/client-core/gateways-storage" }
|
nym-client-core-gateways-storage = { version = "1.20.4", path = "common/client-core/gateways-storage" }
|
||||||
nym-client-core-surb-storage = { version = "1.21.1", path = "common/client-core/surb-storage" }
|
nym-client-core-surb-storage = { version = "1.20.4", path = "common/client-core/surb-storage" }
|
||||||
nym-client-websocket-requests = { version = "1.21.1", path = "clients/native/websocket-requests" }
|
nym-client-websocket-requests = { version = "1.20.4", path = "clients/native/websocket-requests" }
|
||||||
nym-common = { version = "1.21.1", path = "common/nym-common" }
|
nym-common = { version = "1.20.4", path = "common/nym-common" }
|
||||||
nym-compact-ecash = { version = "1.21.1", path = "common/nym_offline_compact_ecash" }
|
nym-compact-ecash = { version = "1.20.4", path = "common/nym_offline_compact_ecash" }
|
||||||
nym-config = { version = "1.21.1", path = "common/config" }
|
nym-config = { version = "1.20.4", path = "common/config" }
|
||||||
nym-contracts-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/contracts-common" }
|
nym-contracts-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/contracts-common" }
|
||||||
nym-coconut-dkg-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/coconut-dkg" }
|
nym-coconut-dkg-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/coconut-dkg" }
|
||||||
nym-credential-storage = { version = "1.21.1", path = "common/credential-storage" }
|
nym-credential-storage = { version = "1.20.4", path = "common/credential-storage" }
|
||||||
nym-credential-utils = { version = "1.21.1", path = "common/credential-utils" }
|
nym-credential-utils = { version = "1.20.4", path = "common/credential-utils" }
|
||||||
nym-credential-proxy-lib = { version = "1.21.1", path = "common/credential-proxy" }
|
nym-credential-proxy-lib = { version = "1.20.4", path = "common/credential-proxy" }
|
||||||
nym-credentials = { version = "1.21.1", path = "common/credentials", default-features = false }
|
nym-credentials = { version = "1.20.4", path = "common/credentials", default-features = false }
|
||||||
nym-credentials-interface = { version = "1.21.1", path = "common/credentials-interface" }
|
nym-credentials-interface = { version = "1.20.4", path = "common/credentials-interface" }
|
||||||
nym-credential-proxy-requests = { version = "1.21.1", path = "nym-credential-proxy/nym-credential-proxy-requests", default-features = false }
|
nym-credential-proxy-requests = { version = "1.20.4", path = "nym-credential-proxy/nym-credential-proxy-requests", default-features = false }
|
||||||
nym-credential-verification = { version = "1.21.1", path = "common/credential-verification" }
|
nym-credential-verification = { version = "1.20.4", path = "common/credential-verification" }
|
||||||
nym-crypto = { version = "1.21.1", path = "common/crypto", default-features = false }
|
nym-crypto = { version = "1.20.4", path = "common/crypto", default-features = false }
|
||||||
nym-dkg = { version = "1.21.1", path = "common/dkg" }
|
nym-dkg = { version = "1.20.4", path = "common/dkg" }
|
||||||
nym-ecash-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/ecash-contract" }
|
nym-ecash-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/ecash-contract" }
|
||||||
nym-ecash-signer-check = { version = "1.21.1", path = "common/ecash-signer-check" }
|
nym-ecash-signer-check = { version = "1.20.4", path = "common/ecash-signer-check" }
|
||||||
nym-ecash-signer-check-types = { version = "1.21.1", path = "common/ecash-signer-check-types" }
|
nym-ecash-signer-check-types = { version = "1.20.4", path = "common/ecash-signer-check-types" }
|
||||||
nym-ecash-time = { version = "1.21.1", path = "common/ecash-time" }
|
nym-ecash-time = { version = "1.20.4", path = "common/ecash-time" }
|
||||||
nym-exit-policy = { version = "1.21.1", path = "common/exit-policy" }
|
nym-exit-policy = { version = "1.20.4", path = "common/exit-policy" }
|
||||||
nym-ffi-shared = { version = "1.21.1", path = "sdk/ffi/shared" }
|
nym-ffi-shared = { version = "1.20.4", path = "sdk/ffi/shared" }
|
||||||
nym-gateway-client = { version = "1.21.1", path = "common/client-libs/gateway-client", default-features = false }
|
nym-gateway-client = { version = "1.20.4", path = "common/client-libs/gateway-client", default-features = false }
|
||||||
nym-gateway-probe = { version = "1.21.1", path = "nym-gateway-probe" }
|
nym-gateway-probe = { version = "1.18.0", path = "nym-gateway-probe" }
|
||||||
nym-gateway-requests = { version = "1.21.1", path = "common/gateway-requests" }
|
nym-gateway-requests = { version = "1.20.4", path = "common/gateway-requests" }
|
||||||
nym-gateway-storage = { version = "1.21.1", path = "common/gateway-storage" }
|
nym-gateway-storage = { version = "1.20.4", path = "common/gateway-storage" }
|
||||||
nym-gateway-stats-storage = { version = "1.21.1", path = "common/gateway-stats-storage" }
|
nym-gateway-stats-storage = { version = "1.20.4", path = "common/gateway-stats-storage" }
|
||||||
nym-group-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/group-contract" }
|
nym-group-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/group-contract" }
|
||||||
nym-http-api-client = { version = "1.21.1", path = "common/http-api-client" }
|
nym-http-api-client = { version = "1.20.4", path = "common/http-api-client" }
|
||||||
nym-http-api-client-macro = { version = "1.21.1", path = "common/http-api-client-macro" }
|
nym-http-api-client-macro = { version = "1.20.4", path = "common/http-api-client-macro" }
|
||||||
nym-http-api-common = { version = "1.21.1", path = "common/http-api-common", default-features = false }
|
nym-http-api-common = { version = "1.20.4", path = "common/http-api-common", default-features = false }
|
||||||
nym-id = { version = "1.21.1", path = "common/nym-id" }
|
nym-id = { version = "1.20.4", path = "common/nym-id" }
|
||||||
nym-ip-packet-client = { version = "1.21.1", path = "nym-ip-packet-client" }
|
nym-ip-packet-client = { version = "1.20.4", path = "nym-ip-packet-client" }
|
||||||
nym-ip-packet-requests = { version = "1.21.1", path = "common/ip-packet-requests" }
|
nym-ip-packet-requests = { version = "1.20.4", path = "common/ip-packet-requests" }
|
||||||
nym-lp = { version = "1.21.1", path = "common/nym-lp" }
|
nym-lp = { version = "1.20.4", path = "common/nym-lp" }
|
||||||
nym-lp-data = { version = "1.21.1", path = "common/nym-lp-data" }
|
nym-kkt = { version = "0.1.0", path = "common/nym-kkt" }
|
||||||
nym-kkt = { version = "1.21.1", path = "common/nym-kkt" }
|
nym-kkt-ciphersuite = { version = "1.20.4", path = "common/nym-kkt-ciphersuite" }
|
||||||
nym-kkt-ciphersuite = { version = "1.21.1", path = "common/nym-kkt-ciphersuite" }
|
nym-kkt-context = { version = "1.20.4", path = "common/nym-kkt-context" }
|
||||||
nym-kkt-context = { version = "1.21.1", path = "common/nym-kkt-context" }
|
nym-metrics = { version = "1.20.4", path = "common/nym-metrics" }
|
||||||
nym-metrics = { version = "1.21.1", path = "common/nym-metrics" }
|
nym-mixnet-client = { version = "1.20.4", path = "common/client-libs/mixnet-client" }
|
||||||
nym-mixnet-client = { version = "1.21.1", path = "common/client-libs/mixnet-client" }
|
nym-mixnet-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||||
nym-mixnet-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/mixnet-contract" }
|
nym-multisig-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/multisig-contract" }
|
||||||
nym-multisig-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/multisig-contract" }
|
nym-network-defaults = { version = "1.20.4", path = "common/network-defaults" }
|
||||||
nym-network-defaults = { version = "1.21.1", path = "common/network-defaults" }
|
nym-node-tester-utils = { version = "1.20.4", path = "common/node-tester-utils" }
|
||||||
nym-node-tester-utils = { version = "1.21.1", path = "common/node-tester-utils" }
|
nym-noise = { version = "1.20.4", path = "common/nymnoise" }
|
||||||
nym-noise = { version = "1.21.1", path = "common/nymnoise" }
|
nym-noise-keys = { version = "1.20.4", path = "common/nymnoise/keys" }
|
||||||
nym-noise-keys = { version = "1.21.1", path = "common/nymnoise/keys" }
|
nym-nonexhaustive-delayqueue = { version = "1.20.4", path = "common/nonexhaustive-delayqueue" }
|
||||||
nym-nonexhaustive-delayqueue = { version = "1.21.1", path = "common/nonexhaustive-delayqueue" }
|
nym-node-requests = { version = "1.20.4", path = "nym-node/nym-node-requests", default-features = false }
|
||||||
nym-node-requests = { version = "1.21.1", path = "nym-node/nym-node-requests", default-features = false }
|
nym-node-metrics = { version = "1.20.4", path = "nym-node/nym-node-metrics" }
|
||||||
nym-node-metrics = { version = "1.21.1", path = "nym-node/nym-node-metrics" }
|
nym-ordered-buffer = { version = "1.20.4", path = "common/socks5/ordered-buffer" }
|
||||||
nym-node-families-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/node-families-contract" }
|
nym-outfox = { version = "1.20.4", path = "nym-outfox" }
|
||||||
nym-ordered-buffer = { version = "1.21.1", path = "common/socks5/ordered-buffer" }
|
nym-registration-common = { version = "1.20.4", path = "common/registration" }
|
||||||
nym-outfox = { version = "1.21.1", path = "nym-outfox" }
|
nym-pemstore = { version = "1.20.4", path = "common/pemstore" }
|
||||||
nym-registration-common = { version = "1.21.1", path = "common/registration" }
|
nym-performance-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/nym-performance-contract" }
|
||||||
nym-pemstore = { version = "1.21.1", path = "common/pemstore" }
|
nym-sdk = { version = "1.20.4", path = "sdk/rust/nym-sdk" }
|
||||||
nym-performance-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/nym-performance-contract" }
|
nym-serde-helpers = { version = "1.20.4", path = "common/serde-helpers" }
|
||||||
nym-sdk = { version = "1.21.1", path = "sdk/rust/nym-sdk" }
|
nym-service-providers-common = { version = "1.20.4", path = "service-providers/common" }
|
||||||
nym-serde-helpers = { version = "1.21.1", path = "common/serde-helpers" }
|
nym-service-provider-requests-common = { version = "1.20.4", path = "common/service-provider-requests-common" }
|
||||||
nym-service-providers-common = { version = "1.21.1", path = "service-providers/common" }
|
nym-socks5-client-core = { version = "1.20.4", path = "common/socks5-client-core" }
|
||||||
nym-service-provider-requests-common = { version = "1.21.1", path = "common/service-provider-requests-common" }
|
nym-socks5-proxy-helpers = { version = "1.20.4", path = "common/socks5/proxy-helpers" }
|
||||||
nym-socks5-client-core = { version = "1.21.1", path = "common/socks5-client-core" }
|
nym-socks5-requests = { version = "1.20.4", path = "common/socks5/requests" }
|
||||||
nym-socks5-proxy-helpers = { version = "1.21.1", path = "common/socks5/proxy-helpers" }
|
nym-sphinx = { version = "1.20.4", path = "common/nymsphinx" }
|
||||||
nym-socks5-requests = { version = "1.21.1", path = "common/socks5/requests" }
|
nym-sphinx-acknowledgements = { version = "1.20.4", path = "common/nymsphinx/acknowledgements" }
|
||||||
nym-sphinx = { version = "1.21.1", path = "common/nymsphinx" }
|
nym-sphinx-addressing = { version = "1.20.4", path = "common/nymsphinx/addressing" }
|
||||||
nym-sphinx-acknowledgements = { version = "1.21.1", path = "common/nymsphinx/acknowledgements" }
|
nym-sphinx-anonymous-replies = { version = "1.20.4", path = "common/nymsphinx/anonymous-replies" }
|
||||||
nym-sphinx-addressing = { version = "1.21.1", path = "common/nymsphinx/addressing" }
|
nym-sphinx-chunking = { version = "1.20.4", path = "common/nymsphinx/chunking" }
|
||||||
nym-sphinx-anonymous-replies = { version = "1.21.1", path = "common/nymsphinx/anonymous-replies" }
|
nym-sphinx-cover = { version = "1.20.4", path = "common/nymsphinx/cover" }
|
||||||
nym-sphinx-chunking = { version = "1.21.1", path = "common/nymsphinx/chunking" }
|
nym-sphinx-forwarding = { version = "1.20.4", path = "common/nymsphinx/forwarding" }
|
||||||
nym-sphinx-cover = { version = "1.21.1", path = "common/nymsphinx/cover" }
|
nym-sphinx-framing = { version = "1.20.4", path = "common/nymsphinx/framing" }
|
||||||
nym-sphinx-forwarding = { version = "1.21.1", path = "common/nymsphinx/forwarding" }
|
nym-sphinx-params = { version = "1.20.4", path = "common/nymsphinx/params" }
|
||||||
nym-sphinx-framing = { version = "1.21.1", path = "common/nymsphinx/framing" }
|
nym-sphinx-routing = { version = "1.20.4", path = "common/nymsphinx/routing" }
|
||||||
nym-sphinx-params = { version = "1.21.1", path = "common/nymsphinx/params" }
|
nym-sphinx-types = { version = "1.20.4", path = "common/nymsphinx/types" }
|
||||||
nym-sphinx-routing = { version = "1.21.1", path = "common/nymsphinx/routing" }
|
nym-statistics-common = { version = "1.20.4", path = "common/statistics" }
|
||||||
nym-sphinx-types = { version = "1.21.1", path = "common/nymsphinx/types" }
|
nym-store-cipher = { version = "1.20.4", path = "common/store-cipher" }
|
||||||
nym-statistics-common = { version = "1.21.1", path = "common/statistics" }
|
nym-task = { version = "1.20.4", path = "common/task" }
|
||||||
nym-store-cipher = { version = "1.21.1", path = "common/store-cipher" }
|
nym-tun = { version = "1.20.4", path = "common/tun" }
|
||||||
nym-task = { version = "1.21.1", path = "common/task" }
|
nym-test-utils = { version = "1.20.4", path = "common/test-utils" }
|
||||||
nym-tun = { version = "1.21.1", path = "common/tun" }
|
nym-ticketbooks-merkle = { version = "1.20.4", path = "common/ticketbooks-merkle" }
|
||||||
nym-test-utils = { version = "1.21.1", path = "common/test-utils" }
|
nym-topology = { version = "1.20.4", path = "common/topology" }
|
||||||
nym-ticketbooks-merkle = { version = "1.21.1", path = "common/ticketbooks-merkle" }
|
nym-types = { version = "1.20.4", path = "common/types" }
|
||||||
nym-topology = { version = "1.21.1", path = "common/topology" }
|
nym-upgrade-mode-check = { version = "1.20.4", path = "common/upgrade-mode-check" }
|
||||||
nym-types = { version = "1.21.1", path = "common/types" }
|
nym-validator-client = { version = "1.20.4", path = "common/client-libs/validator-client", default-features = false }
|
||||||
nym-upgrade-mode-check = { version = "1.21.1", path = "common/upgrade-mode-check" }
|
nym-vesting-contract-common = { version = "1.20.4", path = "common/cosmwasm-smart-contracts/vesting-contract" }
|
||||||
nym-validator-client = { version = "1.21.1", path = "common/client-libs/validator-client", default-features = false }
|
nym-verloc = { version = "1.20.4", path = "common/verloc" }
|
||||||
nym-vesting-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/vesting-contract" }
|
nym-wireguard = { version = "1.20.4", path = "common/wireguard" }
|
||||||
nym-network-monitors-contract-common = { version = "1.21.1", path = "common/cosmwasm-smart-contracts/network-monitors-contract" }
|
nym-wireguard-types = { version = "1.20.4", path = "common/wireguard-types" }
|
||||||
nym-verloc = { version = "1.21.1", path = "common/verloc" }
|
nym-wireguard-private-metadata-shared = { version = "1.20.4", path = "common/wireguard-private-metadata/shared" }
|
||||||
nym-wireguard = { version = "1.21.1", path = "common/wireguard" }
|
nym-wireguard-private-metadata-client = { version = "1.20.4", path = "common/wireguard-private-metadata/client" }
|
||||||
nym-wireguard-types = { version = "1.21.1", path = "common/wireguard-types" }
|
nym-wireguard-private-metadata-server = { version = "1.20.4", path = "common/wireguard-private-metadata/server" }
|
||||||
nym-wireguard-private-metadata-shared = { version = "1.21.1", path = "common/wireguard-private-metadata/shared" }
|
nym-sqlx-pool-guard = { version = "1.2.0", path = "nym-sqlx-pool-guard" }
|
||||||
nym-wireguard-private-metadata-client = { version = "1.21.1", path = "common/wireguard-private-metadata/client" }
|
nym-wasm-client-core = { version = "1.20.4", path = "common/wasm/client-core" }
|
||||||
nym-wireguard-private-metadata-server = { version = "1.21.1", path = "common/wireguard-private-metadata/server" }
|
nym-wasm-storage = { version = "1.20.4", path = "common/wasm/storage" }
|
||||||
nym-sqlx-pool-guard = { version = "1.21.1", path = "nym-sqlx-pool-guard" }
|
nym-wasm-utils = { version = "1.20.4", path = "common/wasm/utils", default-features = false }
|
||||||
nym-wasm-client-core = { version = "1.21.1", path = "common/wasm/client-core" }
|
nyxd-scraper-shared = { version = "1.20.4", path = "common/nyxd-scraper-shared" }
|
||||||
nym-wasm-storage = { version = "1.21.1", path = "common/wasm/storage" }
|
|
||||||
nym-wasm-utils = { version = "1.21.1", path = "common/wasm/utils", default-features = false }
|
|
||||||
nyxd-scraper-shared = { version = "1.21.1", path = "common/nyxd-scraper-shared" }
|
|
||||||
|
|
||||||
smolmix = { version = "1.21.1", path = "smolmix/core" }
|
|
||||||
|
|
||||||
# coconut/DKG related
|
# coconut/DKG related
|
||||||
# unfortunately until https://github.com/zkcrypto/nym-bls12_381-fork/issues/10 is resolved, we have to rely on the fork
|
# unfortunately until https://github.com/zkcrypto/nym-bls12_381-fork/issues/10 is resolved, we have to rely on the fork
|
||||||
@@ -585,7 +560,6 @@ wasm-bindgen = "0.2.99"
|
|||||||
wasm-bindgen-futures = "0.4.49"
|
wasm-bindgen-futures = "0.4.49"
|
||||||
wasm-bindgen-test = "0.3.49"
|
wasm-bindgen-test = "0.3.49"
|
||||||
wasmtimer = "0.4.1"
|
wasmtimer = "0.4.1"
|
||||||
webpki-roots = "0.26"
|
|
||||||
web-sys = "0.3.76"
|
web-sys = "0.3.76"
|
||||||
|
|
||||||
# for local development:
|
# for local development:
|
||||||
@@ -604,11 +578,18 @@ opt-level = 3
|
|||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|
||||||
[profile.release.package.mix-fetch-wasm]
|
[profile.release.package.nym-node-tester-wasm]
|
||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|
||||||
[profile.release.package.smolmix-wasm]
|
# Commented out since the crate is also commented out from the inclusion in the
|
||||||
|
# workspace above. We should uncomment this if we re-include it in the
|
||||||
|
# workspace
|
||||||
|
#[profile.release.package.nym-wasm-sdk]
|
||||||
|
## lto = true
|
||||||
|
#opt-level = 'z'
|
||||||
|
|
||||||
|
[profile.release.package.mix-fetch-wasm]
|
||||||
# lto = true
|
# lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
|
|
||||||
|
|||||||
@@ -104,20 +104,23 @@ $(eval $(call add_cargo_workspace,wallet,nym-wallet))
|
|||||||
sdk-wasm: sdk-wasm-build sdk-wasm-test sdk-wasm-lint
|
sdk-wasm: sdk-wasm-build sdk-wasm-test sdk-wasm-lint
|
||||||
|
|
||||||
sdk-wasm-build:
|
sdk-wasm-build:
|
||||||
|
# $(MAKE) -C nym-browser-extension/storage wasm-pack
|
||||||
$(MAKE) -C wasm/client
|
$(MAKE) -C wasm/client
|
||||||
|
$(MAKE) -C wasm/node-tester
|
||||||
$(MAKE) -C wasm/mix-fetch
|
$(MAKE) -C wasm/mix-fetch
|
||||||
$(MAKE) -C wasm/smolmix
|
|
||||||
# $(MAKE) -C wasm/zknym-lib
|
# $(MAKE) -C wasm/zknym-lib
|
||||||
|
# $(MAKE) -C wasm/full-nym-wasm
|
||||||
|
|
||||||
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
# run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo
|
||||||
sdk-typescript-build:
|
sdk-typescript-build:
|
||||||
npx lerna run --scope @nymproject/sdk build --stream
|
npx lerna run --scope @nymproject/sdk build --stream
|
||||||
npx lerna run --scope @nymproject/mix-fetch build --stream
|
npx lerna run --scope @nymproject/mix-fetch build --stream
|
||||||
pnpm --pwd sdk/typescript/codegen/contract-clients build
|
npx lerna run --scope @nymproject/node-tester build --stream
|
||||||
|
yarn --cwd sdk/typescript/codegen/contract-clients build
|
||||||
|
|
||||||
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
# NOTE: These targets are part of the main workspace (but not as wasm32-unknown-unknown)
|
||||||
|
# WASM_CRATES = extension-storage nym-client-wasm nym-node-tester-wasm zknym-lib
|
||||||
WASM_CRATES = nym-client-wasm
|
WASM_CRATES = nym-client-wasm nym-node-tester-wasm
|
||||||
|
|
||||||
sdk-wasm-test:
|
sdk-wasm-test:
|
||||||
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
#cargo test $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||||
@@ -125,7 +128,6 @@ sdk-wasm-test:
|
|||||||
sdk-wasm-lint:
|
sdk-wasm-lint:
|
||||||
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo clippy $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo clippy $(addprefix -p , $(WASM_CRATES)) --target wasm32-unknown-unknown -- -Dwarnings
|
||||||
$(MAKE) -C wasm/mix-fetch check-fmt
|
$(MAKE) -C wasm/mix-fetch check-fmt
|
||||||
$(MAKE) -C wasm/smolmix check-fmt
|
|
||||||
|
|
||||||
# Add to top-level targets
|
# Add to top-level targets
|
||||||
build: sdk-wasm-build
|
build: sdk-wasm-build
|
||||||
@@ -221,7 +223,7 @@ build-nym-cli:
|
|||||||
|
|
||||||
generate-typescript:
|
generate-typescript:
|
||||||
cd tools/ts-rs-cli && cargo run && cd ../..
|
cd tools/ts-rs-cli && cargo run && cd ../..
|
||||||
pnpm types:lint:fix
|
yarn types:lint:fix
|
||||||
|
|
||||||
# Run the integration tests for public nym-api endpoints
|
# Run the integration tests for public nym-api endpoints
|
||||||
run-api-tests:
|
run-api-tests:
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ Nym Node Operators and Validators Terms and Conditions can be found [here](https
|
|||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm build
|
yarn build
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -60,8 +60,7 @@ packages:
|
|||||||
## SYSTEM MAINTENANCE PLAYBOOK KNOBS
|
## SYSTEM MAINTENANCE PLAYBOOK KNOBS
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# To use particular version instead of Latest, provide in such form:
|
# nym_version: "v2025.21-mozzarella"
|
||||||
# nym_version: "nym-binaries-v2026.7-tola"
|
|
||||||
|
|
||||||
## NOTE:
|
## NOTE:
|
||||||
## if you want to pin Nym to a specific version instead of using the
|
## if you want to pin Nym to a specific version instead of using the
|
||||||
@@ -118,4 +117,4 @@ packages:
|
|||||||
|
|
||||||
# enable_writeback_tuning: true
|
# enable_writeback_tuning: true
|
||||||
# writeback_dirty_writeback_centisecs: 1500
|
# writeback_dirty_writeback_centisecs: 1500
|
||||||
# writeback_dirty_expire_centisecs: 6000
|
# writeback_dirty_expire_centisecs: 6000
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Mitigation playbook for CopyFail (CVE-2026-31431) and DirtyFrag (CVE-2026-43284 / CVE-2026-43500)
|
|
||||||
# This playbook applies interim module blacklists only
|
|
||||||
# Kernel patches are not yet available (May 2026)
|
|
||||||
# Once patched kernels ship, use remove_kernel_CVE_mitigations.yml to reverse everything
|
|
||||||
# This playbook is idempotent - safe to re-run if mitigations were already applied
|
|
||||||
|
|
||||||
- name: Mitigate Copy Fail + Dirty Frag
|
|
||||||
hosts: all
|
|
||||||
become: true
|
|
||||||
tasks:
|
|
||||||
- name: Blacklist algif_aead (Copy Fail)
|
|
||||||
copy:
|
|
||||||
dest: /etc/modprobe.d/disable-algif_aead.conf
|
|
||||||
content: "install algif_aead /bin/false\n"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
|
|
||||||
- name: Blacklist esp4, esp6, rxrpc (Dirty Frag)
|
|
||||||
copy:
|
|
||||||
dest: /etc/modprobe.d/dirtyfrag.conf
|
|
||||||
content: |
|
|
||||||
install esp4 /bin/false
|
|
||||||
install esp6 /bin/false
|
|
||||||
install rxrpc /bin/false
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
|
|
||||||
- name: Unload all affected modules
|
|
||||||
modprobe:
|
|
||||||
name: "{{ item }}"
|
|
||||||
state: absent
|
|
||||||
loop:
|
|
||||||
- algif_aead
|
|
||||||
- esp4
|
|
||||||
- esp6
|
|
||||||
- rxrpc
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Drop page cache to clear any contamination
|
|
||||||
shell: echo 3 > /proc/sys/vm/drop_caches
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
############################################################################################
|
|
||||||
############################################################################################
|
|
||||||
############################################################################################
|
|
||||||
#### THIS PLAYBOOK IS NOT MEANT TO BE RUN YET, IT IS NOT REFERRED IN ANY DOCUMENTATION! ####
|
|
||||||
############################################################################################
|
|
||||||
############################################################################################
|
|
||||||
############################################################################################
|
|
||||||
#
|
|
||||||
# Reversal playbook for mitigate_kernel_CVE.yml (CopyFail CVE-2026-31431 / DirtyFrag CVE-2026-43284 / CVE-2026-43500).
|
|
||||||
#
|
|
||||||
# Run this AFTER your distro has shipped the patched kernel.
|
|
||||||
# This playbook:
|
|
||||||
# 1. Updates the kernel via apt
|
|
||||||
# 2. Reboots and waits for reconnect
|
|
||||||
# 3. Verifies the running kernel is newer than the pre-patch version
|
|
||||||
# 4. Removes the interim module blacklists
|
|
||||||
# 5. Re-enables the affected modules live (no second reboot needed)
|
|
||||||
#
|
|
||||||
# Debian family only (Debian, Ubuntu). Tested on Debian 11, Debian 12, Ubuntu 20.04, 22.04, 24.04.
|
|
||||||
#
|
|
||||||
# For exit-gateway nodes with --wireguard-enabled true:
|
|
||||||
# After this playbook completes, run the networking restore step on each node via:
|
|
||||||
# ansible-playbook deploy.yml -t ntm
|
|
||||||
# See the CVE patch documentation for details.
|
|
||||||
|
|
||||||
- name: Remove CVE mitigations and apply patched kernel
|
|
||||||
hosts: all
|
|
||||||
become: true
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- name: Verify OS is Debian family
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- ansible_os_family == "Debian"
|
|
||||||
fail_msg: "This playbook supports Debian-family distros only (Debian, Ubuntu). For other distros, apply the kernel update and mitigation removal manually."
|
|
||||||
|
|
||||||
- name: Update apt cache
|
|
||||||
apt:
|
|
||||||
update_cache: true
|
|
||||||
cache_valid_time: 0
|
|
||||||
|
|
||||||
- name: Upgrade kernel packages
|
|
||||||
apt:
|
|
||||||
upgrade: full
|
|
||||||
only_upgrade: false
|
|
||||||
register: apt_upgrade_result
|
|
||||||
|
|
||||||
- name: Record pre-reboot kernel version
|
|
||||||
command: uname -r
|
|
||||||
register: kernel_before
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Reboot to load patched kernel
|
|
||||||
reboot:
|
|
||||||
msg: "Rebooting to apply patched kernel (CVE-2026-31431 / CVE-2026-43284 / CVE-2026-43500)"
|
|
||||||
reboot_timeout: 300
|
|
||||||
pre_reboot_delay: 5
|
|
||||||
post_reboot_delay: 15
|
|
||||||
|
|
||||||
- name: Record post-reboot kernel version
|
|
||||||
command: uname -r
|
|
||||||
register: kernel_after
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Show kernel versions before and after reboot
|
|
||||||
debug:
|
|
||||||
msg:
|
|
||||||
- "Kernel before reboot: {{ kernel_before.stdout }}"
|
|
||||||
- "Kernel after reboot: {{ kernel_after.stdout }}"
|
|
||||||
|
|
||||||
- name: Warn if kernel did not change after reboot
|
|
||||||
debug:
|
|
||||||
msg: >
|
|
||||||
WARNING: kernel version did not change after reboot ({{ kernel_after.stdout }}).
|
|
||||||
The patched kernel may not have been selected by GRUB, or no kernel update was available.
|
|
||||||
Do NOT remove the interim mitigations until you have confirmed the running kernel is patched.
|
|
||||||
Check: apt-cache policy linux-image-amd64 # Debian
|
|
||||||
Check: apt-cache policy linux-image-generic # Ubuntu
|
|
||||||
when: kernel_before.stdout == kernel_after.stdout
|
|
||||||
|
|
||||||
- name: Remove algif_aead blacklist
|
|
||||||
file:
|
|
||||||
path: /etc/modprobe.d/disable-algif_aead.conf
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Remove DirtyFrag blacklist (esp4, esp6, rxrpc)
|
|
||||||
file:
|
|
||||||
path: /etc/modprobe.d/dirtyfrag.conf
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Re-enable affected modules live
|
|
||||||
modprobe:
|
|
||||||
name: "{{ item }}"
|
|
||||||
state: present
|
|
||||||
loop:
|
|
||||||
- esp4
|
|
||||||
- esp6
|
|
||||||
- rxrpc
|
|
||||||
- algif_aead
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Confirm nym-node service is still running
|
|
||||||
systemd:
|
|
||||||
name: nym-node
|
|
||||||
state: started
|
|
||||||
register: nym_node_status
|
|
||||||
failed_when: false
|
|
||||||
|
|
||||||
- name: Show nym-node status
|
|
||||||
debug:
|
|
||||||
msg: "nym-node service state: {{ nym_node_status.state | default('unknown - service may not exist on this node') }}"
|
|
||||||
@@ -1,30 +1,11 @@
|
|||||||
---
|
---
|
||||||
- name: Ensure nym binaries directory exists
|
- name: Configure tunnel manager
|
||||||
file:
|
|
||||||
path: /root/nym-binaries
|
|
||||||
state: directory
|
|
||||||
mode: "0755"
|
|
||||||
tags:
|
tags:
|
||||||
- tunnel
|
|
||||||
- network_tunnel_manager
|
- network_tunnel_manager
|
||||||
- ntm
|
become: true
|
||||||
|
command:
|
||||||
- name: Download network tunnel manager
|
cmd: "/root/nym-binaries/network-tunnel-manager.sh {{ item }}"
|
||||||
get_url:
|
|
||||||
url: "{{ tunnel_manager_url }}"
|
|
||||||
dest: /root/nym-binaries/network-tunnel-manager.sh
|
|
||||||
mode: "0755"
|
|
||||||
force: yes
|
|
||||||
tags:
|
|
||||||
- tunnel
|
|
||||||
- network_tunnel_manager
|
|
||||||
- ntm
|
|
||||||
|
|
||||||
- name: Run network tunnel manager
|
|
||||||
command: "/root/nym-binaries/network-tunnel-manager.sh {{ item }}"
|
|
||||||
loop:
|
loop:
|
||||||
- complete_networking_configuration
|
- complete_networking_configuration
|
||||||
tags:
|
register: tunnel_mgr
|
||||||
- tunnel
|
failed_when: false
|
||||||
- network_tunnel_manager
|
|
||||||
- ntm
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client"
|
name = "nym-client"
|
||||||
description = "Implementation of the Nym Client"
|
version = "1.1.74"
|
||||||
version = "1.1.78"
|
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
|
description = "Implementation of the Nym Client"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
|
license.workspace = true
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
@@ -472,7 +472,6 @@ impl Handler {
|
|||||||
fn prepare_reconstructed_binary(
|
fn prepare_reconstructed_binary(
|
||||||
reconstructed_messages: Vec<ReconstructedMessage>,
|
reconstructed_messages: Vec<ReconstructedMessage>,
|
||||||
) -> Vec<Result<WsMessage, WsError>> {
|
) -> Vec<Result<WsMessage, WsError>> {
|
||||||
#[allow(clippy::result_large_err)] // TODO : remove this once tungstenite is updated
|
|
||||||
reconstructed_messages
|
reconstructed_messages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(ServerResponse::Received)
|
.map(ServerResponse::Received)
|
||||||
@@ -485,7 +484,6 @@ fn prepare_reconstructed_binary(
|
|||||||
fn prepare_reconstructed_text(
|
fn prepare_reconstructed_text(
|
||||||
reconstructed_messages: Vec<ReconstructedMessage>,
|
reconstructed_messages: Vec<ReconstructedMessage>,
|
||||||
) -> Vec<Result<WsMessage, WsError>> {
|
) -> Vec<Result<WsMessage, WsError>> {
|
||||||
#[allow(clippy::result_large_err)] // TODO : remove this once tungstenite is updated
|
|
||||||
reconstructed_messages
|
reconstructed_messages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(ServerResponse::Received)
|
.map(ServerResponse::Received)
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-websocket-requests"
|
name = "nym-client-websocket-requests"
|
||||||
description = "Request and response definitions for Nym client websocket connections"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Request and response definitions for Nym client websocket connections"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-socks5-client"
|
name = "nym-socks5-client"
|
||||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
version = "1.1.74"
|
||||||
version = "1.1.78"
|
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
|
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
|
license.workspace = true
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-async-file-watcher"
|
name = "nym-async-file-watcher"
|
||||||
description = "Simple file watcher that sends a notification whenever there was any change in the watched file"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Simple file watcher that sends a notification whenever there was any change in the watched file"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-authenticator-requests"
|
name = "nym-authenticator-requests"
|
||||||
description = "Crate defining requests and responses for the Nym authenticator client"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
|
||||||
license.workspace = true
|
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
edition.workspace = true
|
||||||
readme.workspace = true
|
license.workspace = true
|
||||||
publish = true
|
description = "Crate defining requests and responses for the Nym authenticator client"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-bandwidth-controller"
|
name = "nym-bandwidth-controller"
|
||||||
description = "Crate for controlling the use of zknym credentials to ensure constant bandwidth availability for NymVPN app"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Crate for controlling the use of zknym credentials to ensure constant bandwidth availability for NymVPN app"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ pub trait BandwidthTicketProvider: Send + Sync {
|
|||||||
) -> Result<PreparedCredential, BandwidthControllerError>;
|
) -> Result<PreparedCredential, BandwidthControllerError>;
|
||||||
|
|
||||||
async fn get_upgrade_mode_token(&self) -> Result<Option<String>, BandwidthControllerError>;
|
async fn get_upgrade_mode_token(&self) -> Result<Option<String>, BandwidthControllerError>;
|
||||||
|
|
||||||
async fn close(&self) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -58,10 +56,6 @@ where
|
|||||||
.map_err(|_| BandwidthControllerError::MalformedUpgradeModeToken)?;
|
.map_err(|_| BandwidthControllerError::MalformedUpgradeModeToken)?;
|
||||||
Ok(Some(token))
|
Ok(Some(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn close(&self) {
|
|
||||||
self.storage.close().await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -81,8 +75,4 @@ impl<T: BandwidthTicketProvider + ?Sized + Send> BandwidthTicketProvider for Box
|
|||||||
async fn get_upgrade_mode_token(&self) -> Result<Option<String>, BandwidthControllerError> {
|
async fn get_upgrade_mode_token(&self) -> Result<Option<String>, BandwidthControllerError> {
|
||||||
(**self).get_upgrade_mode_token().await
|
(**self).get_upgrade_mode_token().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn close(&self) {
|
|
||||||
(**self).close().await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-bin-common"
|
name = "nym-bin-common"
|
||||||
description = "Common code for nym binaries"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = { workspace = true }
|
description = "Common code for nym binaries"
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
authors = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
homepage.workspace = true
|
|
||||||
documentation.workspace = true
|
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true, features = ["derive"], optional = true }
|
clap = { workspace = true, features = ["derive"], optional = true }
|
||||||
@@ -43,7 +38,6 @@ default = []
|
|||||||
openapi = ["utoipa"]
|
openapi = ["utoipa"]
|
||||||
output_format = ["serde_json", "dep:clap"]
|
output_format = ["serde_json", "dep:clap"]
|
||||||
bin_info_schema = ["schemars"]
|
bin_info_schema = ["schemars"]
|
||||||
ip_check = []
|
|
||||||
basic_tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
basic_tracing = ["dep:tracing", "dep:tracing-subscriber"]
|
||||||
otel-otlp = [
|
otel-otlp = [
|
||||||
"basic_tracing",
|
"basic_tracing",
|
||||||
|
|||||||
@@ -9,6 +9,3 @@ pub mod completions;
|
|||||||
|
|
||||||
#[cfg(feature = "output_format")]
|
#[cfg(feature = "output_format")]
|
||||||
pub mod output_format;
|
pub mod output_format;
|
||||||
|
|
||||||
#[cfg(feature = "ip_check")]
|
|
||||||
pub mod ip_check;
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-core"
|
name = "nym-client-core"
|
||||||
description = "Crate containing core client functionality and configs, used by all other Nym client implentations"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Crate containing core client functionality and configs, used by all other Nym client implentations"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version = "1.85"
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-core-config-types"
|
name = "nym-client-core-config-types"
|
||||||
description = "Low level configs and constants used by Nym clients and nodes"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Low level configs and constants used by Nym clients and nodes"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-core-gateways-storage"
|
name = "nym-client-core-gateways-storage"
|
||||||
description = "Functionality for Nym clients to store and retrive Gateway connections"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
description = "Functionality for Nym clients to store and retrive Gateway connections"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1023,16 +1023,6 @@ where
|
|||||||
let encryption_keys = init_res.client_keys.encryption_keypair();
|
let encryption_keys = init_res.client_keys.encryption_keypair();
|
||||||
let identity_keys = init_res.client_keys.identity_keypair();
|
let identity_keys = init_res.client_keys.identity_keypair();
|
||||||
|
|
||||||
let credential_store_for_close = credential_store.clone();
|
|
||||||
let close_credential_token = shutdown_tracker.clone_shutdown_token();
|
|
||||||
shutdown_tracker.try_spawn_named(
|
|
||||||
async move {
|
|
||||||
close_credential_token.cancelled().await;
|
|
||||||
credential_store_for_close.close().await;
|
|
||||||
},
|
|
||||||
"CredentialStorage::close_on_shutdown",
|
|
||||||
);
|
|
||||||
|
|
||||||
// the components are started in very specific order. Unless you know what you are doing,
|
// the components are started in very specific order. Unless you know what you are doing,
|
||||||
// do not change that.
|
// do not change that.
|
||||||
let bandwidth_controller = self
|
let bandwidth_controller = self
|
||||||
|
|||||||
@@ -11,17 +11,11 @@ use nym_bandwidth_controller::BandwidthController;
|
|||||||
use nym_client_core_gateways_storage::OnDiskGatewaysDetails;
|
use nym_client_core_gateways_storage::OnDiskGatewaysDetails;
|
||||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||||
use nym_validator_client::{QueryHttpRpcNyxdClient, nyxd};
|
use nym_validator_client::{QueryHttpRpcNyxdClient, nyxd};
|
||||||
use std::{io, path::Path, time::Duration};
|
use std::{io, path::Path};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tracing::{error, info, trace};
|
use tracing::{error, info, trace};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Maximum rename retry attempts when the database file is temporarily locked.
|
|
||||||
const ARCHIVE_MAX_RETRY_ATTEMPTS: u8 = 15;
|
|
||||||
|
|
||||||
/// Delay between archive rename retry attempts.
|
|
||||||
const ARCHIVE_RETRY_DELAY: Duration = Duration::from_millis(200);
|
|
||||||
|
|
||||||
async fn setup_fresh_backend<P: AsRef<Path>>(
|
async fn setup_fresh_backend<P: AsRef<Path>>(
|
||||||
db_path: P,
|
db_path: P,
|
||||||
surb_config: &config::ReplySurbs,
|
surb_config: &config::ReplySurbs,
|
||||||
@@ -80,58 +74,13 @@ async fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()
|
|||||||
};
|
};
|
||||||
let renamed = db_path.with_extension(new_extension);
|
let renamed = db_path.with_extension(new_extension);
|
||||||
|
|
||||||
// On Windows, sqlx may release its OS file handles asynchronously after
|
tokio::fs::rename(db_path, &renamed).await.inspect_err(|_| {
|
||||||
// pool.close() returns, briefly keeping the file locked
|
error!(
|
||||||
// (ERROR_SHARING_VIOLATION, os error 32). Retry with a short delay to
|
"Failed to rename corrupt database file: {} to {}",
|
||||||
// give the OS time to flush the remaining handles.
|
db_path.display(),
|
||||||
for attempt in 0..ARCHIVE_MAX_RETRY_ATTEMPTS {
|
renamed.display()
|
||||||
match tokio::fs::rename(db_path, &renamed).await {
|
);
|
||||||
Ok(()) => return Ok(()),
|
})
|
||||||
Err(e) if is_file_locked_error(&e) && (attempt + 1) < ARCHIVE_MAX_RETRY_ATTEMPTS => {
|
|
||||||
trace!(
|
|
||||||
"Database file is temporarily locked, retrying archive \
|
|
||||||
(attempt {}/{}): {e}",
|
|
||||||
attempt + 1,
|
|
||||||
ARCHIVE_MAX_RETRY_ATTEMPTS
|
|
||||||
);
|
|
||||||
tokio::time::sleep(ARCHIVE_RETRY_DELAY).await;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
"Failed to rename corrupt database file: {} to {}",
|
|
||||||
db_path.display(),
|
|
||||||
renamed.display()
|
|
||||||
);
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reached only when every attempt was blocked by a file lock.
|
|
||||||
error!(
|
|
||||||
"Failed to rename corrupt database file after {} attempts: {} to {}",
|
|
||||||
ARCHIVE_MAX_RETRY_ATTEMPTS,
|
|
||||||
db_path.display(),
|
|
||||||
renamed.display()
|
|
||||||
);
|
|
||||||
Err(io::Error::other(
|
|
||||||
"corrupt database archive blocked by persistent file lock",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` when the IO error indicates a temporary file lock held by another handle
|
|
||||||
/// within the same process. Only meaningful on Windows; always `false` elsewhere.
|
|
||||||
fn is_file_locked_error(e: &io::Error) -> bool {
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
// ERROR_SHARING_VIOLATION = 32, ERROR_LOCK_VIOLATION = 33
|
|
||||||
matches!(e.raw_os_error(), Some(32) | Some(33))
|
|
||||||
}
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
let _ = e;
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ mod nonwasm_sealed {
|
|||||||
impl GatewaySender for LocalGateway {
|
impl GatewaySender for LocalGateway {
|
||||||
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
|
async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> {
|
||||||
self.packet_forwarder
|
self.packet_forwarder
|
||||||
.forward_client_packet_without_delay(packet)
|
.forward_packet(packet)
|
||||||
.map_err(erase_err)
|
.map_err(erase_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ where
|
|||||||
let mut pending_acks = Vec::with_capacity(fragments.len());
|
let mut pending_acks = Vec::with_capacity(fragments.len());
|
||||||
let mut to_forward: HashMap<_, Vec<_>> = HashMap::new();
|
let mut to_forward: HashMap<_, Vec<_>> = HashMap::new();
|
||||||
|
|
||||||
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments) {
|
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
|
||||||
let lane = raw.0;
|
let lane = raw.0;
|
||||||
let FragmentWithMaxRetransmissions {
|
let FragmentWithMaxRetransmissions {
|
||||||
fragment,
|
fragment,
|
||||||
@@ -670,7 +670,7 @@ where
|
|||||||
|
|
||||||
Ok(fragments
|
Ok(fragments
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(reply_surbs)
|
.zip(reply_surbs.into_iter())
|
||||||
.map(|(fragment, reply_surb)| {
|
.map(|(fragment, reply_surb)| {
|
||||||
// unwrap here is fine as we know we have a valid topology
|
// unwrap here is fine as we know we have a valid topology
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-client-core-surb-storage"
|
name = "nym-client-core-surb-storage"
|
||||||
description = "Functionality for Nym clients to generate and use Single Use Reply Blocks (SURBs)"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Functionality for Nym clients to generate and use Single Use Reply Blocks (SURBs)"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -337,8 +337,6 @@ impl ReplyStorageBackend for Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
|
async fn stop_storage_session(self) -> Result<(), Self::StorageError> {
|
||||||
let result = self.stop_client_use().await;
|
self.stop_client_use().await
|
||||||
self.shutdown().await;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ where
|
|||||||
debug!("Started PersistentReplyStorage");
|
debug!("Started PersistentReplyStorage");
|
||||||
if let Err(err) = self.backend.start_storage_session().await {
|
if let Err(err) = self.backend.start_storage_session().await {
|
||||||
error!("failed to start the storage session - {err}");
|
error!("failed to start the storage session - {err}");
|
||||||
self.backend.stop_storage_session().await.ok();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,11 +55,10 @@ where
|
|||||||
|
|
||||||
info!("PersistentReplyStorage is flushing all reply-related data to underlying storage");
|
info!("PersistentReplyStorage is flushing all reply-related data to underlying storage");
|
||||||
if let Err(err) = self.backend.flush_surb_storage(&mem_state).await {
|
if let Err(err) = self.backend.flush_surb_storage(&mem_state).await {
|
||||||
error!("failed to flush our reply-related data to the persistent storage: {err}");
|
error!("failed to flush our reply-related data to the persistent storage: {err}")
|
||||||
self.backend.stop_storage_session().await.ok();
|
} else {
|
||||||
return;
|
info!("Data flush is complete")
|
||||||
}
|
}
|
||||||
info!("Data flush is complete");
|
|
||||||
|
|
||||||
if let Err(err) = self.backend.stop_storage_session().await {
|
if let Err(err) = self.backend.stop_storage_session().await {
|
||||||
error!("failed to properly stop the storage session - {err}. We might not be able to smoothly restore it")
|
error!("failed to properly stop the storage session - {err}. We might not be able to smoothly restore it")
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-gateway-client"
|
name = "nym-gateway-client"
|
||||||
description = "Functions and types for Nym client <> Gateway connections"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Functions and types for Nym client <> Gateway connections"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-mixnet-client"
|
name = "nym-mixnet-client"
|
||||||
description = "Client for Mix Node <> Mix Node & Mix Node <> Gateway communication"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Client for Mix Node <> Mix Node & Mix Node <> Gateway communication"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -34,4 +31,3 @@ client = ["tokio-util", "nym-task", "tokio/net", "tokio/rt"]
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nym-crypto = { workspace = true }
|
nym-crypto = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["macros", "io-util", "rt", "rt-multi-thread"] }
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::StreamExt;
|
||||||
use nym_noise::config::NoiseConfig;
|
use nym_noise::config::NoiseConfig;
|
||||||
use nym_noise::upgrade_noise_initiator;
|
use nym_noise::upgrade_noise_initiator;
|
||||||
use nym_sphinx::forwarding::packet::MixPacket;
|
use nym_sphinx::forwarding::packet::MixPacket;
|
||||||
@@ -14,7 +14,6 @@ use std::ops::Deref;
|
|||||||
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
@@ -91,17 +90,13 @@ impl Deref for ActiveConnections {
|
|||||||
pub struct ConnectionSender {
|
pub struct ConnectionSender {
|
||||||
channel: mpsc::Sender<FramedNymPacket>,
|
channel: mpsc::Sender<FramedNymPacket>,
|
||||||
current_reconnection_attempt: Arc<AtomicU32>,
|
current_reconnection_attempt: Arc<AtomicU32>,
|
||||||
// Identifies the `ManagedConnection` task currently owning this entry; used
|
|
||||||
// to ensure drop-time eviction only fires on the still-owning task.
|
|
||||||
handle_token: Arc<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectionSender {
|
impl ConnectionSender {
|
||||||
fn new(channel: mpsc::Sender<FramedNymPacket>, handle_token: Arc<()>) -> Self {
|
fn new(channel: mpsc::Sender<FramedNymPacket>) -> Self {
|
||||||
ConnectionSender {
|
ConnectionSender {
|
||||||
channel,
|
channel,
|
||||||
current_reconnection_attempt: Arc::new(AtomicU32::new(0)),
|
current_reconnection_attempt: Arc::new(AtomicU32::new(0)),
|
||||||
handle_token,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,31 +107,6 @@ struct ManagedConnection {
|
|||||||
message_receiver: ReceiverStream<FramedNymPacket>,
|
message_receiver: ReceiverStream<FramedNymPacket>,
|
||||||
connection_timeout: Duration,
|
connection_timeout: Duration,
|
||||||
current_reconnection: Arc<AtomicU32>,
|
current_reconnection: Arc<AtomicU32>,
|
||||||
active_connections: ActiveConnections,
|
|
||||||
handle_token: Arc<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evicts the cache entry on task exit (only if still owned by this task).
|
|
||||||
// Without this, a stale `ConnectionSender` survives after the peer disconnects
|
|
||||||
// and the next outbound packet is silently swallowed by the dead TCP.
|
|
||||||
struct EvictOnDrop {
|
|
||||||
active_connections: ActiveConnections,
|
|
||||||
address: SocketAddr,
|
|
||||||
handle_token: Arc<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for EvictOnDrop {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let address = self.address;
|
|
||||||
let handle_token = &self.handle_token;
|
|
||||||
self.active_connections.remove_if(&address, |_, sender| {
|
|
||||||
Arc::ptr_eq(&sender.handle_token, handle_token)
|
|
||||||
});
|
|
||||||
trace!(
|
|
||||||
peer = %address,
|
|
||||||
"managed connection task exited; evicted owning cache entry"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ManagedConnection {
|
impl ManagedConnection {
|
||||||
@@ -146,8 +116,6 @@ impl ManagedConnection {
|
|||||||
message_receiver: mpsc::Receiver<FramedNymPacket>,
|
message_receiver: mpsc::Receiver<FramedNymPacket>,
|
||||||
connection_timeout: Duration,
|
connection_timeout: Duration,
|
||||||
current_reconnection: Arc<AtomicU32>,
|
current_reconnection: Arc<AtomicU32>,
|
||||||
active_connections: ActiveConnections,
|
|
||||||
handle_token: Arc<()>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ManagedConnection {
|
ManagedConnection {
|
||||||
address,
|
address,
|
||||||
@@ -155,30 +123,72 @@ impl ManagedConnection {
|
|||||||
message_receiver: ReceiverStream::new(message_receiver),
|
message_receiver: ReceiverStream::new(message_receiver),
|
||||||
connection_timeout,
|
connection_timeout,
|
||||||
current_reconnection,
|
current_reconnection,
|
||||||
active_connections,
|
|
||||||
handle_token,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(self) {
|
async fn run(self) {
|
||||||
let address = self.address;
|
let address = self.address;
|
||||||
let _evict_guard = EvictOnDrop {
|
|
||||||
active_connections: self.active_connections,
|
|
||||||
address,
|
|
||||||
handle_token: self.handle_token,
|
|
||||||
};
|
|
||||||
|
|
||||||
let reconnection_attempt = self.current_reconnection.load(Ordering::Acquire);
|
let reconnection_attempt = self.current_reconnection.load(Ordering::Acquire);
|
||||||
let connect_start = tokio::time::Instant::now();
|
let connect_start = tokio::time::Instant::now();
|
||||||
let connection_fut = TcpStream::connect(address);
|
let connection_fut = TcpStream::connect(address);
|
||||||
|
|
||||||
// 1. attempt to establish the connection with timeout
|
let conn = match tokio::time::timeout(self.connection_timeout, connection_fut).await {
|
||||||
let maybe_stream = match tokio::time::timeout(self.connection_timeout, connection_fut).await
|
Ok(stream_res) => match stream_res {
|
||||||
{
|
Ok(stream) => {
|
||||||
Ok(stream) => stream,
|
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||||
|
debug!(
|
||||||
|
peer = %address,
|
||||||
|
connect_ms,
|
||||||
|
"Managed to establish connection to {}", self.address
|
||||||
|
);
|
||||||
|
|
||||||
|
let noise_start = tokio::time::Instant::now();
|
||||||
|
let noise_stream =
|
||||||
|
match upgrade_noise_initiator(stream, &self.noise_config).await {
|
||||||
|
Ok(noise_stream) => noise_stream,
|
||||||
|
Err(err) => {
|
||||||
|
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
||||||
|
warn!(
|
||||||
|
event = "connection.failed.noise",
|
||||||
|
peer = %address,
|
||||||
|
error = %err,
|
||||||
|
connect_ms,
|
||||||
|
noise_handshake_ms,
|
||||||
|
reconnection_attempt,
|
||||||
|
exit_reason = "noise_error",
|
||||||
|
"Failed to perform Noise initiator handshake with {address}"
|
||||||
|
);
|
||||||
|
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
||||||
|
self.current_reconnection.store(0, Ordering::Release);
|
||||||
|
debug!(
|
||||||
|
peer = %address,
|
||||||
|
connect_ms,
|
||||||
|
noise_handshake_ms,
|
||||||
|
"Noise initiator handshake completed for {:?}", address
|
||||||
|
);
|
||||||
|
Framed::new(noise_stream, NymCodec)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||||
|
warn!(
|
||||||
|
event = "connection.failed.connect",
|
||||||
|
peer = %address,
|
||||||
|
error = %err,
|
||||||
|
connect_ms,
|
||||||
|
reconnection_attempt,
|
||||||
|
exit_reason = "connect_error",
|
||||||
|
"failed to establish connection to {address}"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
||||||
debug!(
|
warn!(
|
||||||
event = "connection.failed.timeout",
|
event = "connection.failed.timeout",
|
||||||
peer = %address,
|
peer = %address,
|
||||||
timeout_ms = self.connection_timeout.as_millis() as u64,
|
timeout_ms = self.connection_timeout.as_millis() as u64,
|
||||||
@@ -193,163 +203,21 @@ impl ManagedConnection {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. check if it actually succeeded
|
if let Err(err) = self.message_receiver.map(Ok).forward(conn).await {
|
||||||
let stream = match maybe_stream {
|
warn!(
|
||||||
Ok(stream) => stream,
|
event = "connection.forward_error",
|
||||||
Err(err) => {
|
peer = %address,
|
||||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
error = %err,
|
||||||
debug!(
|
exit_reason = "forward_error",
|
||||||
event = "connection.failed.connect",
|
"Failed to forward packets to {address}: {err}"
|
||||||
peer = %address,
|
);
|
||||||
error = %err,
|
|
||||||
connect_ms,
|
|
||||||
reconnection_attempt,
|
|
||||||
exit_reason = "connect_error",
|
|
||||||
"failed to establish connection to {address}"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let connect_ms = connect_start.elapsed().as_millis() as u64;
|
|
||||||
debug!(
|
|
||||||
peer = %address,
|
|
||||||
connect_ms,
|
|
||||||
"Managed to establish connection to {}", self.address
|
|
||||||
);
|
|
||||||
|
|
||||||
// disable Nagle: mix packets are latency-sensitive and flushed one at a time.
|
|
||||||
if let Err(err) = stream.set_nodelay(true) {
|
|
||||||
warn!(peer = %address, error = %err, "failed to set TCP_NODELAY on outbound mixnet connection");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. perform noise handshake (if applicable)
|
|
||||||
let noise_start = tokio::time::Instant::now();
|
|
||||||
let noise_stream = match upgrade_noise_initiator(stream, &self.noise_config).await {
|
|
||||||
Ok(noise_stream) => noise_stream,
|
|
||||||
Err(err) => {
|
|
||||||
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
|
||||||
debug!(
|
|
||||||
event = "connection.failed.noise",
|
|
||||||
peer = %address,
|
|
||||||
error = %err,
|
|
||||||
connect_ms,
|
|
||||||
noise_handshake_ms,
|
|
||||||
reconnection_attempt,
|
|
||||||
exit_reason = "noise_error",
|
|
||||||
"Failed to perform Noise initiator handshake with {address}"
|
|
||||||
);
|
|
||||||
self.current_reconnection.fetch_add(1, Ordering::SeqCst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let noise_handshake_ms = noise_start.elapsed().as_millis() as u64;
|
|
||||||
self.current_reconnection.store(0, Ordering::Release);
|
|
||||||
debug!(
|
debug!(
|
||||||
peer = %address,
|
peer = %address,
|
||||||
connect_ms,
|
exit_reason = "sender_dropped",
|
||||||
noise_handshake_ms,
|
"connection manager to {address} finished"
|
||||||
"Noise initiator handshake completed for {:?}", address
|
|
||||||
);
|
);
|
||||||
let mut conn = Framed::new(noise_stream, NymCodec);
|
|
||||||
// let the write buffer accumulate several packets before flushing (see run_io_loop)
|
|
||||||
conn.set_backpressure_boundary(OUTBOUND_WRITE_BUFFER);
|
|
||||||
|
|
||||||
// 4. start handling the framed stream
|
|
||||||
run_io_loop(conn, self.message_receiver, address).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Upper bound on how many already-queued packets we drain into a single flush.
|
|
||||||
/// Bounds the per-batch allocation and how often we re-check the read side; the actual
|
|
||||||
/// write coalescing is governed by the Framed backpressure boundary below.
|
|
||||||
const OUTBOUND_FLUSH_BATCH: usize = 1024;
|
|
||||||
|
|
||||||
/// Write-buffer high-water mark for the egress `Framed`: packets are coalesced up to
|
|
||||||
/// roughly this many bytes before a flush, trading a larger write burst for far fewer
|
|
||||||
/// syscalls (and noise frames) under load. Kept under the ~64KiB noise frame ceiling so
|
|
||||||
/// a flush is usually a single frame.
|
|
||||||
const OUTBOUND_WRITE_BUFFER: usize = 32 * 1024;
|
|
||||||
|
|
||||||
// The connection is unidirectional (send-only); we read from it solely to
|
|
||||||
// notice peer FIN/RST while idle so we can evict the cache entry before the
|
|
||||||
// next outbound send finds it stale.
|
|
||||||
async fn run_io_loop<T>(
|
|
||||||
conn: Framed<T, NymCodec>,
|
|
||||||
receiver: ReceiverStream<FramedNymPacket>,
|
|
||||||
address: SocketAddr,
|
|
||||||
) where
|
|
||||||
T: AsyncRead + AsyncWrite + Unpin,
|
|
||||||
{
|
|
||||||
let (mut sink, mut stream) = conn.split();
|
|
||||||
|
|
||||||
// drain all currently-queued packets into one flush rather than flushing per packet,
|
|
||||||
// which otherwise caps egress throughput and backs up the per-connection queue under load
|
|
||||||
let mut receiver = receiver.ready_chunks(OUTBOUND_FLUSH_BATCH);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
msg = stream.next() => {
|
|
||||||
match msg {
|
|
||||||
None => {
|
|
||||||
debug!(
|
|
||||||
peer = %address,
|
|
||||||
exit_reason = "peer_closed",
|
|
||||||
"peer closed mixnet connection to {address}"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Some(Err(err)) => {
|
|
||||||
debug!(
|
|
||||||
event = "connection.read_error",
|
|
||||||
peer = %address,
|
|
||||||
error = %err,
|
|
||||||
exit_reason = "read_error",
|
|
||||||
"read error on mixnet connection to {address}: {err}"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Some(Ok(_)) => {
|
|
||||||
trace!(
|
|
||||||
peer = %address,
|
|
||||||
"unexpected inbound packet on mixnet connection to {address}; discarding"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outgoing = receiver.next() => {
|
|
||||||
match outgoing {
|
|
||||||
None => {
|
|
||||||
debug!(
|
|
||||||
peer = %address,
|
|
||||||
exit_reason = "sender_dropped",
|
|
||||||
"connection manager to {address} finished"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Some(batch) => {
|
|
||||||
// feed the whole ready batch, then flush once
|
|
||||||
let res = async {
|
|
||||||
for packet in batch {
|
|
||||||
sink.feed(packet).await?;
|
|
||||||
}
|
|
||||||
sink.flush().await
|
|
||||||
}
|
|
||||||
.await;
|
|
||||||
if let Err(err) = res {
|
|
||||||
debug!(
|
|
||||||
event = "connection.forward_error",
|
|
||||||
peer = %address,
|
|
||||||
error = %err,
|
|
||||||
exit_reason = "forward_error",
|
|
||||||
"failed to forward packet batch to {address}: {err}"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,18 +264,13 @@ impl Client {
|
|||||||
sender.try_send(pending_packet).unwrap();
|
sender.try_send(pending_packet).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ownership token for the task we're about to spawn; lets it tell
|
|
||||||
// on exit whether the cache entry still names it.
|
|
||||||
let handle_token = Arc::new(());
|
|
||||||
|
|
||||||
// if we already tried to connect to `address` before, grab the current attempt count
|
// if we already tried to connect to `address` before, grab the current attempt count
|
||||||
let current_reconnection_attempt =
|
let current_reconnection_attempt =
|
||||||
if let Some(mut existing) = self.active_connections.get_mut(&address) {
|
if let Some(mut existing) = self.active_connections.get_mut(&address) {
|
||||||
existing.channel = sender;
|
existing.channel = sender;
|
||||||
existing.handle_token = Arc::clone(&handle_token);
|
|
||||||
Arc::clone(&existing.current_reconnection_attempt)
|
Arc::clone(&existing.current_reconnection_attempt)
|
||||||
} else {
|
} else {
|
||||||
let new_entry = ConnectionSender::new(sender, Arc::clone(&handle_token));
|
let new_entry = ConnectionSender::new(sender);
|
||||||
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
|
let current_attempt = Arc::clone(&new_entry.current_reconnection_attempt);
|
||||||
self.active_connections.insert(address, new_entry);
|
self.active_connections.insert(address, new_entry);
|
||||||
current_attempt
|
current_attempt
|
||||||
@@ -422,7 +285,6 @@ impl Client {
|
|||||||
|
|
||||||
let connections_count = self.connections_count.clone();
|
let connections_count = self.connections_count.clone();
|
||||||
let noise_config = self.noise_config.clone();
|
let noise_config = self.noise_config.clone();
|
||||||
let active_connections = self.active_connections.clone();
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// before executing the manager, wait for what was specified, if anything
|
// before executing the manager, wait for what was specified, if anything
|
||||||
if let Some(backoff) = backoff {
|
if let Some(backoff) = backoff {
|
||||||
@@ -437,8 +299,6 @@ impl Client {
|
|||||||
receiver,
|
receiver,
|
||||||
initial_connection_timeout,
|
initial_connection_timeout,
|
||||||
current_reconnection_attempt,
|
current_reconnection_attempt,
|
||||||
active_connections,
|
|
||||||
handle_token,
|
|
||||||
)
|
)
|
||||||
.run()
|
.run()
|
||||||
.await;
|
.await;
|
||||||
@@ -568,102 +428,4 @@ mod tests {
|
|||||||
client.config.maximum_reconnection_backoff
|
client.config.maximum_reconnection_backoff
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_addr() -> SocketAddr {
|
|
||||||
"127.0.0.1:1".parse().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_with_token(
|
|
||||||
active: &ActiveConnections,
|
|
||||||
addr: SocketAddr,
|
|
||||||
token: Arc<()>,
|
|
||||||
) -> mpsc::Receiver<FramedNymPacket> {
|
|
||||||
let (tx, rx) = mpsc::channel(1);
|
|
||||||
active.insert(addr, ConnectionSender::new(tx, token));
|
|
||||||
rx
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn evict_on_drop_removes_entry_when_token_still_matches() {
|
|
||||||
let active = ActiveConnections::default();
|
|
||||||
let addr = test_addr();
|
|
||||||
let token = Arc::new(());
|
|
||||||
let _rx = insert_with_token(&active, addr, Arc::clone(&token));
|
|
||||||
|
|
||||||
assert!(active.get(&addr).is_some());
|
|
||||||
|
|
||||||
{
|
|
||||||
let _guard = EvictOnDrop {
|
|
||||||
active_connections: active.clone(),
|
|
||||||
address: addr,
|
|
||||||
handle_token: token,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
active.get(&addr).is_none(),
|
|
||||||
"owning task's drop should evict the entry"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn evict_on_drop_preserves_entry_replaced_by_newer_make_connection() {
|
|
||||||
// Simulates the race: old task's run() has returned, but before its
|
|
||||||
// drop guard fires, a concurrent `make_connection` replaced the
|
|
||||||
// entry's channel + handle_token with a fresh task's token.
|
|
||||||
let active = ActiveConnections::default();
|
|
||||||
let addr = test_addr();
|
|
||||||
let old_token = Arc::new(());
|
|
||||||
let new_token = Arc::new(());
|
|
||||||
let _rx_new = insert_with_token(&active, addr, Arc::clone(&new_token));
|
|
||||||
|
|
||||||
{
|
|
||||||
let _guard = EvictOnDrop {
|
|
||||||
active_connections: active.clone(),
|
|
||||||
address: addr,
|
|
||||||
handle_token: old_token,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
active.get(&addr).is_some(),
|
|
||||||
"old task's drop must not clobber the newer entry"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn io_loop_exits_when_peer_closes_idle_connection() {
|
|
||||||
// The fix's second half: while no packets are flowing, peer FIN/RST
|
|
||||||
// must still be observed so the cache entry can be evicted before the
|
|
||||||
// next send finds it stale.
|
|
||||||
let (a, b) = tokio::io::duplex(64);
|
|
||||||
let conn = Framed::new(a, NymCodec);
|
|
||||||
let (_tx, rx) = mpsc::channel(1);
|
|
||||||
|
|
||||||
let task = tokio::spawn(run_io_loop(conn, ReceiverStream::new(rx), test_addr()));
|
|
||||||
|
|
||||||
// Simulate peer closing both directions of the connection.
|
|
||||||
drop(b);
|
|
||||||
|
|
||||||
tokio::time::timeout(Duration::from_secs(1), task)
|
|
||||||
.await
|
|
||||||
.expect("io_loop must notice peer close while idle")
|
|
||||||
.expect("io_loop task must not panic");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn io_loop_exits_when_sender_dropped() {
|
|
||||||
let (a, _b) = tokio::io::duplex(64);
|
|
||||||
let conn = Framed::new(a, NymCodec);
|
|
||||||
let (tx, rx) = mpsc::channel(1);
|
|
||||||
|
|
||||||
let task = tokio::spawn(run_io_loop(conn, ReceiverStream::new(rx), test_addr()));
|
|
||||||
|
|
||||||
drop(tx);
|
|
||||||
|
|
||||||
tokio::time::timeout(Duration::from_secs(1), task)
|
|
||||||
.await
|
|
||||||
.expect("io_loop must exit when the upstream sender is dropped")
|
|
||||||
.expect("io_loop task must not panic");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,12 @@ impl From<mpsc::UnboundedSender<PacketToForward>> for MixForwardingSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MixForwardingSender {
|
impl MixForwardingSender {
|
||||||
pub fn forward_packet(&self, packet: PacketToForward) -> Result<(), SendError> {
|
pub fn forward_packet(&self, packet: impl Into<PacketToForward>) -> Result<(), SendError> {
|
||||||
self.0
|
self.0
|
||||||
.unbounded_send(packet)
|
.unbounded_send(packet.into())
|
||||||
.map_err(|err| err.into_send_error())
|
.map_err(|err| err.into_send_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_client_packet_without_delay(&self, packet: MixPacket) -> Result<(), SendError> {
|
|
||||||
self.forward_packet(PacketToForward::client_packet_without_delay(packet))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
@@ -42,23 +38,35 @@ pub type MixForwardingReceiver = mpsc::UnboundedReceiver<PacketToForward>;
|
|||||||
pub struct PacketToForward {
|
pub struct PacketToForward {
|
||||||
pub packet: MixPacket,
|
pub packet: MixPacket,
|
||||||
pub forward_delay_target: Option<Instant>,
|
pub forward_delay_target: Option<Instant>,
|
||||||
pub network_monitor_packet: bool,
|
}
|
||||||
|
|
||||||
|
impl From<MixPacket> for PacketToForward {
|
||||||
|
fn from(packet: MixPacket) -> Self {
|
||||||
|
PacketToForward::new_no_delay(packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(MixPacket, Option<Instant>)> for PacketToForward {
|
||||||
|
fn from((packet, delay_until): (MixPacket, Option<Instant>)) -> Self {
|
||||||
|
PacketToForward::new(packet, delay_until)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(MixPacket, Instant)> for PacketToForward {
|
||||||
|
fn from((packet, delay_until): (MixPacket, Instant)) -> Self {
|
||||||
|
PacketToForward::new(packet, Some(delay_until))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketToForward {
|
impl PacketToForward {
|
||||||
pub fn new(
|
pub fn new(packet: MixPacket, forward_delay_target: Option<Instant>) -> Self {
|
||||||
packet: MixPacket,
|
|
||||||
forward_delay_target: Option<Instant>,
|
|
||||||
network_monitor_packet: bool,
|
|
||||||
) -> Self {
|
|
||||||
PacketToForward {
|
PacketToForward {
|
||||||
packet,
|
packet,
|
||||||
forward_delay_target,
|
forward_delay_target,
|
||||||
network_monitor_packet,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_packet_without_delay(packet: MixPacket) -> Self {
|
pub fn new_no_delay(packet: MixPacket) -> Self {
|
||||||
Self::new(packet, None, false)
|
Self::new(packet, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-validator-client"
|
name = "nym-validator-client"
|
||||||
description = "Client for interacting with Nyx Cosmos SDK blockchain"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
rust-version = "1.85"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Client for interacting with Nyx Cosmos SDK blockchain"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version = "1.85"
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -26,8 +24,6 @@ nym-ecash-contract-common = { workspace = true }
|
|||||||
nym-multisig-contract-common = { workspace = true }
|
nym-multisig-contract-common = { workspace = true }
|
||||||
nym-group-contract-common = { workspace = true }
|
nym-group-contract-common = { workspace = true }
|
||||||
nym-performance-contract-common = { workspace = true }
|
nym-performance-contract-common = { workspace = true }
|
||||||
nym-network-monitors-contract-common = { workspace = true }
|
|
||||||
nym-node-families-contract-common = { workspace = true }
|
|
||||||
nym-serde-helpers = { workspace = true, features = ["hex", "base64"] }
|
nym-serde-helpers = { workspace = true, features = ["hex", "base64"] }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
|||||||
@@ -104,14 +104,6 @@ impl TryFrom<NymNetworkDetails> for Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new(nyxd_url: Url, api_url: Url, nyxd_config: nyxd::Config) -> Self {
|
|
||||||
Config {
|
|
||||||
api_url,
|
|
||||||
nyxd_url,
|
|
||||||
nyxd_config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_from_nym_network_details(
|
pub fn try_from_nym_network_details(
|
||||||
details: &NymNetworkDetails,
|
details: &NymNetworkDetails,
|
||||||
) -> Result<Self, ValidatorClientError> {
|
) -> Result<Self, ValidatorClientError> {
|
||||||
@@ -122,15 +114,6 @@ impl Config {
|
|||||||
.map(|url| Url::parse(url))
|
.map(|url| Url::parse(url))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
if let Some(nym_api_urls) = details.nym_api_urls.as_ref() {
|
|
||||||
api_url.extend(
|
|
||||||
nym_api_urls
|
|
||||||
.iter()
|
|
||||||
.map(|url| url.url.parse())
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if api_url.is_empty() {
|
if api_url.is_empty() {
|
||||||
return Err(ValidatorClientError::NoAPIUrlAvailable);
|
return Err(ValidatorClientError::NoAPIUrlAvailable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,11 @@ use nym_api_requests::ecash::models::{
|
|||||||
VerifyEcashTicketBody,
|
VerifyEcashTicketBody,
|
||||||
};
|
};
|
||||||
use nym_api_requests::ecash::VerificationKeyResponse;
|
use nym_api_requests::ecash::VerificationKeyResponse;
|
||||||
use nym_api_requests::models::network_monitor::{
|
|
||||||
KnownNetworkMonitorResponse, StressTestBatchSubmission,
|
|
||||||
};
|
|
||||||
use nym_api_requests::models::node_families::NodeFamily;
|
|
||||||
use nym_api_requests::models::{
|
use nym_api_requests::models::{
|
||||||
AnnotationResponseV1, ApiHealthResponse, BinaryBuildInformationOwned,
|
AnnotationResponse, ApiHealthResponse, BinaryBuildInformationOwned, ChainBlocksStatusResponse,
|
||||||
ChainBlocksStatusResponse, ChainStatusResponse, KeyRotationInfoResponse,
|
ChainStatusResponse, KeyRotationInfoResponse, NodePerformanceResponse, NodeRefreshBody,
|
||||||
NodePerformanceResponse, NodeRefreshBody, NymNodeDescriptionV1, NymNodeDescriptionV2,
|
NymNodeDescriptionV1, NymNodeDescriptionV2, PerformanceHistoryResponse, RewardedSetResponse,
|
||||||
PerformanceHistoryResponse, RewardedSetResponse, SignerInformationResponse,
|
SignerInformationResponse,
|
||||||
StressTestBatchSubmissionResponse,
|
|
||||||
};
|
};
|
||||||
use nym_api_requests::pagination::PaginatedResponse;
|
use nym_api_requests::pagination::PaginatedResponse;
|
||||||
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
use nym_http_api_client::{ApiClient, NO_PARAMS};
|
||||||
@@ -394,45 +389,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
Ok(bonds)
|
Ok(bonds)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
|
||||||
async fn get_node_families(
|
|
||||||
&self,
|
|
||||||
page: Option<u32>,
|
|
||||||
per_page: Option<u32>,
|
|
||||||
) -> Result<PaginatedResponse<NodeFamily>, NymAPIError> {
|
|
||||||
let mut params = Vec::new();
|
|
||||||
if let Some(page) = page {
|
|
||||||
params.push(("page", page.to_string()))
|
|
||||||
}
|
|
||||||
if let Some(per_page) = per_page {
|
|
||||||
params.push(("per_page", per_page.to_string()))
|
|
||||||
}
|
|
||||||
self.get_json(
|
|
||||||
&[routes::V1_API_VERSION, routes::NODE_FAMILIES_ROUTES],
|
|
||||||
¶ms,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_node_families(&self) -> Result<Vec<NodeFamily>, NymAPIError> {
|
|
||||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
|
||||||
let mut page = 0;
|
|
||||||
let mut families = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut res = self.get_node_families(Some(page), None).await?;
|
|
||||||
|
|
||||||
families.append(&mut res.data);
|
|
||||||
if families.len() < res.pagination.total {
|
|
||||||
page += 1
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(families)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNodeV1>, NymAPIError> {
|
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNodeV1>, NymAPIError> {
|
||||||
@@ -1020,7 +976,7 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
async fn get_node_annotation(
|
async fn get_node_annotation(
|
||||||
&self,
|
&self,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
) -> Result<AnnotationResponseV1, NymAPIError> {
|
) -> Result<AnnotationResponse, NymAPIError> {
|
||||||
self.get_json(
|
self.get_json(
|
||||||
&[
|
&[
|
||||||
routes::V1_API_VERSION,
|
routes::V1_API_VERSION,
|
||||||
@@ -1403,53 +1359,6 @@ pub trait NymApiClientExt: ApiClient {
|
|||||||
|
|
||||||
Ok(SemiSkimmedNodesWithMetadata::new(nodes, metadata))
|
Ok(SemiSkimmedNodesWithMetadata::new(nodes, metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queries the nym-api for whether a particular ed25519 identity key is currently recognised
|
|
||||||
/// as an authorised network monitor permitted to submit stress testing results.
|
|
||||||
///
|
|
||||||
/// `identity_key` is expected to be the base58-encoded form of the ed25519 public key.
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
async fn get_known_network_monitor(
|
|
||||||
&self,
|
|
||||||
identity_key: IdentityKeyRef<'_>,
|
|
||||||
) -> Result<KnownNetworkMonitorResponse, NymAPIError> {
|
|
||||||
self.get_json(
|
|
||||||
&[
|
|
||||||
routes::V3_API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::STRESS_TESTING,
|
|
||||||
routes::STRESS_TESTING_KNOWN_MONITORS,
|
|
||||||
identity_key,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Submit a signed batch of stress-testing results to nym-api on behalf of a network monitor
|
|
||||||
/// orchestrator.
|
|
||||||
///
|
|
||||||
/// The caller is expected to have produced `request` via
|
|
||||||
/// `StressTestBatchSubmissionContent::new(...)` and signed it with the orchestrator's ed25519
|
|
||||||
/// key; nym-api will reject submissions that are stale, replayed, unauthorised, or whose
|
|
||||||
/// signature fails to verify.
|
|
||||||
#[instrument(level = "debug", skip(self, request))]
|
|
||||||
async fn submit_stress_testing_results(
|
|
||||||
&self,
|
|
||||||
request: &StressTestBatchSubmission,
|
|
||||||
) -> Result<StressTestBatchSubmissionResponse, NymAPIError> {
|
|
||||||
self.post_json(
|
|
||||||
&[
|
|
||||||
routes::V3_API_VERSION,
|
|
||||||
routes::NYM_NODES_ROUTES,
|
|
||||||
routes::STRESS_TESTING,
|
|
||||||
routes::STRESS_TESTING_BATCH_SUBMIT,
|
|
||||||
],
|
|
||||||
NO_PARAMS,
|
|
||||||
request,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is already nym_http_api_client::Client (re-exported above), so just one impl needed
|
// Client is already nym_http_api_client::Client (re-exported above), so just one impl needed
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ pub mod ecash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const NYM_NODES_ROUTES: &str = "nym-nodes";
|
pub const NYM_NODES_ROUTES: &str = "nym-nodes";
|
||||||
pub const NODE_FAMILIES_ROUTES: &str = "node-families";
|
|
||||||
|
|
||||||
pub use nym_nodes::*;
|
pub use nym_nodes::*;
|
||||||
pub mod nym_nodes {
|
pub mod nym_nodes {
|
||||||
@@ -50,9 +49,6 @@ pub mod nym_nodes {
|
|||||||
pub const NYM_NODES_REWARDED_SET: &str = "rewarded-set";
|
pub const NYM_NODES_REWARDED_SET: &str = "rewarded-set";
|
||||||
pub const NYM_NODES_REFRESH_DESCRIBED: &str = "refresh-described";
|
pub const NYM_NODES_REFRESH_DESCRIBED: &str = "refresh-described";
|
||||||
pub const BY_ADDRESSES: &str = "by-addresses";
|
pub const BY_ADDRESSES: &str = "by-addresses";
|
||||||
pub const STRESS_TESTING: &str = "stress-testing";
|
|
||||||
pub const STRESS_TESTING_KNOWN_MONITORS: &str = "known-monitors";
|
|
||||||
pub const STRESS_TESTING_BATCH_SUBMIT: &str = "batch-submit";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const STATUS_ROUTES: &str = "status";
|
pub const STATUS_ROUTES: &str = "status";
|
||||||
|
|||||||
@@ -867,10 +867,6 @@ mod tests {
|
|||||||
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
|
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
|
||||||
client.testing_resolve_all_pending_events(None).ignore()
|
client.testing_resolve_all_pending_events(None).ignore()
|
||||||
}
|
}
|
||||||
// not expected to be exposed by the client
|
|
||||||
ExecuteMsg::AdminMigrateVestedMixNode { .. }
|
|
||||||
| ExecuteMsg::AdminMigrateVestedDelegation { .. }
|
|
||||||
| ExecuteMsg::AdminBatchMigrateVestedDelegations { .. } => ().ignore(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ pub mod ecash_query_client;
|
|||||||
pub mod group_query_client;
|
pub mod group_query_client;
|
||||||
pub mod mixnet_query_client;
|
pub mod mixnet_query_client;
|
||||||
pub mod multisig_query_client;
|
pub mod multisig_query_client;
|
||||||
pub mod network_monitors_query_client;
|
|
||||||
pub mod node_families_query_client;
|
|
||||||
pub mod performance_query_client;
|
pub mod performance_query_client;
|
||||||
pub mod vesting_query_client;
|
pub mod vesting_query_client;
|
||||||
|
|
||||||
@@ -24,8 +22,6 @@ pub mod ecash_signing_client;
|
|||||||
pub mod group_signing_client;
|
pub mod group_signing_client;
|
||||||
pub mod mixnet_signing_client;
|
pub mod mixnet_signing_client;
|
||||||
pub mod multisig_signing_client;
|
pub mod multisig_signing_client;
|
||||||
pub mod network_monitors_signing_client;
|
|
||||||
pub mod node_families_signing_client;
|
|
||||||
pub mod performance_signing_client;
|
pub mod performance_signing_client;
|
||||||
pub mod vesting_signing_client;
|
pub mod vesting_signing_client;
|
||||||
|
|
||||||
@@ -35,10 +31,6 @@ pub use ecash_query_client::{EcashQueryClient, PagedEcashQueryClient};
|
|||||||
pub use group_query_client::{GroupQueryClient, PagedGroupQueryClient};
|
pub use group_query_client::{GroupQueryClient, PagedGroupQueryClient};
|
||||||
pub use mixnet_query_client::{MixnetQueryClient, PagedMixnetQueryClient};
|
pub use mixnet_query_client::{MixnetQueryClient, PagedMixnetQueryClient};
|
||||||
pub use multisig_query_client::{MultisigQueryClient, PagedMultisigQueryClient};
|
pub use multisig_query_client::{MultisigQueryClient, PagedMultisigQueryClient};
|
||||||
pub use network_monitors_query_client::{
|
|
||||||
NetworkMonitorsQueryClient, PagedNetworkMonitorsQueryClient,
|
|
||||||
};
|
|
||||||
pub use node_families_query_client::{NodeFamiliesQueryClient, PagedNodeFamiliesQueryClient};
|
|
||||||
pub use performance_query_client::{PagedPerformanceQueryClient, PerformanceQueryClient};
|
pub use performance_query_client::{PagedPerformanceQueryClient, PerformanceQueryClient};
|
||||||
pub use vesting_query_client::{PagedVestingQueryClient, VestingQueryClient};
|
pub use vesting_query_client::{PagedVestingQueryClient, VestingQueryClient};
|
||||||
|
|
||||||
@@ -48,8 +40,6 @@ pub use ecash_signing_client::EcashSigningClient;
|
|||||||
pub use group_signing_client::GroupSigningClient;
|
pub use group_signing_client::GroupSigningClient;
|
||||||
pub use mixnet_signing_client::MixnetSigningClient;
|
pub use mixnet_signing_client::MixnetSigningClient;
|
||||||
pub use multisig_signing_client::MultisigSigningClient;
|
pub use multisig_signing_client::MultisigSigningClient;
|
||||||
pub use network_monitors_signing_client::NetworkMonitorsSigningClient;
|
|
||||||
pub use node_families_signing_client::NodeFamiliesSigningClient;
|
|
||||||
pub use performance_signing_client::PerformanceSigningClient;
|
pub use performance_signing_client::PerformanceSigningClient;
|
||||||
pub use vesting_signing_client::VestingSigningClient;
|
pub use vesting_signing_client::VestingSigningClient;
|
||||||
|
|
||||||
@@ -59,8 +49,6 @@ pub trait NymContractsProvider {
|
|||||||
fn mixnet_contract_address(&self) -> Option<&AccountId>;
|
fn mixnet_contract_address(&self) -> Option<&AccountId>;
|
||||||
fn vesting_contract_address(&self) -> Option<&AccountId>;
|
fn vesting_contract_address(&self) -> Option<&AccountId>;
|
||||||
fn performance_contract_address(&self) -> Option<&AccountId>;
|
fn performance_contract_address(&self) -> Option<&AccountId>;
|
||||||
fn network_monitors_contract_address(&self) -> Option<&AccountId>;
|
|
||||||
fn node_families_contract_address(&self) -> Option<&AccountId>;
|
|
||||||
|
|
||||||
// coconut-related
|
// coconut-related
|
||||||
fn ecash_contract_address(&self) -> Option<&AccountId>;
|
fn ecash_contract_address(&self) -> Option<&AccountId>;
|
||||||
@@ -74,8 +62,6 @@ pub struct TypedNymContracts {
|
|||||||
pub mixnet_contract_address: Option<AccountId>,
|
pub mixnet_contract_address: Option<AccountId>,
|
||||||
pub vesting_contract_address: Option<AccountId>,
|
pub vesting_contract_address: Option<AccountId>,
|
||||||
pub performance_contract_address: Option<AccountId>,
|
pub performance_contract_address: Option<AccountId>,
|
||||||
pub network_monitors_contract_address: Option<AccountId>,
|
|
||||||
pub node_families_contract_address: Option<AccountId>,
|
|
||||||
|
|
||||||
pub ecash_contract_address: Option<AccountId>,
|
pub ecash_contract_address: Option<AccountId>,
|
||||||
pub group_contract_address: Option<AccountId>,
|
pub group_contract_address: Option<AccountId>,
|
||||||
@@ -100,14 +86,6 @@ impl TryFrom<NymContracts> for TypedNymContracts {
|
|||||||
.performance_contract_address
|
.performance_contract_address
|
||||||
.map(|addr| addr.parse())
|
.map(|addr| addr.parse())
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
network_monitors_contract_address: value
|
|
||||||
.network_monitors_contract_address
|
|
||||||
.map(|addr| addr.parse())
|
|
||||||
.transpose()?,
|
|
||||||
node_families_contract_address: value
|
|
||||||
.node_families_contract_address
|
|
||||||
.map(|addr| addr.parse())
|
|
||||||
.transpose()?,
|
|
||||||
ecash_contract_address: value
|
ecash_contract_address: value
|
||||||
.ecash_contract_address
|
.ecash_contract_address
|
||||||
.map(|addr| addr.parse())
|
.map(|addr| addr.parse())
|
||||||
|
|||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::collect_paged;
|
|
||||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
|
||||||
use crate::nyxd::error::NyxdError;
|
|
||||||
use crate::nyxd::CosmWasmClient;
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use nym_network_monitors_contract_common::{
|
|
||||||
AuthorisedNetworkMonitor, AuthorisedNetworkMonitorOrchestratorsResponse,
|
|
||||||
AuthorisedNetworkMonitorsPagedResponse, QueryMsg as NetworkMonitorsQueryMsg,
|
|
||||||
};
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait NetworkMonitorsQueryClient {
|
|
||||||
async fn query_network_monitors_contract<T>(
|
|
||||||
&self,
|
|
||||||
query: NetworkMonitorsQueryMsg,
|
|
||||||
) -> Result<T, NyxdError>
|
|
||||||
where
|
|
||||||
for<'a> T: Deserialize<'a>;
|
|
||||||
|
|
||||||
async fn get_admin(&self) -> Result<cw_controllers::AdminResponse, NyxdError> {
|
|
||||||
self.query_network_monitors_contract(NetworkMonitorsQueryMsg::Admin {})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_network_monitor_orchestrators(
|
|
||||||
&self,
|
|
||||||
) -> Result<AuthorisedNetworkMonitorOrchestratorsResponse, NyxdError> {
|
|
||||||
self.query_network_monitors_contract(
|
|
||||||
NetworkMonitorsQueryMsg::NetworkMonitorOrchestrators {},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_network_monitor_agents_paged(
|
|
||||||
&self,
|
|
||||||
start_next_after: Option<SocketAddr>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<AuthorisedNetworkMonitorsPagedResponse, NyxdError> {
|
|
||||||
self.query_network_monitors_contract(NetworkMonitorsQueryMsg::NetworkMonitorAgents {
|
|
||||||
start_next_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait PagedNetworkMonitorsQueryClient: NetworkMonitorsQueryClient {
|
|
||||||
async fn get_all_network_monitor_agents(
|
|
||||||
&self,
|
|
||||||
) -> Result<Vec<AuthorisedNetworkMonitor>, NyxdError> {
|
|
||||||
collect_paged!(self, get_network_monitor_agents_paged, authorised)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T> PagedNetworkMonitorsQueryClient for T where T: NetworkMonitorsQueryClient {}
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
impl<C> NetworkMonitorsQueryClient for C
|
|
||||||
where
|
|
||||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
|
||||||
{
|
|
||||||
async fn query_network_monitors_contract<T>(
|
|
||||||
&self,
|
|
||||||
query: NetworkMonitorsQueryMsg,
|
|
||||||
) -> Result<T, NyxdError>
|
|
||||||
where
|
|
||||||
for<'a> T: Deserialize<'a>,
|
|
||||||
{
|
|
||||||
let contract_address = &self
|
|
||||||
.network_monitors_contract_address()
|
|
||||||
.ok_or_else(|| NyxdError::unavailable_contract_address("network monitors contract"))?;
|
|
||||||
self.query_contract_smart(contract_address, &query).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
|
||||||
|
|
||||||
// it's enough that this compiles and clippy is happy about it
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn all_query_variants_are_covered<C: NetworkMonitorsQueryClient + Send + Sync>(
|
|
||||||
client: C,
|
|
||||||
msg: NetworkMonitorsQueryMsg,
|
|
||||||
) {
|
|
||||||
match msg {
|
|
||||||
NetworkMonitorsQueryMsg::Admin {} => client.get_admin().ignore(),
|
|
||||||
NetworkMonitorsQueryMsg::NetworkMonitorOrchestrators {} => {
|
|
||||||
client.get_network_monitor_orchestrators().ignore()
|
|
||||||
}
|
|
||||||
NetworkMonitorsQueryMsg::NetworkMonitorAgents { .. } => {
|
|
||||||
client.get_network_monitor_agents_paged(None, None).ignore()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-205
@@ -1,205 +0,0 @@
|
|||||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
|
||||||
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
|
|
||||||
use crate::nyxd::error::NyxdError;
|
|
||||||
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
|
|
||||||
use crate::signing::signer::OfflineSigner;
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use nym_network_monitors_contract_common::ExecuteMsg as NetworkMonitorsExecuteMsg;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait NetworkMonitorsSigningClient {
|
|
||||||
async fn execute_network_monitors_contract(
|
|
||||||
&self,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
msg: NetworkMonitorsExecuteMsg,
|
|
||||||
memo: String,
|
|
||||||
funds: Vec<Coin>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError>;
|
|
||||||
|
|
||||||
async fn update_admin(
|
|
||||||
&self,
|
|
||||||
admin: String,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::UpdateAdmin { admin };
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::UpdateAdmin".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn authorise_network_monitor_orchestrator(
|
|
||||||
&self,
|
|
||||||
address: String,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::AuthoriseNetworkMonitorOrchestrator { address };
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::AuthoriseNetworkMonitorOrchestrator".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Announce (or rotate) the ed25519 identity key of the calling network monitor orchestrator.
|
|
||||||
///
|
|
||||||
/// The caller must already be an authorised orchestrator; the contract validates that
|
|
||||||
/// `identity_key` is a well-formed base-58 encoding of a 32-byte ed25519 public key.
|
|
||||||
async fn update_orchestrator_identity_key(
|
|
||||||
&self,
|
|
||||||
identity_key: String,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::UpdateOrchestratorIdentityKey { key: identity_key };
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::UpdateOrchestratorIdentityKey".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn revoke_network_monitor_orchestrator(
|
|
||||||
&self,
|
|
||||||
address: String,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::RevokeNetworkMonitorOrchestrator { address };
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::RevokeNetworkMonitorOrchestrator".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn authorise_network_monitor(
|
|
||||||
&self,
|
|
||||||
mixnet_address: SocketAddr,
|
|
||||||
bs58_x25519_noise: String,
|
|
||||||
noise_version: u8,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::AuthoriseNetworkMonitor {
|
|
||||||
mixnet_address,
|
|
||||||
bs58_x25519_noise,
|
|
||||||
noise_version,
|
|
||||||
};
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::AuthoriseNetworkMonitor".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn revoke_network_monitor(
|
|
||||||
&self,
|
|
||||||
address: SocketAddr,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::RevokeNetworkMonitor { address };
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::RevokeNetworkMonitor".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn revoke_all_network_monitors(
|
|
||||||
&self,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let msg = NetworkMonitorsExecuteMsg::RevokeAllNetworkMonitors;
|
|
||||||
self.execute_network_monitors_contract(
|
|
||||||
fee,
|
|
||||||
msg,
|
|
||||||
"NetworkMonitorsExecuteMsg::RevokeAllNetworkMonitors".into(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
impl<C> NetworkMonitorsSigningClient for C
|
|
||||||
where
|
|
||||||
C: SigningCosmWasmClient + NymContractsProvider + Sync,
|
|
||||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
|
||||||
{
|
|
||||||
async fn execute_network_monitors_contract(
|
|
||||||
&self,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
msg: NetworkMonitorsExecuteMsg,
|
|
||||||
memo: String,
|
|
||||||
funds: Vec<Coin>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let contract_address = &self
|
|
||||||
.network_monitors_contract_address()
|
|
||||||
.ok_or_else(|| NyxdError::unavailable_contract_address("network monitors contract"))?;
|
|
||||||
|
|
||||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
|
|
||||||
|
|
||||||
let signer_address = &self.signer_addresses()[0];
|
|
||||||
self.execute(signer_address, contract_address, &msg, fee, memo, funds)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
|
||||||
use nym_network_monitors_contract_common::ExecuteMsg;
|
|
||||||
|
|
||||||
// it's enough that this compiles and clippy is happy about it
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn all_execute_variants_are_covered<C: NetworkMonitorsSigningClient + Send + Sync>(
|
|
||||||
client: C,
|
|
||||||
msg: NetworkMonitorsExecuteMsg,
|
|
||||||
) {
|
|
||||||
match msg {
|
|
||||||
NetworkMonitorsExecuteMsg::UpdateAdmin { admin } => {
|
|
||||||
client.update_admin(admin, None).ignore()
|
|
||||||
}
|
|
||||||
ExecuteMsg::AuthoriseNetworkMonitorOrchestrator { address } => client
|
|
||||||
.authorise_network_monitor_orchestrator(address, None)
|
|
||||||
.ignore(),
|
|
||||||
ExecuteMsg::UpdateOrchestratorIdentityKey { key } => {
|
|
||||||
client.update_orchestrator_identity_key(key, None).ignore()
|
|
||||||
}
|
|
||||||
ExecuteMsg::RevokeNetworkMonitorOrchestrator { address } => client
|
|
||||||
.revoke_network_monitor_orchestrator(address, None)
|
|
||||||
.ignore(),
|
|
||||||
ExecuteMsg::AuthoriseNetworkMonitor {
|
|
||||||
mixnet_address: address,
|
|
||||||
bs58_x25519_noise,
|
|
||||||
noise_version,
|
|
||||||
} => client
|
|
||||||
.authorise_network_monitor(address, bs58_x25519_noise, noise_version, None)
|
|
||||||
.ignore(),
|
|
||||||
ExecuteMsg::RevokeNetworkMonitor { address } => {
|
|
||||||
client.revoke_network_monitor(address, None).ignore()
|
|
||||||
}
|
|
||||||
ExecuteMsg::RevokeAllNetworkMonitors => {
|
|
||||||
client.revoke_all_network_monitors(None).ignore()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-441
@@ -1,441 +0,0 @@
|
|||||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::collect_paged;
|
|
||||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
|
||||||
use crate::nyxd::error::NyxdError;
|
|
||||||
use crate::nyxd::CosmWasmClient;
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use cosmrs::AccountId;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use nym_mixnet_contract_common::NodeId;
|
|
||||||
pub use nym_node_families_contract_common::{
|
|
||||||
msg::QueryMsg as NodeFamiliesQueryMsg, AllFamilyMembersPagedResponse,
|
|
||||||
AllPastFamilyInvitationsPagedResponse, FamiliesPagedResponse, FamilyMemberRecord,
|
|
||||||
FamilyMembersPagedResponse, GlobalPastFamilyInvitationCursor, NodeFamily,
|
|
||||||
NodeFamilyByNameResponse, NodeFamilyByOwnerResponse, NodeFamilyId,
|
|
||||||
NodeFamilyMembershipResponse, NodeFamilyResponse, PastFamilyInvitation,
|
|
||||||
PastFamilyInvitationCursor, PastFamilyInvitationForNodeCursor,
|
|
||||||
PastFamilyInvitationsForNodePagedResponse, PastFamilyInvitationsPagedResponse,
|
|
||||||
PastFamilyMember, PastFamilyMemberCursor, PastFamilyMemberForNodeCursor,
|
|
||||||
PastFamilyMembersForNodePagedResponse, PastFamilyMembersPagedResponse,
|
|
||||||
PendingFamilyInvitationDetails, PendingFamilyInvitationResponse,
|
|
||||||
PendingFamilyInvitationsPagedResponse, PendingInvitationsForNodePagedResponse,
|
|
||||||
PendingInvitationsPagedResponse,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait NodeFamiliesQueryClient {
|
|
||||||
async fn query_node_families_contract<T>(
|
|
||||||
&self,
|
|
||||||
query: NodeFamiliesQueryMsg,
|
|
||||||
) -> Result<T, NyxdError>
|
|
||||||
where
|
|
||||||
for<'a> T: Deserialize<'a>;
|
|
||||||
|
|
||||||
async fn get_family_by_id(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
) -> Result<NodeFamilyResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamilyById { family_id })
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_family_by_owner(
|
|
||||||
&self,
|
|
||||||
owner: &AccountId,
|
|
||||||
) -> Result<NodeFamilyByOwnerResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamilyByOwner {
|
|
||||||
owner: owner.to_string(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_family_by_name(
|
|
||||||
&self,
|
|
||||||
name: String,
|
|
||||||
) -> Result<NodeFamilyByNameResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamilyByName { name })
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_families_paged(
|
|
||||||
&self,
|
|
||||||
start_after: Option<NodeFamilyId>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<FamiliesPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamiliesPaged {
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_family_membership(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<NodeFamilyMembershipResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamilyMembership { node_id })
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_family_members_paged(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
start_after: Option<NodeId>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<FamilyMembersPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetFamilyMembersPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_family_members_paged(
|
|
||||||
&self,
|
|
||||||
start_after: Option<NodeId>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<AllFamilyMembersPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetAllFamilyMembersPaged {
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_pending_invitation(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<PendingFamilyInvitationResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPendingInvitation {
|
|
||||||
family_id,
|
|
||||||
node_id,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_pending_invitations_for_family_paged(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
start_after: Option<NodeId>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PendingFamilyInvitationsPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(
|
|
||||||
NodeFamiliesQueryMsg::GetPendingInvitationsForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_pending_invitations_for_node_paged(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
start_after: Option<NodeFamilyId>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PendingInvitationsForNodePagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPendingInvitationsForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_pending_invitations_paged(
|
|
||||||
&self,
|
|
||||||
start_after: Option<(NodeFamilyId, NodeId)>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PendingInvitationsPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetAllPendingInvitationsPaged {
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_past_invitations_for_family_paged(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
start_after: Option<PastFamilyInvitationCursor>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PastFamilyInvitationsPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPastInvitationsForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_past_invitations_for_node_paged(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
start_after: Option<PastFamilyInvitationForNodeCursor>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PastFamilyInvitationsForNodePagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPastInvitationsForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_invitations_paged(
|
|
||||||
&self,
|
|
||||||
start_after: Option<GlobalPastFamilyInvitationCursor>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<AllPastFamilyInvitationsPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetAllPastInvitationsPaged {
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_past_members_for_family_paged(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
start_after: Option<PastFamilyMemberCursor>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PastFamilyMembersPagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPastMembersForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_past_members_for_node_paged(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
start_after: Option<PastFamilyMemberForNodeCursor>,
|
|
||||||
limit: Option<u32>,
|
|
||||||
) -> Result<PastFamilyMembersForNodePagedResponse, NyxdError> {
|
|
||||||
self.query_node_families_contract(NodeFamiliesQueryMsg::GetPastMembersForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// extension trait to the query client to deal with the paged queries
|
|
||||||
// (it didn't feel appropriate to combine it with the existing trait)
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait PagedNodeFamiliesQueryClient: NodeFamiliesQueryClient {
|
|
||||||
async fn get_all_families(&self) -> Result<Vec<NodeFamily>, NyxdError> {
|
|
||||||
collect_paged!(self, get_families_paged, families)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_family_members_for_family(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
) -> Result<Vec<FamilyMemberRecord>, NyxdError> {
|
|
||||||
collect_paged!(self, get_family_members_paged, members, family_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_family_members(&self) -> Result<Vec<FamilyMemberRecord>, NyxdError> {
|
|
||||||
collect_paged!(self, get_all_family_members_paged, members)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_pending_invitations_for_family(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
) -> Result<Vec<PendingFamilyInvitationDetails>, NyxdError> {
|
|
||||||
collect_paged!(
|
|
||||||
self,
|
|
||||||
get_pending_invitations_for_family_paged,
|
|
||||||
invitations,
|
|
||||||
family_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_pending_invitations_for_node(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<Vec<PendingFamilyInvitationDetails>, NyxdError> {
|
|
||||||
collect_paged!(
|
|
||||||
self,
|
|
||||||
get_pending_invitations_for_node_paged,
|
|
||||||
invitations,
|
|
||||||
node_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_pending_invitations(
|
|
||||||
&self,
|
|
||||||
) -> Result<Vec<PendingFamilyInvitationDetails>, NyxdError> {
|
|
||||||
collect_paged!(self, get_all_pending_invitations_paged, invitations)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_invitations_for_family(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
) -> Result<Vec<PastFamilyInvitation>, NyxdError> {
|
|
||||||
collect_paged!(
|
|
||||||
self,
|
|
||||||
get_past_invitations_for_family_paged,
|
|
||||||
invitations,
|
|
||||||
family_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_invitations_for_node(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<Vec<PastFamilyInvitation>, NyxdError> {
|
|
||||||
collect_paged!(
|
|
||||||
self,
|
|
||||||
get_past_invitations_for_node_paged,
|
|
||||||
invitations,
|
|
||||||
node_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_invitations(&self) -> Result<Vec<PastFamilyInvitation>, NyxdError> {
|
|
||||||
collect_paged!(self, get_all_past_invitations_paged, invitations)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_members_for_family(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
) -> Result<Vec<PastFamilyMember>, NyxdError> {
|
|
||||||
collect_paged!(self, get_past_members_for_family_paged, members, family_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_all_past_members_for_node(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
) -> Result<Vec<PastFamilyMember>, NyxdError> {
|
|
||||||
collect_paged!(self, get_past_members_for_node_paged, members, node_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T> PagedNodeFamiliesQueryClient for T where T: NodeFamiliesQueryClient {}
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
impl<C> NodeFamiliesQueryClient for C
|
|
||||||
where
|
|
||||||
C: CosmWasmClient + NymContractsProvider + Send + Sync,
|
|
||||||
{
|
|
||||||
async fn query_node_families_contract<T>(
|
|
||||||
&self,
|
|
||||||
query: NodeFamiliesQueryMsg,
|
|
||||||
) -> Result<T, NyxdError>
|
|
||||||
where
|
|
||||||
for<'a> T: Deserialize<'a>,
|
|
||||||
{
|
|
||||||
let node_families_contract_address = &self
|
|
||||||
.node_families_contract_address()
|
|
||||||
.ok_or_else(|| NyxdError::unavailable_contract_address("node families contract"))?;
|
|
||||||
self.query_contract_smart(node_families_contract_address, &query)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
|
||||||
use nym_node_families_contract_common::QueryMsg;
|
|
||||||
|
|
||||||
// it's enough that this compiles and clippy is happy about it
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn all_query_variants_are_covered<C: NodeFamiliesQueryClient + Send + Sync>(
|
|
||||||
client: C,
|
|
||||||
msg: NodeFamiliesQueryMsg,
|
|
||||||
) {
|
|
||||||
match msg {
|
|
||||||
NodeFamiliesQueryMsg::GetFamilyById { family_id } => {
|
|
||||||
client.get_family_by_id(family_id).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetFamilyByOwner { owner } => {
|
|
||||||
client.get_family_by_owner(&owner.parse().unwrap()).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetFamilyByName { name } => {
|
|
||||||
client.get_family_by_name(name).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetFamiliesPaged { start_after, limit } => {
|
|
||||||
client.get_families_paged(start_after, limit).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetFamilyMembership { node_id } => {
|
|
||||||
client.get_family_membership(node_id).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetFamilyMembersPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_family_members_paged(family_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetAllFamilyMembersPaged { start_after, limit } => client
|
|
||||||
.get_all_family_members_paged(start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetPendingInvitation { family_id, node_id } => {
|
|
||||||
client.get_pending_invitation(family_id, node_id).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesQueryMsg::GetPendingInvitationsForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_pending_invitations_for_family_paged(family_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetPendingInvitationsForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_pending_invitations_for_node_paged(node_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetAllPendingInvitationsPaged { start_after, limit } => client
|
|
||||||
.get_all_pending_invitations_paged(start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetPastInvitationsForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_past_invitations_for_family_paged(family_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetPastInvitationsForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_past_invitations_for_node_paged(node_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetAllPastInvitationsPaged { start_after, limit } => client
|
|
||||||
.get_all_past_invitations_paged(start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesQueryMsg::GetPastMembersForFamilyPaged {
|
|
||||||
family_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_past_members_for_family_paged(family_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
QueryMsg::GetPastMembersForNodePaged {
|
|
||||||
node_id,
|
|
||||||
start_after,
|
|
||||||
limit,
|
|
||||||
} => client
|
|
||||||
.get_past_members_for_node_paged(node_id, start_after, limit)
|
|
||||||
.ignore(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-281
@@ -1,281 +0,0 @@
|
|||||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
use crate::nyxd::coin::Coin;
|
|
||||||
use crate::nyxd::contract_traits::NymContractsProvider;
|
|
||||||
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
|
|
||||||
use crate::nyxd::error::NyxdError;
|
|
||||||
use crate::nyxd::{Fee, SigningCosmWasmClient};
|
|
||||||
use crate::signing::signer::OfflineSigner;
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use nym_mixnet_contract_common::NodeId;
|
|
||||||
use nym_node_families_contract_common::{
|
|
||||||
Config, ExecuteMsg as NodeFamiliesExecuteMsg, NodeFamilyId,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
pub trait NodeFamiliesSigningClient {
|
|
||||||
async fn execute_node_families_contract(
|
|
||||||
&self,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
msg: NodeFamiliesExecuteMsg,
|
|
||||||
memo: String,
|
|
||||||
funds: Vec<Coin>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError>;
|
|
||||||
|
|
||||||
async fn update_node_families_config(
|
|
||||||
&self,
|
|
||||||
config: Config,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::UpdateConfig { config },
|
|
||||||
"NodeFamiliesContract::UpdateConfig".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_family(
|
|
||||||
&self,
|
|
||||||
name: String,
|
|
||||||
description: String,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
creation_fee: Vec<Coin>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::CreateFamily { name, description },
|
|
||||||
"NodeFamiliesContract::CreateFamily".to_string(),
|
|
||||||
creation_fee,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the name and/or description of the caller's family. Each
|
|
||||||
/// argument follows `None = keep` / `Some(_) = replace` semantics; a
|
|
||||||
/// call with both `None` is a server-side no-op.
|
|
||||||
async fn update_family(
|
|
||||||
&self,
|
|
||||||
updated_name: Option<String>,
|
|
||||||
updated_description: Option<String>,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::UpdateFamily {
|
|
||||||
updated_name,
|
|
||||||
updated_description,
|
|
||||||
},
|
|
||||||
"NodeFamiliesContract::UpdateFamily".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn disband_family(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::DisbandFamily {},
|
|
||||||
"NodeFamiliesContract::DisbandFamily".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn invite_to_family(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
validity_secs: Option<u64>,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::InviteToFamily {
|
|
||||||
node_id,
|
|
||||||
validity_secs,
|
|
||||||
},
|
|
||||||
"NodeFamiliesContract::InviteToFamily".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn revoke_family_invitation(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::RevokeFamilyInvitation { node_id },
|
|
||||||
"NodeFamiliesContract::RevokeFamilyInvitation".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn accept_family_invitation(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::AcceptFamilyInvitation { family_id, node_id },
|
|
||||||
"NodeFamiliesContract::AcceptFamilyInvitation".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn reject_family_invitation(
|
|
||||||
&self,
|
|
||||||
family_id: NodeFamilyId,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::RejectFamilyInvitation { family_id, node_id },
|
|
||||||
"NodeFamiliesContract::RejectFamilyInvitation".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn leave_family(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::LeaveFamily { node_id },
|
|
||||||
"NodeFamiliesContract::LeaveFamily".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn kick_from_family(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::KickFromFamily { node_id },
|
|
||||||
"NodeFamiliesContract::KickFromFamily".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cross-contract callback fired by the mixnet contract on node unbonding.
|
|
||||||
/// Exposed for completeness; the families contract rejects this call from
|
|
||||||
/// any sender other than the configured mixnet contract address.
|
|
||||||
async fn on_nym_node_unbond(
|
|
||||||
&self,
|
|
||||||
node_id: NodeId,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
self.execute_node_families_contract(
|
|
||||||
fee,
|
|
||||||
NodeFamiliesExecuteMsg::OnNymNodeUnbond { node_id },
|
|
||||||
"NodeFamiliesContract::OnNymNodeUnbond".to_string(),
|
|
||||||
vec![],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
||||||
impl<C> NodeFamiliesSigningClient for C
|
|
||||||
where
|
|
||||||
C: SigningCosmWasmClient + NymContractsProvider + Sync,
|
|
||||||
NyxdError: From<<Self as OfflineSigner>::Error>,
|
|
||||||
{
|
|
||||||
async fn execute_node_families_contract(
|
|
||||||
&self,
|
|
||||||
fee: Option<Fee>,
|
|
||||||
msg: NodeFamiliesExecuteMsg,
|
|
||||||
memo: String,
|
|
||||||
funds: Vec<Coin>,
|
|
||||||
) -> Result<ExecuteResult, NyxdError> {
|
|
||||||
let node_families_contract_address = &self
|
|
||||||
.node_families_contract_address()
|
|
||||||
.ok_or_else(|| NyxdError::unavailable_contract_address("node families contract"))?;
|
|
||||||
|
|
||||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
|
|
||||||
|
|
||||||
let signer_address = &self.signer_addresses()[0];
|
|
||||||
self.execute(
|
|
||||||
signer_address,
|
|
||||||
node_families_contract_address,
|
|
||||||
&msg,
|
|
||||||
fee,
|
|
||||||
memo,
|
|
||||||
funds,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
|
||||||
use nym_node_families_contract_common::ExecuteMsg;
|
|
||||||
|
|
||||||
// it's enough that this compiles and clippy is happy about it
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn all_execute_variants_are_covered<C: NodeFamiliesSigningClient + Send + Sync>(
|
|
||||||
client: C,
|
|
||||||
msg: NodeFamiliesExecuteMsg,
|
|
||||||
) {
|
|
||||||
match msg {
|
|
||||||
NodeFamiliesExecuteMsg::UpdateConfig { config } => {
|
|
||||||
client.update_node_families_config(config, None).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesExecuteMsg::CreateFamily { name, description } => client
|
|
||||||
.create_family(name, description, None, vec![])
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::UpdateFamily {
|
|
||||||
updated_name,
|
|
||||||
updated_description,
|
|
||||||
} => client
|
|
||||||
.update_family(updated_name, updated_description, None)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::DisbandFamily {} => client.disband_family(None).ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::InviteToFamily {
|
|
||||||
node_id,
|
|
||||||
validity_secs,
|
|
||||||
} => client
|
|
||||||
.invite_to_family(node_id, validity_secs, None)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::RevokeFamilyInvitation { node_id } => {
|
|
||||||
client.revoke_family_invitation(node_id, None).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesExecuteMsg::AcceptFamilyInvitation { family_id, node_id } => client
|
|
||||||
.accept_family_invitation(family_id, node_id, None)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::RejectFamilyInvitation { family_id, node_id } => client
|
|
||||||
.reject_family_invitation(family_id, node_id, None)
|
|
||||||
.ignore(),
|
|
||||||
NodeFamiliesExecuteMsg::LeaveFamily { node_id } => {
|
|
||||||
client.leave_family(node_id, None).ignore()
|
|
||||||
}
|
|
||||||
NodeFamiliesExecuteMsg::KickFromFamily { node_id } => {
|
|
||||||
client.kick_from_family(node_id, None).ignore()
|
|
||||||
}
|
|
||||||
ExecuteMsg::OnNymNodeUnbond { node_id } => {
|
|
||||||
client.on_nym_node_unbond(node_id, None).ignore()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -36,7 +36,7 @@ pub mod logs;
|
|||||||
pub mod module_traits;
|
pub mod module_traits;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct SigningClientOptions {
|
pub(crate) struct SigningClientOptions {
|
||||||
gas_price: GasPrice,
|
gas_price: GasPrice,
|
||||||
simulated_gas_multiplier: f32,
|
simulated_gas_multiplier: f32,
|
||||||
@@ -80,17 +80,6 @@ impl<C, S> MaybeSigningClient<C, S> {
|
|||||||
opts,
|
opts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_query_client(&self) -> MaybeSigningClient<C, NoSigner>
|
|
||||||
where
|
|
||||||
C: Clone,
|
|
||||||
{
|
|
||||||
MaybeSigningClient {
|
|
||||||
client: self.client.clone(),
|
|
||||||
signer: Default::default(),
|
|
||||||
opts: self.opts.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http-client")]
|
#[cfg(feature = "http-client")]
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ use async_trait::async_trait;
|
|||||||
use cosmrs::tendermint::{abci, evidence::Evidence, Genesis};
|
use cosmrs::tendermint::{abci, evidence::Evidence, Genesis};
|
||||||
use cosmrs::tx::{Raw, SignDoc};
|
use cosmrs::tx::{Raw, SignDoc};
|
||||||
use cosmwasm_std::Addr;
|
use cosmwasm_std::Addr;
|
||||||
use nym_contracts_common::build_information::CONTRACT_BUILD_INFO_STORAGE_KEY;
|
|
||||||
use nym_contracts_common::ContractBuildInformation;
|
|
||||||
use nym_network_defaults::{ChainDetails, NymNetworkDetails};
|
use nym_network_defaults::{ChainDetails, NymNetworkDetails};
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@@ -42,7 +40,6 @@ pub use crate::nyxd::{
|
|||||||
fee::Fee,
|
fee::Fee,
|
||||||
};
|
};
|
||||||
pub use crate::rpc::TendermintRpcClient;
|
pub use crate::rpc::TendermintRpcClient;
|
||||||
pub use bip39;
|
|
||||||
pub use coin::Coin;
|
pub use coin::Coin;
|
||||||
pub use cosmrs::{
|
pub use cosmrs::{
|
||||||
bank::MsgSend,
|
bank::MsgSend,
|
||||||
@@ -73,19 +70,14 @@ pub use tendermint_rpc::{
|
|||||||
Paging, Request, Response, SimpleRequest,
|
Paging, Request, Response, SimpleRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use nym_ecash_contract_common;
|
|
||||||
pub use nym_mixnet_contract_common;
|
|
||||||
pub use nym_multisig_contract_common;
|
|
||||||
pub use nym_network_monitors_contract_common;
|
|
||||||
pub use nym_performance_contract_common;
|
|
||||||
pub use nym_vesting_contract_common;
|
|
||||||
|
|
||||||
#[cfg(feature = "http-client")]
|
#[cfg(feature = "http-client")]
|
||||||
use crate::http_client;
|
use crate::http_client;
|
||||||
#[cfg(feature = "http-client")]
|
#[cfg(feature = "http-client")]
|
||||||
use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
|
use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
|
||||||
#[cfg(feature = "http-client")]
|
#[cfg(feature = "http-client")]
|
||||||
use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
||||||
|
use nym_contracts_common::build_information::CONTRACT_BUILD_INFO_STORAGE_KEY;
|
||||||
|
use nym_contracts_common::ContractBuildInformation;
|
||||||
|
|
||||||
pub mod coin;
|
pub mod coin;
|
||||||
pub mod contract_traits;
|
pub mod contract_traits;
|
||||||
@@ -270,16 +262,6 @@ impl<C, S> NyxdClient<C, S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_query_client(&self) -> NyxdClient<C>
|
|
||||||
where
|
|
||||||
C: Clone,
|
|
||||||
{
|
|
||||||
NyxdClient {
|
|
||||||
client: self.client.clone_query_client(),
|
|
||||||
config: self.config.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_config(&self) -> &Config {
|
pub fn current_config(&self) -> &Config {
|
||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
@@ -304,17 +286,9 @@ impl<C, S> NyxdClient<C, S> {
|
|||||||
self.config.contracts.multisig_contract_address = Some(address);
|
self.config.contracts.multisig_contract_address = Some(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_node_families_contract_address(&mut self, address: AccountId) {
|
|
||||||
self.config.contracts.node_families_contract_address = Some(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
|
pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
|
||||||
self.config.simulated_gas_multiplier = multiplier;
|
self.config.simulated_gas_multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_nym_contracts(&self) -> TypedNymContracts {
|
|
||||||
self.config.contracts.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, S> NymContractsProvider for NyxdClient<C, S> {
|
impl<C, S> NymContractsProvider for NyxdClient<C, S> {
|
||||||
@@ -329,19 +303,6 @@ impl<C, S> NymContractsProvider for NyxdClient<C, S> {
|
|||||||
fn performance_contract_address(&self) -> Option<&AccountId> {
|
fn performance_contract_address(&self) -> Option<&AccountId> {
|
||||||
self.config.contracts.performance_contract_address.as_ref()
|
self.config.contracts.performance_contract_address.as_ref()
|
||||||
}
|
}
|
||||||
fn network_monitors_contract_address(&self) -> Option<&AccountId> {
|
|
||||||
self.config
|
|
||||||
.contracts
|
|
||||||
.network_monitors_contract_address
|
|
||||||
.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_families_contract_address(&self) -> Option<&AccountId> {
|
|
||||||
self.config
|
|
||||||
.contracts
|
|
||||||
.node_families_contract_address
|
|
||||||
.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ecash_contract_address(&self) -> Option<&AccountId> {
|
fn ecash_contract_address(&self) -> Option<&AccountId> {
|
||||||
self.config.contracts.ecash_contract_address.as_ref()
|
self.config.contracts.ecash_contract_address.as_ref()
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-cli-commands"
|
name = "nym-cli-commands"
|
||||||
description = "Common commands crate used by the nym-cli tool for interacting with the Nyx Cosmos SDK blockchain and Mixnet endpoints"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Common commands crate used by the nym-cli tool for interacting with the Nyx Cosmos SDK blockchain and Mixnet endpoints"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ pub struct Args {
|
|||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub vesting_contract_address: Option<AccountId>,
|
pub vesting_contract_address: Option<AccountId>,
|
||||||
|
|
||||||
#[clap(long)]
|
|
||||||
pub node_families_contract_address: Option<AccountId>,
|
|
||||||
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub rewarding_denom: Option<String>,
|
pub rewarding_denom: Option<String>,
|
||||||
|
|
||||||
@@ -133,14 +130,6 @@ pub async fn generate(args: Args) {
|
|||||||
.expect("Failed converting vesting contract address to AccountId")
|
.expect("Failed converting vesting contract address to AccountId")
|
||||||
});
|
});
|
||||||
|
|
||||||
let node_families_contract_address = args.node_families_contract_address.unwrap_or_else(|| {
|
|
||||||
let address =
|
|
||||||
std::env::var(nym_network_defaults::var_names::NODE_FAMILIES_CONTRACT_ADDRESS)
|
|
||||||
.expect("node families contract address has to be set");
|
|
||||||
AccountId::from_str(address.as_str())
|
|
||||||
.expect("Failed converting node families contract address to AccountId")
|
|
||||||
});
|
|
||||||
|
|
||||||
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
|
let rewarding_denom = args.rewarding_denom.unwrap_or_else(|| {
|
||||||
std::env::var(nym_network_defaults::var_names::MIX_DENOM)
|
std::env::var(nym_network_defaults::var_names::MIX_DENOM)
|
||||||
.expect("Rewarding (mix) denom has to be set")
|
.expect("Rewarding (mix) denom has to be set")
|
||||||
@@ -153,7 +142,6 @@ pub async fn generate(args: Args) {
|
|||||||
let instantiate_msg = InstantiateMsg {
|
let instantiate_msg = InstantiateMsg {
|
||||||
rewarding_validator_address: rewarding_validator_address.to_string(),
|
rewarding_validator_address: rewarding_validator_address.to_string(),
|
||||||
vesting_contract_address: vesting_contract_address.to_string(),
|
vesting_contract_address: vesting_contract_address.to_string(),
|
||||||
node_families_contract_address: node_families_contract_address.to_string(),
|
|
||||||
rewarding_denom,
|
rewarding_denom,
|
||||||
epochs_in_interval: args.epochs_in_interval,
|
epochs_in_interval: args.epochs_in_interval,
|
||||||
epoch_duration: Duration::from_secs(args.epoch_duration),
|
epoch_duration: Duration::from_secs(args.epoch_duration),
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-config"
|
name = "nym-config"
|
||||||
description = "Config related helpers and functions"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
repository.workspace = true
|
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
description = "Config related helpers and functions"
|
||||||
rust-version.workspace = true
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-coconut-dkg-common"
|
name = "nym-coconut-dkg-common"
|
||||||
description = "Common crate for Nym's DKG cosmwasm contract"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Common crate for Nym's DKG cosmwasm contract"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version = "1.85"
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-contracts-common-testing"
|
name = "nym-contracts-common-testing"
|
||||||
description = "Common crate for cosmwasm contract tests"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
|
||||||
license.workspace = true
|
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version = "1.85"
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
readme.workspace = true
|
readme.workspace = true
|
||||||
publish = true
|
description = "Common crate for cosmwasm contract tests"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|||||||
@@ -26,14 +26,6 @@ pub trait ContractOpts {
|
|||||||
|
|
||||||
fn addr_make(&self, input: &str) -> Addr;
|
fn addr_make(&self, input: &str) -> Addr;
|
||||||
|
|
||||||
fn make_sender_with_funds(&self, input: &str, funds: &[Coin]) -> MessageInfo {
|
|
||||||
message_info(&self.addr_make(input), funds)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_sender(&self, input: &str) -> MessageInfo {
|
|
||||||
self.make_sender_with_funds(input, &[])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deps_mut_env(&mut self) -> (DepsMut<'_>, Env) {
|
fn deps_mut_env(&mut self) -> (DepsMut<'_>, Env) {
|
||||||
let env = self.env().clone();
|
let env = self.env().clone();
|
||||||
(self.deps_mut(), env)
|
(self.deps_mut(), env)
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-contracts-common"
|
name = "nym-contracts-common"
|
||||||
description = "Common library for Nym cosmwasm contracts"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors = { workspace = true }
|
description = "Common library for Nym cosmwasm contracts"
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
authors = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
repository = { workspace = true }
|
repository = { workspace = true }
|
||||||
homepage.workspace = true
|
|
||||||
documentation.workspace = true
|
|
||||||
rust-version = "1.85"
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bs58 = { workspace = true }
|
bs58 = { workspace = true }
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
name = "easy-addr"
|
name = "easy-addr"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
|
||||||
publish = false
|
publish = false
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nym-ecash-contract-common"
|
name = "nym-ecash-contract-common"
|
||||||
description = "Common crate for Nym's ecash/zknym cosmwasm contract"
|
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
description = "Common crate for Nym's ecash/zknym cosmwasm contract"
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
documentation.workspace = true
|
documentation.workspace = true
|
||||||
rust-version = "1.85"
|
|
||||||
readme.workspace = true
|
|
||||||
publish = true
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
//! Blacklist types. **The blacklist surface is stubbed today** - the execute
|
|
||||||
//! handlers always return `UnimplementedBlacklisting` and the storage map is
|
|
||||||
//! never populated. These types are kept for the planned redesign.
|
|
||||||
|
|
||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
|
|
||||||
/// Public-key + metadata pair surfaced by `GetBlacklistedAccount` /
|
|
||||||
/// `GetBlacklistPaged`. Always empty on a freshly deployed contract.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct BlacklistedAccount {
|
pub struct BlacklistedAccount {
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
@@ -21,8 +15,6 @@ impl From<(String, Blacklisting)> for BlacklistedAccount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Per-key blacklist record: the multisig proposal that approved it and the
|
|
||||||
/// block height at which finalisation landed (None until finalised).
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct Blacklisting {
|
pub struct Blacklisting {
|
||||||
pub proposal_id: u64,
|
pub proposal_id: u64,
|
||||||
@@ -44,8 +36,6 @@ impl BlacklistedAccount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Page of blacklist entries returned by `GetBlacklistPaged`. Always empty on
|
|
||||||
/// a freshly deployed contract.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct PagedBlacklistedAccountResponse {
|
pub struct PagedBlacklistedAccountResponse {
|
||||||
pub accounts: Vec<BlacklistedAccount>,
|
pub accounts: Vec<BlacklistedAccount>,
|
||||||
@@ -69,8 +59,6 @@ impl PagedBlacklistedAccountResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Response shape for `GetBlacklistedAccount`. `account` is `None` for any
|
|
||||||
/// key not present in the (currently always-empty) blacklist.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct BlacklistedAccountResponse {
|
pub struct BlacklistedAccountResponse {
|
||||||
pub account: Option<Blacklisting>,
|
pub account: Option<Blacklisting>,
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::Coin;
|
use cosmwasm_std::Coin;
|
||||||
|
|
||||||
/// Pool-level deposit accounting. Updated by every successful
|
|
||||||
/// `DepositTicketBookFunds` and (for the unredeemed-tickets counter) by every
|
|
||||||
/// successful legacy `RedeemTickets`.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct PoolCounters {
|
pub struct PoolCounters {
|
||||||
/// Represents the total amount of funds deposited into the contract.
|
/// Represents the total amount of funds deposited into the contract.
|
||||||
@@ -17,6 +14,5 @@ pub struct PoolCounters {
|
|||||||
|
|
||||||
/// Represents the total amount of tickets requested to be redeemed from the contract and get moved into the holding account,
|
/// Represents the total amount of tickets requested to be redeemed from the contract and get moved into the holding account,
|
||||||
/// after that functionality got disabled.
|
/// after that functionality got disabled.
|
||||||
#[serde(default)]
|
|
||||||
pub tickets_requested_and_not_redeemed: u64,
|
pub tickets_requested_and_not_redeemed: u64,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,8 @@ use crate::error::EcashContractError;
|
|||||||
use cosmwasm_schema::cw_serde;
|
use cosmwasm_schema::cw_serde;
|
||||||
use cosmwasm_std::{StdError, StdResult};
|
use cosmwasm_std::{StdError, StdResult};
|
||||||
|
|
||||||
/// Sequential identifier assigned to every accepted deposit. Starts at 0 and
|
|
||||||
/// is never recycled.
|
|
||||||
pub type DepositId = u32;
|
pub type DepositId = u32;
|
||||||
|
|
||||||
/// Opaque on-chain record of a deposit: the depositor-claimed bs58-encoded
|
|
||||||
/// ed25519 identity public key. The contract does not verify control of the
|
|
||||||
/// corresponding private key.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct Deposit {
|
pub struct Deposit {
|
||||||
pub bs58_encoded_ed25519_pubkey: String,
|
pub bs58_encoded_ed25519_pubkey: String,
|
||||||
@@ -24,8 +19,6 @@ impl Deposit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a bs58-encoded ed25519 public key to its 32-byte raw form.
|
|
||||||
/// Surfaces `MalformedEd25519Identity` on any bs58 / length failure.
|
|
||||||
pub fn get_ed25519_pubkey_bytes(raw: &str) -> Result<[u8; 32], EcashContractError> {
|
pub fn get_ed25519_pubkey_bytes(raw: &str) -> Result<[u8; 32], EcashContractError> {
|
||||||
let mut ed25519_pubkey_bytes = [0u8; 32];
|
let mut ed25519_pubkey_bytes = [0u8; 32];
|
||||||
bs58::decode(raw)
|
bs58::decode(raw)
|
||||||
@@ -39,13 +32,10 @@ impl Deposit {
|
|||||||
bs58::encode(raw).into_string()
|
bs58::encode(raw).into_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode this deposit's identity key to its 32-byte raw form for storage.
|
|
||||||
pub fn to_bytes(&self) -> Result<[u8; 32], EcashContractError> {
|
pub fn to_bytes(&self) -> Result<[u8; 32], EcashContractError> {
|
||||||
Self::get_ed25519_pubkey_bytes(&self.bs58_encoded_ed25519_pubkey)
|
Self::get_ed25519_pubkey_bytes(&self.bs58_encoded_ed25519_pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconstruct a `Deposit` from a raw 32-byte ed25519 pubkey as stored
|
|
||||||
/// under the `"deposit"` namespace.
|
|
||||||
pub fn try_from_bytes(bytes: &[u8]) -> StdResult<Self> {
|
pub fn try_from_bytes(bytes: &[u8]) -> StdResult<Self> {
|
||||||
if bytes.len() != 32 {
|
if bytes.len() != 32 {
|
||||||
return Err(StdError::generic_err("malformed deposit data"));
|
return Err(StdError::generic_err("malformed deposit data"));
|
||||||
@@ -57,16 +47,12 @@ impl Deposit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Response shape for `GetLatestDeposit`. `deposit` is `None` on a freshly
|
|
||||||
/// deployed contract.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LatestDepositResponse {
|
pub struct LatestDepositResponse {
|
||||||
pub deposit: Option<DepositData>,
|
pub deposit: Option<DepositData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Response shape for `GetDeposit { deposit_id }`. `deposit` is `None` when
|
|
||||||
/// the id has not yet been assigned (`id >= total_deposits_made`).
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct DepositResponse {
|
pub struct DepositResponse {
|
||||||
pub id: DepositId,
|
pub id: DepositId,
|
||||||
@@ -74,8 +60,6 @@ pub struct DepositResponse {
|
|||||||
pub deposit: Option<Deposit>,
|
pub deposit: Option<Deposit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `(deposit_id, deposit)` pair surfaced by the latest-deposit and paginated
|
|
||||||
/// deposit queries.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct DepositData {
|
pub struct DepositData {
|
||||||
pub id: DepositId,
|
pub id: DepositId,
|
||||||
@@ -89,8 +73,6 @@ impl From<(DepositId, Deposit)> for DepositData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Page of deposits returned by `GetDepositsPaged`. `start_next_after` is the
|
|
||||||
/// id of the last returned entry; pass it as the next call's `start_after`.
|
|
||||||
#[cw_serde]
|
#[cw_serde]
|
||||||
pub struct PagedDepositsResponse {
|
pub struct PagedDepositsResponse {
|
||||||
pub deposits: Vec<DepositData>,
|
pub deposits: Vec<DepositData>,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user