Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1266f39446 |
@@ -1,75 +0,0 @@
|
||||
name: ci-nym-wallet-storybook
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'nym-wallet/**'
|
||||
- '.github/workflows/ci-nym-wallet-storybook.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- 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 stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- 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/"
|
||||
|
||||
- name: Matrix - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
|
||||
- name: Matrix - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: nym-wallet
|
||||
NYM_PROJECT_NAME: "nym-wallet"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "wallet-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
@@ -5,8 +5,6 @@
|
||||
>
|
||||
> ➡️➡️➡️➡️➡️ **View output:**
|
||||
>
|
||||
> `storybook`: https://{{ env.NYM_CI_WWW_LOCATION }}.{{ env.NYM_CI_WWW_BASE }}
|
||||
>
|
||||
> `branch` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/tree/{{ env.GIT_BRANCH_NAME }}
|
||||
>
|
||||
> `commit` {{ env.GITHUB_SERVER_URL }}/{{ env.GITHUB_REPOSITORY }}/commit/{{ env.GITHUB_SHA }}
|
||||
|
||||
@@ -1,686 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Nym is a privacy platform that uses mixnet technology to protect against metadata surveillance. The platform consists of several key components:
|
||||
- Mixnet nodes (mixnodes) for packet mixing
|
||||
- Gateways (entry/exit points for the network)
|
||||
- Clients for interacting with the network
|
||||
- Network monitoring tools
|
||||
- Validators for network consensus
|
||||
- Various service providers and integrations
|
||||
|
||||
## Build Commands
|
||||
|
||||
### Rust Components
|
||||
|
||||
```bash
|
||||
# Default build (debug)
|
||||
cargo build
|
||||
|
||||
# Release build
|
||||
cargo build --release
|
||||
|
||||
# Build a specific package
|
||||
cargo build -p <package-name>
|
||||
|
||||
# Build main components
|
||||
make build
|
||||
|
||||
# Build release versions of main binaries and contracts
|
||||
make build-release
|
||||
|
||||
# Build specific binaries
|
||||
make build-nym-cli
|
||||
cargo build -p nym-node --release
|
||||
cargo build -p nym-api --release
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run clippy, unit tests, and formatting
|
||||
make test
|
||||
|
||||
# Run all tests including slow tests
|
||||
make test-all
|
||||
|
||||
# Run clippy on all workspaces
|
||||
make clippy
|
||||
|
||||
# Run unit tests for a specific package
|
||||
cargo test -p <package-name>
|
||||
|
||||
# Run only expensive/ignored tests
|
||||
cargo test --workspace -- --ignored
|
||||
|
||||
# Run API tests
|
||||
dotenv -f envs/sandbox.env -- cargo test --test public-api-tests
|
||||
|
||||
# Run tests with specific log level
|
||||
RUST_LOG=debug cargo test -p <package-name>
|
||||
|
||||
# Run specific test scripts
|
||||
./nym-node/tests/test_apis.sh
|
||||
./scripts/wireguard-exit-policy/exit-policy-tests.sh
|
||||
```
|
||||
|
||||
### Linting and Formatting
|
||||
|
||||
```bash
|
||||
# Run rustfmt on all code
|
||||
make fmt
|
||||
|
||||
# Check formatting without modifying
|
||||
cargo fmt --all -- --check
|
||||
|
||||
# Run clippy with all targets
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
# TypeScript linting
|
||||
yarn lint
|
||||
yarn lint:fix
|
||||
yarn types:lint:fix
|
||||
|
||||
# Check dependencies for security/licensing issues
|
||||
cargo deny check
|
||||
```
|
||||
|
||||
### WASM Components
|
||||
|
||||
```bash
|
||||
# Build all WASM components
|
||||
make sdk-wasm-build
|
||||
|
||||
# Build TypeScript SDK
|
||||
yarn build:sdk
|
||||
npx lerna run --scope @nymproject/sdk build --stream
|
||||
|
||||
# Build and test WASM components
|
||||
make sdk-wasm
|
||||
|
||||
# Build specific WASM packages
|
||||
cd wasm/client && make
|
||||
cd wasm/mix-fetch && make
|
||||
cd wasm/node-tester && make
|
||||
```
|
||||
|
||||
### Contract Development
|
||||
|
||||
```bash
|
||||
# Build all contracts
|
||||
make contracts
|
||||
|
||||
# Build contracts in release mode
|
||||
make build-release-contracts
|
||||
|
||||
# Generate contract schemas
|
||||
make contract-schema
|
||||
|
||||
# Run wasm-opt on contracts
|
||||
make wasm-opt-contracts
|
||||
|
||||
# Check contracts with cosmwasm-check
|
||||
make cosmwasm-check-contracts
|
||||
```
|
||||
|
||||
### Running Components
|
||||
|
||||
```bash
|
||||
# Run nym-node as a mixnode
|
||||
cargo run -p nym-node -- run --mode mixnode
|
||||
|
||||
# Run nym-node as a gateway
|
||||
cargo run -p nym-node -- run --mode gateway
|
||||
|
||||
# Run the network monitor
|
||||
cargo run -p nym-network-monitor
|
||||
|
||||
# Run the API server
|
||||
cargo run -p nym-api
|
||||
|
||||
# Run with specific environment
|
||||
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||
|
||||
# Start a local network
|
||||
./scripts/localnet_start.sh
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The Nym platform consists of various components organized as a monorepo:
|
||||
|
||||
1. **Core Mixnet Infrastructure**:
|
||||
- `nym-node`: Core binary supporting mixnode and gateway modes
|
||||
- `common/nymsphinx`: Implementation of the Sphinx packet format
|
||||
- `common/topology`: Network topology management
|
||||
- `common/types`: Shared data types across components
|
||||
|
||||
2. **Network Monitoring**:
|
||||
- `nym-network-monitor`: Monitors the network's reliability and performance
|
||||
- `nym-api`: API server for network stats and monitoring data
|
||||
- Metrics tracking for nodes, routes, and overall network health
|
||||
|
||||
3. **Client Implementations**:
|
||||
- `clients/native`: Native Rust client implementation
|
||||
- `clients/socks5`: SOCKS5 proxy client for standard applications
|
||||
- `wasm`: WebAssembly client implementations (for browsers)
|
||||
- `nym-connect`: Desktop and mobile clients
|
||||
|
||||
4. **Blockchain & Smart Contracts**:
|
||||
- `common/cosmwasm-smart-contracts`: Smart contract implementations
|
||||
- `contracts`: CosmWasm contracts for the Nym network
|
||||
- `common/ledger`: Blockchain integration
|
||||
|
||||
5. **Utilities & Tools**:
|
||||
- `tools`: Various CLI tools and utilities
|
||||
- `sdk`: SDKs for different languages and platforms
|
||||
- `documentation`: Documentation generation and management
|
||||
|
||||
## Packet System
|
||||
|
||||
Nym uses a modified Sphinx packet format for its mixnet:
|
||||
|
||||
1. **Message Chunking**:
|
||||
- Messages are divided into "sets" and "fragments"
|
||||
- Each fragment fits in a single Sphinx packet
|
||||
- The `common/nymsphinx/chunking` module handles message fragmentation
|
||||
|
||||
2. **Routing**:
|
||||
- Packets traverse through 3 layers of mixnodes
|
||||
- Routing information is encrypted in layers (onion routing)
|
||||
- The final gateway receives and processes the messages
|
||||
|
||||
3. **Monitoring**:
|
||||
- Monitoring system tracks packet delivery through the network
|
||||
- Routes are analyzed for reliability statistics
|
||||
- Node performance metrics are collected
|
||||
|
||||
## Network Protocol
|
||||
|
||||
Nym implements the Loopix mixnet design with several key privacy features:
|
||||
|
||||
1. **Continuous-time Mixing**:
|
||||
- Each mixnode delays messages independently with an exponential distribution
|
||||
- This creates random reordering of packets, destroying timing correlations
|
||||
- Offers better anonymity properties than batch mixing approaches
|
||||
|
||||
2. **Cover Traffic**:
|
||||
- Clients and nodes generate dummy "loop" packets that circulate through the network
|
||||
- These packets are indistinguishable from real traffic
|
||||
- Creates a baseline level of traffic that hides actual communication patterns
|
||||
- Provides unobservability (hiding when and how much real traffic is being sent)
|
||||
|
||||
3. **Stratified Network Architecture**:
|
||||
- Traffic flows through Entry Gateway → 3 Mixnode Layers → Exit Gateway
|
||||
- Path selection is independent per-message (unlike Tor)
|
||||
- Each node connects only to adjacent layers
|
||||
|
||||
4. **Anonymous Replies**:
|
||||
- Single-Use Reply Blocks (SURBs) allow receiving messages without revealing identity
|
||||
- Enables bidirectional communication while maintaining privacy
|
||||
|
||||
## Network Monitoring Architecture
|
||||
|
||||
The network monitoring system is a core component that measures mixnet reliability:
|
||||
|
||||
1. The `nym-network-monitor` sends test packets through the network
|
||||
2. These packets follow predefined routes through multiple mixnodes
|
||||
3. Metrics are collected about:
|
||||
- Successful and failed packet deliveries
|
||||
- Node reliability (percentage of successful packet handling)
|
||||
- Route reliability (which specific route combinations work best)
|
||||
4. Results are stored in the database and used by `nym-api` to:
|
||||
- Present node performance statistics
|
||||
- Determine network rewards
|
||||
- Provide route selection guidance to clients
|
||||
|
||||
In the current branch, metrics collection is being enhanced with a fanout approach to submit to multiple API endpoints.
|
||||
|
||||
## Development Environment
|
||||
|
||||
### Required Dependencies
|
||||
|
||||
- Rust toolchain (stable, 1.80+)
|
||||
- Node.js (v20+) and yarn for TypeScript components
|
||||
- SQLite for local database development
|
||||
- PostgreSQL for API database (optional, for full API functionality)
|
||||
- CosmWasm tools for contract development
|
||||
- For building contracts: `wasm-opt` tool from `binaryen`
|
||||
- Python 3.8+ for some scripts
|
||||
- Docker (optional, for containerized development)
|
||||
- protoc (Protocol Buffers compiler) for some components
|
||||
|
||||
### Environment Configurations
|
||||
|
||||
The `envs/` directory contains pre-configured environments:
|
||||
|
||||
#### Available Environments
|
||||
|
||||
- **`local.env`**: Local development environment
|
||||
- Points to local services (localhost)
|
||||
- Uses test mnemonics and keys
|
||||
- Ideal for testing without external dependencies
|
||||
|
||||
- **`sandbox.env`**: Sandbox test network
|
||||
- Public test network with real nodes
|
||||
- Test tokens available from faucet
|
||||
- Contract addresses for sandbox deployment
|
||||
- API: https://sandbox-nym-api1.nymtech.net
|
||||
|
||||
- **`mainnet.env`**: Production mainnet
|
||||
- Real network with real tokens
|
||||
- Production contract addresses
|
||||
- API: https://validator.nymtech.net
|
||||
- Use with caution!
|
||||
|
||||
- **`canary.env`**: Canary deployment
|
||||
- Pre-release testing environment
|
||||
- Tests new features before mainnet
|
||||
|
||||
- **`mainnet-local-api.env`**: Hybrid environment
|
||||
- Uses mainnet contracts but local API
|
||||
- Useful for API development against mainnet data
|
||||
|
||||
#### Key Environment Variables
|
||||
|
||||
```bash
|
||||
# Network configuration
|
||||
NETWORK_NAME=sandbox # Network identifier
|
||||
BECH32_PREFIX=n # Address prefix (n for sandbox, n for mainnet)
|
||||
NYM_API=https://sandbox-nym-api1.nymtech.net/api
|
||||
NYXD=https://rpc.sandbox.nymtech.net
|
||||
NYM_API_NETWORK=sandbox
|
||||
|
||||
# Contract addresses (network-specific)
|
||||
MIXNET_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
|
||||
VESTING_CONTRACT_ADDRESS=n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz
|
||||
# ... other contract addresses
|
||||
|
||||
# Mnemonic for testing (NEVER use in production)
|
||||
MNEMONIC="clutch captain shoe salt awake harvest setup primary inmate ugly among become"
|
||||
|
||||
# API Keys and tokens
|
||||
IPINFO_API_TOKEN=your_token_here
|
||||
AUTHENTICATOR_PASSWORD=password_here
|
||||
|
||||
# Logging
|
||||
RUST_LOG=info # Options: error, warn, info, debug, trace
|
||||
RUST_BACKTRACE=1 # Enable backtraces
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:pass@localhost/nym_api
|
||||
```
|
||||
|
||||
#### Using Environment Files
|
||||
|
||||
```bash
|
||||
# Load environment and run command
|
||||
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||
|
||||
# Export to shell
|
||||
source envs/sandbox.env
|
||||
|
||||
# Use with make targets
|
||||
dotenv -f envs/sandbox.env -- make run-api-tests
|
||||
```
|
||||
|
||||
## Initial Setup
|
||||
|
||||
### First Time Setup
|
||||
|
||||
1. **Install Prerequisites**
|
||||
```bash
|
||||
# Install Rust
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
|
||||
# Install Node.js and yarn
|
||||
# Via nvm (recommended):
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
nvm install 20
|
||||
npm install -g yarn
|
||||
|
||||
# Install build tools
|
||||
# Ubuntu/Debian:
|
||||
sudo apt-get install build-essential pkg-config libssl-dev protobuf-compiler libpq-dev
|
||||
|
||||
# macOS:
|
||||
brew install protobuf postgresql
|
||||
|
||||
# Install wasm-opt for contract builds
|
||||
npm install -g wasm-opt
|
||||
|
||||
# Add wasm target for Rust
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
2. **Clone and Setup Repository**
|
||||
```bash
|
||||
git clone https://github.com/nymtech/nym.git
|
||||
cd nym/nym
|
||||
|
||||
# Install JavaScript dependencies
|
||||
yarn install
|
||||
|
||||
# Build the project
|
||||
make build
|
||||
```
|
||||
|
||||
3. **Database Setup (Optional, for API development)**
|
||||
```bash
|
||||
# Install PostgreSQL
|
||||
# Create database
|
||||
createdb nym_api
|
||||
|
||||
# Run migrations (from nym-api directory)
|
||||
cd nym-api
|
||||
sqlx migrate run
|
||||
```
|
||||
|
||||
### Quick Start
|
||||
|
||||
```bash
|
||||
# Run a mixnode locally
|
||||
dotenv -f envs/sandbox.env -- cargo run -p nym-node -- run --mode mixnode --id my-mixnode
|
||||
|
||||
# Run a gateway locally
|
||||
dotenv -f envs/sandbox.env -- cargo run -p nym-node -- run --mode gateway --id my-gateway
|
||||
|
||||
# Run the API server
|
||||
dotenv -f envs/sandbox.env -- cargo run -p nym-api
|
||||
|
||||
# Run a client
|
||||
cargo run -p nym-client -- init --id my-client
|
||||
cargo run -p nym-client -- run --id my-client
|
||||
```
|
||||
|
||||
## CI/CD Pipeline
|
||||
|
||||
The project uses GitHub Actions for CI/CD with several key workflows:
|
||||
|
||||
1. **Build and Test**:
|
||||
- `ci-build.yml`: Main build workflow for Rust components
|
||||
- Tests are run on multiple platforms (Linux, Windows, macOS)
|
||||
- Includes formatting check (rustfmt) and linting (clippy)
|
||||
|
||||
2. **Release Process**:
|
||||
- Binary artifacts are published on release tags
|
||||
- Multiple platform builds are created
|
||||
|
||||
3. **Documentation**:
|
||||
- Documentation is automatically built and deployed
|
||||
|
||||
## Database Structure
|
||||
|
||||
The system uses SQLite databases with tables like:
|
||||
- `mixnode_status`: Status information about mixnodes
|
||||
- `gateway_status`: Status information about gateways
|
||||
- `routes`: Route performance information (success/failure of specific paths)
|
||||
- `monitor_run`: Information about monitoring test runs
|
||||
|
||||
## Development Workflows
|
||||
|
||||
### Running a Node
|
||||
|
||||
To run the mixnode or gateway:
|
||||
|
||||
```bash
|
||||
# Run nym-node as a mixnode with specified identity
|
||||
cargo run -p nym-node -- run --mode mixnode --id my-mixnode
|
||||
|
||||
# Run nym-node as a gateway
|
||||
cargo run -p nym-node -- run --mode gateway --id my-gateway
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Nodes can be configured with files in various locations:
|
||||
- Command-line arguments
|
||||
- Environment variables
|
||||
- `.env` files specified with `--config-env-file`
|
||||
|
||||
### Monitoring
|
||||
|
||||
To monitor the health of your node:
|
||||
- View logs for real-time information
|
||||
- Use the node's HTTP API for status information
|
||||
- Check the explorer for public node statistics
|
||||
|
||||
## Common Libraries
|
||||
|
||||
- `common/types`: Shared data types across all components
|
||||
- `common/crypto`: Cryptographic primitives and wrappers
|
||||
- `common/client-core`: Core client functionality
|
||||
- `common/gateway-client`: Client-gateway communication
|
||||
- `common/task`: Task management and concurrency utilities
|
||||
- `common/nymsphinx`: Sphinx packet implementation for mixnet
|
||||
- `common/topology`: Network topology management
|
||||
- `common/credentials`: Credential system for privacy-preserving authentication
|
||||
- `common/bandwidth-controller`: Bandwidth management and accounting
|
||||
|
||||
## Code Conventions
|
||||
|
||||
- Error handling: Use anyhow/thiserror for structured error handling
|
||||
- Logging: Use the tracing framework for logging and diagnostics
|
||||
- State management: Generally use Tokio/futures for async code
|
||||
- Configuration: Use the config crate and env vars with defaults
|
||||
- Database: Use sqlx for type-safe database queries
|
||||
- Follow clippy recommendations and rustfmt formatting
|
||||
- Use semantic commit messages: feat, fix, docs, refactor, test, chore
|
||||
|
||||
## When Making Changes
|
||||
|
||||
- Run `make test` before submitting PRs
|
||||
- Follow Rust naming conventions
|
||||
- Use `clippy` to check for common issues
|
||||
- Update SQLx query caches when modifying DB queries: `cargo sqlx prepare`
|
||||
- Consider backward compatibility for protocol changes
|
||||
- Use lefthook pre-commit hooks for TypeScript formatting
|
||||
- Run `cargo deny check` to verify dependency compliance
|
||||
- Test against both sandbox and local environments when possible
|
||||
- Update relevant documentation and CHANGELOG.md
|
||||
|
||||
## Development Tools
|
||||
|
||||
### Useful Cargo Commands
|
||||
|
||||
```bash
|
||||
# Check for outdated dependencies
|
||||
cargo outdated
|
||||
|
||||
# Analyze binary size
|
||||
cargo bloat --release -p nym-node
|
||||
|
||||
# Generate dependency graph
|
||||
cargo tree -p nym-api
|
||||
|
||||
# Run with instrumentation
|
||||
cargo run --features profiling -p nym-node
|
||||
|
||||
# Check for security advisories
|
||||
cargo audit
|
||||
```
|
||||
|
||||
### Database Tools
|
||||
|
||||
```bash
|
||||
# SQLx CLI for migrations
|
||||
cargo install sqlx-cli
|
||||
|
||||
# Create new migration
|
||||
cd nym-api && sqlx migrate add <migration_name>
|
||||
|
||||
# Prepare query metadata for offline compilation
|
||||
cargo sqlx prepare --workspace
|
||||
|
||||
# View database schema
|
||||
./nym-api/enter_db.sh
|
||||
```
|
||||
|
||||
### Development Scripts
|
||||
|
||||
- `scripts/build_topology.py`: Generate network topology files
|
||||
- `scripts/node_api_check.py`: Verify node API endpoints
|
||||
- `scripts/network_tunnel_manager.sh`: Manage network tunnels
|
||||
- `scripts/localnet_start.sh`: Start a local test network
|
||||
- Various deployment scripts in `deployment/` for different environments
|
||||
|
||||
## Debugging
|
||||
|
||||
- Enable more verbose logging with the RUST_LOG environment variable:
|
||||
```
|
||||
RUST_LOG=debug,nym_node=trace cargo run -p nym-node -- run --mode mixnode
|
||||
```
|
||||
- Use the HTTP API endpoints for status information
|
||||
- Check monitoring data in the database for network performance metrics
|
||||
- For complex issues, use tracing tools to follow packet flow
|
||||
- Enable backtraces: `RUST_BACKTRACE=full`
|
||||
- For WASM debugging: Use browser developer tools with source maps
|
||||
|
||||
## Deployment and Advanced Configurations
|
||||
|
||||
### Deployment Structure
|
||||
|
||||
The `deployment/` directory contains Ansible playbooks and configurations for various deployment scenarios:
|
||||
|
||||
- **`aws/`**: AWS-specific deployment configurations
|
||||
- **`mixnode/`**: Mixnode deployment playbooks
|
||||
- **`gateway/`**: Gateway deployment playbooks
|
||||
- **`validator/`**: Validator node deployment
|
||||
- **`sandbox-v2/`**: Complete sandbox environment setup
|
||||
- **`big-dipper-2/`**: Block explorer deployment
|
||||
|
||||
### Sandbox V2 Deployment
|
||||
|
||||
The sandbox-v2 deployment (`deployment/sandbox-v2/`) provides a complete test environment:
|
||||
|
||||
```bash
|
||||
# Key playbooks:
|
||||
- deploy.yaml # Main deployment orchestrator
|
||||
- deploy-mixnodes.yaml # Deploy mixnodes
|
||||
- deploy-gateways.yaml # Deploy gateways
|
||||
- deploy-validators.yaml # Deploy validator nodes
|
||||
- deploy-nym-api.yaml # Deploy API services
|
||||
```
|
||||
|
||||
### Custom Environment Setup
|
||||
|
||||
To create a custom environment:
|
||||
|
||||
1. Copy an existing env file: `cp envs/sandbox.env envs/custom.env`
|
||||
2. Modify the network endpoints and contract addresses
|
||||
3. Update the `NETWORK_NAME` to your identifier
|
||||
4. Set appropriate mnemonics and keys (use fresh ones for production!)
|
||||
|
||||
### Contract Addresses
|
||||
|
||||
Contract addresses are network-specific and defined in environment files:
|
||||
- Mixnet contract: Manages mixnode/gateway registry
|
||||
- Vesting contract: Handles token vesting schedules
|
||||
- Coconut contracts: Privacy-preserving credentials
|
||||
- Name service: Human-readable address mapping
|
||||
- Ecash contract: Electronic cash functionality
|
||||
|
||||
### Local Network Setup
|
||||
|
||||
For a completely local network:
|
||||
```bash
|
||||
# Start local chain
|
||||
./scripts/localnet_start.sh
|
||||
|
||||
# Deploy contracts
|
||||
cd contracts
|
||||
make deploy-local
|
||||
|
||||
# Start nodes with local config
|
||||
dotenv -f envs/local.env -- cargo run -p nym-node -- run --mode mixnode
|
||||
```
|
||||
|
||||
## Common Issues and Troubleshooting
|
||||
|
||||
### Database Issues
|
||||
|
||||
- When modifying database queries, you must update SQLx query caches:
|
||||
```bash
|
||||
cargo sqlx prepare
|
||||
```
|
||||
- If you see SQLx errors about missing query files, this is likely the cause
|
||||
- For "database is locked" errors with SQLite, ensure only one process accesses the DB
|
||||
- For PostgreSQL connection issues, verify DATABASE_URL and that the server is running
|
||||
|
||||
### API Connection Issues
|
||||
|
||||
- Check the environment variables pointing to the APIs (NYM_API, NYXD)
|
||||
- Verify network connectivity and API health endpoints
|
||||
- For authentication issues, check node keys and credentials
|
||||
- Common endpoints to verify:
|
||||
- API health: `$NYM_API/health`
|
||||
- Chain status: `$NYXD/status`
|
||||
- Contract info: `$NYXD/cosmwasm/wasm/v1/contract/$CONTRACT_ADDRESS`
|
||||
|
||||
### Build Problems
|
||||
|
||||
- Clean dependencies with `cargo clean` for a fresh build
|
||||
- Check for compatible Rust version (1.80+ recommended)
|
||||
- For smart contract builds, ensure wasm-opt is installed: `npm install -g wasm-opt`
|
||||
- For cross-compilation issues, check target-specific dependencies
|
||||
- WASM build issues: Ensure wasm32-unknown-unknown target is installed:
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
- For "cannot find -lpq" errors, install PostgreSQL development files:
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install libpq-dev
|
||||
# macOS
|
||||
brew install postgresql
|
||||
```
|
||||
|
||||
### Environment Issues
|
||||
|
||||
- Contract address mismatches: Ensure you're using the correct environment file
|
||||
- "Account sequence mismatch": The account nonce is out of sync, wait and retry
|
||||
- Token decimal issues: Sandbox uses different decimal places than mainnet
|
||||
- API version mismatches: Ensure your local API version matches the network
|
||||
- "Insufficient funds": Get test tokens from faucet (sandbox) or check balance
|
||||
- Gateway/mixnode bonding issues: Verify minimum stake requirements
|
||||
|
||||
## Working with Routes and Monitoring
|
||||
|
||||
1. Route monitoring metrics are stored in a `routes` table with:
|
||||
- Layer node IDs (layer1, layer2, layer3, gw)
|
||||
- Success flag (boolean)
|
||||
- Timestamp
|
||||
|
||||
2. To analyze routes:
|
||||
- Check `NetworkAccount` and `AccountingRoute` in `nym-network-monitor/src/accounting.rs`
|
||||
- View monitoring logic in `common/nymsphinx/chunking/monitoring.rs`
|
||||
- Observe how routes are submitted to the database in the `submit_accounting_routes_to_db` function
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Profiling and Benchmarking
|
||||
|
||||
```bash
|
||||
# Run benchmarks
|
||||
cargo bench -p nym-node
|
||||
|
||||
# Profile with perf (Linux)
|
||||
cargo build --release --features profiling
|
||||
perf record --call-graph=dwarf ./target/release/nym-node run --mode mixnode
|
||||
perf report
|
||||
|
||||
# Generate flamegraph
|
||||
cargo install flamegraph
|
||||
cargo flamegraph --bin nym-node -- run --mode mixnode
|
||||
```
|
||||
|
||||
### Common Performance Considerations
|
||||
|
||||
- Use bounded channels for backpressure
|
||||
- Batch database operations where possible
|
||||
- Monitor memory usage with `RUST_LOG=nym_node::metrics=debug`
|
||||
- Use connection pooling for database connections
|
||||
- Consider using `jemalloc` for better memory allocation performance
|
||||
Generated
+933
-844
File diff suppressed because it is too large
Load Diff
@@ -318,7 +318,7 @@ impl Handler {
|
||||
|
||||
async fn handle_text_message(&mut self, msg: String) -> Option<WsMessage> {
|
||||
debug!("Handling text message request");
|
||||
trace!("Content: {msg:?}");
|
||||
trace!("Content: {:?}", msg);
|
||||
|
||||
self.received_response_type = ReceivedResponseType::Text;
|
||||
let client_request = ClientRequest::try_from_text(msg);
|
||||
|
||||
@@ -68,9 +68,9 @@ impl Listener {
|
||||
new_conn = tcp_listener.accept() => {
|
||||
match new_conn {
|
||||
Ok((mut socket, remote_addr)) => {
|
||||
debug!("Received connection from {remote_addr:?}");
|
||||
debug!("Received connection from {:?}", remote_addr);
|
||||
if self.state.is_connected() {
|
||||
warn!("Tried to open a duplicate websocket connection. The request came from {remote_addr}");
|
||||
warn!("Tried to open a duplicate websocket connection. The request came from {}", remote_addr);
|
||||
// if we've already got a connection, don't allow another one
|
||||
// while we only ever want to accept a single connection, we don't want
|
||||
// to leave clients hanging (and also allow for reconnection if it somehow
|
||||
|
||||
@@ -137,7 +137,7 @@ impl AsyncFileWatcher {
|
||||
log::error!("the file watcher receiver has been dropped!");
|
||||
}
|
||||
} else {
|
||||
log::debug!("will not propagate information about {event:?}");
|
||||
log::debug!("will not propagate information about {:?}", event);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -11,7 +11,7 @@ impl std::fmt::Display for BandwidthStatusMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BandwidthStatusMessage::RemainingBandwidth(b) => {
|
||||
write!(f, "remaining bandwidth: {b}")
|
||||
write!(f, "remaining bandwidth: {}", b)
|
||||
}
|
||||
BandwidthStatusMessage::NoBandwidth => write!(f, "no bandwidth left"),
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ impl MixTrafficController {
|
||||
Some(client_request) => {
|
||||
match self.gateway_transceiver.send_client_request(client_request).await {
|
||||
Ok(_) => (),
|
||||
Err(e) => error!("Failed to send client request: {e}"),
|
||||
Err(e) => error!("Failed to send client request: {}", e),
|
||||
};
|
||||
},
|
||||
None => {
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ impl AcknowledgementListener {
|
||||
return;
|
||||
}
|
||||
|
||||
trace!("Received {frag_id} from the mix network");
|
||||
trace!("Received {} from the mix network", frag_id);
|
||||
self.stats_tx
|
||||
.report(PacketStatisticsEvent::RealAckReceived(ack_content.len()).into());
|
||||
if let Err(err) = self
|
||||
|
||||
+19
-7
@@ -126,7 +126,7 @@ impl ActionController {
|
||||
fn handle_insert(&mut self, pending_acks: Vec<PendingAcknowledgement>) {
|
||||
for pending_ack in pending_acks {
|
||||
let frag_id = pending_ack.message_chunk.fragment_identifier();
|
||||
trace!("{frag_id} is inserted");
|
||||
trace!("{} is inserted", frag_id);
|
||||
|
||||
if self
|
||||
.pending_acks_data
|
||||
@@ -161,16 +161,22 @@ impl ActionController {
|
||||
let new_queue_key = self.pending_acks_timers.insert(frag_id, timeout);
|
||||
*queue_key = Some(new_queue_key)
|
||||
} else {
|
||||
debug!("Tried to START TIMER on pending ack that is already gone! - {frag_id}");
|
||||
debug!(
|
||||
"Tried to START TIMER on pending ack that is already gone! - {}",
|
||||
frag_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_remove(&mut self, frag_id: FragmentIdentifier) {
|
||||
trace!("{frag_id} is getting removed");
|
||||
trace!("{} is getting removed", frag_id);
|
||||
|
||||
match self.pending_acks_data.remove(&frag_id) {
|
||||
None => {
|
||||
debug!("Tried to REMOVE pending ack that is already gone! - {frag_id}");
|
||||
debug!(
|
||||
"Tried to REMOVE pending ack that is already gone! - {}",
|
||||
frag_id
|
||||
);
|
||||
}
|
||||
Some((_, queue_key)) => {
|
||||
if let Some(queue_key) = queue_key {
|
||||
@@ -182,7 +188,10 @@ impl ActionController {
|
||||
} else {
|
||||
// I'm not 100% sure if having a `None` key is even possible here
|
||||
// (REMOVE would have to be called before START TIMER),
|
||||
debug!("Tried to REMOVE pending ack without TIMER active - {frag_id}");
|
||||
debug!(
|
||||
"Tried to REMOVE pending ack without TIMER active - {}",
|
||||
frag_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,7 +200,7 @@ impl ActionController {
|
||||
// initiated basically as a first step of retransmission. At first data has its delay updated
|
||||
// (as new sphinx packet was created with new expected delivery time)
|
||||
fn handle_update_pending_ack(&mut self, frag_id: FragmentIdentifier, delay: SphinxDelay) {
|
||||
trace!("{frag_id} is updating its delay");
|
||||
trace!("{} is updating its delay", frag_id);
|
||||
// TODO: is it possible to solve this without either locking or temporarily removing the value?
|
||||
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.remove(&frag_id) {
|
||||
// this Action is triggered by `RetransmissionRequestListener` (for 'normal' packets)
|
||||
@@ -204,7 +213,10 @@ impl ActionController {
|
||||
self.pending_acks_data
|
||||
.insert(frag_id, (Arc::new(inner_data), queue_key));
|
||||
} else {
|
||||
debug!("Tried to UPDATE TIMER on pending ack that is already gone! - {frag_id}");
|
||||
debug!(
|
||||
"Tried to UPDATE TIMER on pending ack that is already gone! - {}",
|
||||
frag_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ where
|
||||
// well technically the message was not sent just yet, but now it's up to internal
|
||||
// queues and client load rather than the required delay. So realistically we can treat
|
||||
// whatever is about to happen as negligible additional delay.
|
||||
trace!("{frag_id} is about to get sent to the mixnet");
|
||||
trace!("{} is about to get sent to the mixnet", frag_id);
|
||||
if let Err(err) = self.sent_notifier.unbounded_send(frag_id) {
|
||||
error!("Failed to notify about sent message: {err}");
|
||||
}
|
||||
|
||||
+3
-3
@@ -164,11 +164,11 @@ impl SendingDelayController {
|
||||
self.current_multiplier()
|
||||
);
|
||||
if self.current_multiplier() > 0 {
|
||||
log::debug!("{status_str}");
|
||||
log::debug!("{}", status_str);
|
||||
} else if self.current_multiplier() > 1 {
|
||||
log::info!("{status_str}");
|
||||
log::info!("{}", status_str);
|
||||
} else if self.current_multiplier() > 2 {
|
||||
log::warn!("{status_str}");
|
||||
log::warn!("{}", status_str);
|
||||
}
|
||||
self.time_when_logged_about_elevated_multiplier = now;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,10 @@ impl<R: MessageReceiver> ReceivedMessagesBuffer<R> {
|
||||
let stored_messages = std::mem::take(&mut guard.messages);
|
||||
if !stored_messages.is_empty() {
|
||||
if let Err(err) = sender.unbounded_send(stored_messages) {
|
||||
error!("The sender channel we just received is already invalidated - {err:?}");
|
||||
error!(
|
||||
"The sender channel we just received is already invalidated - {:?}",
|
||||
err
|
||||
);
|
||||
// put the values back to the buffer
|
||||
// the returned error has two fields: err: SendError and val: T,
|
||||
// where val is the value that was failed to get sent;
|
||||
|
||||
@@ -217,14 +217,14 @@ where
|
||||
.surbs_storage_ref()
|
||||
.contains_surbs_for(&recipient_tag)
|
||||
{
|
||||
warn!("received reply request for {recipient_tag:?} but we don't have any surbs stored for that recipient!");
|
||||
warn!("received reply request for {:?} but we don't have any surbs stored for that recipient!", recipient_tag);
|
||||
return;
|
||||
}
|
||||
|
||||
trace!("handling reply to {recipient_tag:?}");
|
||||
trace!("handling reply to {:?}", recipient_tag);
|
||||
let mut fragments = self.message_handler.split_reply_message(data);
|
||||
let total_size = fragments.len();
|
||||
trace!("This reply requires {total_size:?} SURBs");
|
||||
trace!("This reply requires {:?} SURBs", total_size);
|
||||
|
||||
let available_surbs = self
|
||||
.full_reply_storage
|
||||
@@ -327,7 +327,10 @@ where
|
||||
.await
|
||||
{
|
||||
let err = err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
|
||||
warn!("failed to request additional surbs from {target:?} - {err}");
|
||||
warn!(
|
||||
"failed to request additional surbs from {:?} - {err}",
|
||||
target
|
||||
);
|
||||
return Err(err);
|
||||
} else {
|
||||
self.full_reply_storage
|
||||
@@ -406,7 +409,10 @@ where
|
||||
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
|
||||
self.re_insert_pending_retransmission(&target, to_take);
|
||||
|
||||
warn!("failed to clear pending retransmission queue for {target:?} - {err}");
|
||||
warn!(
|
||||
"failed to clear pending retransmission queue for {:?} - {err}",
|
||||
target
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -483,7 +489,7 @@ where
|
||||
let err =
|
||||
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
|
||||
self.re_insert_pending_replies(&target, to_send);
|
||||
warn!("failed to clear pending queue for {target:?} - {err}");
|
||||
warn!("failed to clear pending queue for {:?} - {err}", target);
|
||||
}
|
||||
} else {
|
||||
trace!("the pending queue is empty");
|
||||
@@ -810,7 +816,7 @@ where
|
||||
if diff > max_drop_wait {
|
||||
to_remove.push(*pending_reply_target)
|
||||
} else {
|
||||
debug!("We haven't received any surbs in {diff:?} from {pending_reply_target}. Going to explicitly ask for more");
|
||||
debug!("We haven't received any surbs in {:?} from {pending_reply_target}. Going to explicitly ask for more", diff);
|
||||
to_request.push(*pending_reply_target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ impl StatisticsControl {
|
||||
None,
|
||||
);
|
||||
if let Err(err) = self.report_tx.send(report_message).await {
|
||||
log::error!("Failed to report client stats: {err:?}");
|
||||
log::error!("Failed to report client stats: {:?}", err);
|
||||
} else {
|
||||
self.stats.reset();
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ impl<T> TransmissionBuffer<T> {
|
||||
};
|
||||
|
||||
let msg = self.pop_front_from_lane(&lane)?;
|
||||
log::trace!("picking to send from lane: {lane:?}");
|
||||
log::trace!("picking to send from lane: {:?}", lane);
|
||||
Some((lane, msg))
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ pub async fn gateways_for_init<R: Rng>(
|
||||
let gateways = client.get_all_basic_entry_assigned_nodes_v2().await?.nodes;
|
||||
info!("nym api reports {} gateways", gateways.len());
|
||||
|
||||
log::trace!("Gateways: {gateways:#?}");
|
||||
log::trace!("Gateways: {:#?}", gateways);
|
||||
|
||||
// filter out gateways below minimum performance and ones that could operate as a mixnode
|
||||
// (we don't want instability)
|
||||
@@ -121,7 +121,7 @@ pub async fn gateways_for_init<R: Rng>(
|
||||
.filter_map(|gateway| gateway.try_into().ok())
|
||||
.collect::<Vec<_>>();
|
||||
log::debug!("After checking validity: {}", valid_gateways.len());
|
||||
log::trace!("Valid gateways: {valid_gateways:#?}");
|
||||
log::trace!("Valid gateways: {:#?}", valid_gateways);
|
||||
|
||||
log::info!(
|
||||
"and {} after validity and performance filtering",
|
||||
@@ -286,7 +286,7 @@ pub(super) fn get_specified_gateway(
|
||||
gateways: &[RoutingNode],
|
||||
must_use_tls: bool,
|
||||
) -> Result<RoutingNode, ClientCoreError> {
|
||||
log::debug!("Requesting specified gateway: {gateway_identity}");
|
||||
log::debug!("Requesting specified gateway: {}", gateway_identity);
|
||||
let user_gateway = ed25519::PublicKey::from_base58_string(gateway_identity)
|
||||
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
|
||||
|
||||
|
||||
+9
-15
@@ -7,16 +7,17 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use serde::Deserialize;
|
||||
|
||||
pub use nym_performance_contract_common::{
|
||||
msg::QueryMsg as PerformanceQueryMsg, types::NetworkMonitorResponse, EpochId,
|
||||
EpochMeasurementsPagedResponse, EpochNodePerformance, EpochPerformancePagedResponse,
|
||||
FullHistoricalPerformancePagedResponse, HistoricalPerformance, LastSubmission,
|
||||
NetworkMonitorInformation, NetworkMonitorsPagedResponse, NodeId, NodeMeasurement,
|
||||
NodeMeasurementsResponse, NodePerformance, NodePerformancePagedResponse,
|
||||
NodePerformanceResponse, RetiredNetworkMonitor, RetiredNetworkMonitorsPagedResponse,
|
||||
msg::QueryMsg as PerformanceQueryMsg, types::NetworkMonitorResponse,
|
||||
};
|
||||
use nym_performance_contract_common::{
|
||||
EpochId, EpochMeasurementsPagedResponse, EpochNodePerformance, EpochPerformancePagedResponse,
|
||||
FullHistoricalPerformancePagedResponse, HistoricalPerformance, NetworkMonitorInformation,
|
||||
NetworkMonitorsPagedResponse, NodeId, NodeMeasurement, NodeMeasurementsResponse,
|
||||
NodePerformance, NodePerformancePagedResponse, NodePerformanceResponse, RetiredNetworkMonitor,
|
||||
RetiredNetworkMonitorsPagedResponse,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -138,11 +139,6 @@ pub trait PerformanceQueryClient {
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_last_submission(&self) -> Result<LastSubmission, NyxdError> {
|
||||
self.query_performance_contract(PerformanceQueryMsg::LastSubmittedMeasurement {})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// extension trait to the query client to deal with the paged queries
|
||||
@@ -216,7 +212,6 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::nyxd::contract_traits::tests::IgnoreValue;
|
||||
use nym_performance_contract_common::QueryMsg;
|
||||
|
||||
// it's enough that this compiles and clippy is happy about it
|
||||
#[allow(dead_code)]
|
||||
@@ -265,7 +260,6 @@ mod tests {
|
||||
PerformanceQueryMsg::RetiredNetworkMonitorsPaged { start_after, limit } => client
|
||||
.get_retired_network_monitors_paged(start_after, limit)
|
||||
.ignore(),
|
||||
QueryMsg::LastSubmittedMeasurement {} => client.get_last_submission().ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ pub fn show_error<E>(e: E)
|
||||
where
|
||||
E: Display,
|
||||
{
|
||||
error!("{e}");
|
||||
error!("{}", e);
|
||||
}
|
||||
|
||||
pub fn show_error_passthrough<E>(e: E) -> E
|
||||
where
|
||||
E: Error + Display,
|
||||
{
|
||||
error!("{e}");
|
||||
error!("{}", e);
|
||||
e
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ pub async fn query_balance(
|
||||
.address
|
||||
.unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic"));
|
||||
|
||||
info!("Getting balance for {address}...");
|
||||
info!("Getting balance for {}...", address);
|
||||
|
||||
match client.get_all_balances(&address).await {
|
||||
Ok(coins) => {
|
||||
|
||||
@@ -57,17 +57,17 @@ pub fn get_pubkey_from_mnemonic(address: AccountId, prefix: &str, mnemonic: bip3
|
||||
println!("{}", account.public_key().to_string());
|
||||
}
|
||||
None => {
|
||||
error!("Could not derive key that matches {address}")
|
||||
error!("Could not derive key that matches {}", address)
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Failed to derive accounts. {e}");
|
||||
error!("Failed to derive accounts. {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_pubkey_from_chain(address: AccountId, client: &QueryClient) {
|
||||
info!("Getting public key for address {address} from chain...");
|
||||
info!("Getting public key for address {} from chain...", address);
|
||||
match client.get_account(&address).await {
|
||||
Ok(Some(account)) => {
|
||||
if let Ok(base_account) = account.try_get_base_account() {
|
||||
|
||||
@@ -37,7 +37,7 @@ pub async fn send_multiple(args: Args, client: &SigningClient) {
|
||||
|
||||
let rows = InputFileReader::new(&args.input);
|
||||
if let Err(e) = rows {
|
||||
error!("Failed to read input file: {e}");
|
||||
error!("Failed to read input file: {}", e);
|
||||
return;
|
||||
}
|
||||
let rows = rows.unwrap();
|
||||
@@ -67,7 +67,7 @@ pub async fn send_multiple(args: Args, client: &SigningClient) {
|
||||
.prompt();
|
||||
|
||||
if let Err(e) = ans {
|
||||
info!("Aborting, {e}...");
|
||||
info!("Aborting, {}...", e);
|
||||
return;
|
||||
}
|
||||
if let Ok(false) = ans {
|
||||
@@ -100,10 +100,13 @@ pub async fn send_multiple(args: Args, client: &SigningClient) {
|
||||
println!("Transaction hash: {}", &res.hash);
|
||||
|
||||
if let Some(output_filename) = args.output {
|
||||
println!("\nWriting output log to {output_filename}");
|
||||
println!("\nWriting output log to {}", output_filename);
|
||||
|
||||
if let Err(e) = write_output_file(rows, res, &output_filename) {
|
||||
error!("Failed to write output file {output_filename} with error {e}");
|
||||
error!(
|
||||
"Failed to write output file {} with error {}",
|
||||
output_filename, e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +136,7 @@ fn write_output_file(
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
|
||||
Ok(file.write_all(format!("{data}\n").as_bytes())?)
|
||||
Ok(file.write_all(format!("{}\n", data).as_bytes())?)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -168,7 +171,7 @@ impl InputFileReader {
|
||||
|
||||
// multiply when a whole token amount, e.g. 50nym (50.123456nym is not allowed, that must be input as 50123456unym)
|
||||
let (amount, denom) = if !denom.starts_with('u') {
|
||||
(amount * 1_000_000u128, format!("u{denom}"))
|
||||
(amount * 1_000_000u128, format!("u{}", denom))
|
||||
} else {
|
||||
(amount, denom)
|
||||
};
|
||||
|
||||
@@ -55,6 +55,6 @@ pub async fn execute(args: Args, client: SigningClient) {
|
||||
.await
|
||||
{
|
||||
Ok(res) => info!("SUCCESS ✅\n{}", json!(res)),
|
||||
Err(e) => error!("FAILURE ❌\n{e}"),
|
||||
Err(e) => error!("FAILURE ❌\n{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ pub struct Args {
|
||||
pub async fn generate(args: Args) {
|
||||
info!("Starting to generate vesting contract instantiate msg");
|
||||
|
||||
debug!("Received arguments: {args:?}");
|
||||
debug!("Received arguments: {:?}", args);
|
||||
|
||||
let multisig_addr = args.multisig_addr.unwrap_or_else(|| {
|
||||
let address = std::env::var(nym_network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
||||
@@ -97,7 +97,7 @@ pub async fn generate(args: Args) {
|
||||
key_size: DEFAULT_DEALINGS as u32,
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {instantiate_msg:?}");
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
let res =
|
||||
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
||||
|
||||
@@ -28,7 +28,7 @@ pub struct Args {
|
||||
pub async fn generate(args: Args) {
|
||||
info!("Starting to generate vesting contract instantiate msg");
|
||||
|
||||
debug!("Received arguments: {args:?}");
|
||||
debug!("Received arguments: {:?}", args);
|
||||
|
||||
let group_addr = args.group_addr.unwrap_or_else(|| {
|
||||
let address = std::env::var(nym_network_defaults::var_names::GROUP_CONTRACT_ADDRESS)
|
||||
@@ -51,7 +51,7 @@ pub async fn generate(args: Args) {
|
||||
deposit_amount: args.deposit_amount,
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {instantiate_msg:?}");
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
let res =
|
||||
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
||||
|
||||
@@ -88,7 +88,7 @@ pub struct Args {
|
||||
pub async fn generate(args: Args) {
|
||||
info!("Starting to generate mixnet contract instantiate msg");
|
||||
|
||||
debug!("Received arguments: {args:?}");
|
||||
debug!("Received arguments: {:?}", args);
|
||||
|
||||
let initial_rewarding_params = InitialRewardingParams {
|
||||
initial_reward_pool: Decimal::from_atomics(args.initial_reward_pool, 0)
|
||||
@@ -114,7 +114,7 @@ pub async fn generate(args: Args) {
|
||||
},
|
||||
};
|
||||
|
||||
debug!("initial_rewarding_params: {initial_rewarding_params:?}");
|
||||
debug!("initial_rewarding_params: {:?}", initial_rewarding_params);
|
||||
|
||||
let rewarding_validator_address = args.rewarding_validator_address.unwrap_or_else(|| {
|
||||
let address = std::env::var(nym_network_defaults::var_names::REWARDING_VALIDATOR_ADDRESS)
|
||||
@@ -160,7 +160,7 @@ pub async fn generate(args: Args) {
|
||||
key_validity_in_epochs: None,
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {instantiate_msg:?}");
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
let res =
|
||||
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
||||
|
||||
@@ -31,7 +31,7 @@ pub struct Args {
|
||||
pub async fn generate(args: Args) {
|
||||
info!("Starting to generate vesting contract instantiate msg");
|
||||
|
||||
debug!("Received arguments: {args:?}");
|
||||
debug!("Received arguments: {:?}", args);
|
||||
|
||||
let ecash_contract_address = args.ecash_contract_address.unwrap_or_else(|| {
|
||||
let address = std::env::var(nym_network_defaults::var_names::ECASH_CONTRACT_ADDRESS)
|
||||
@@ -60,7 +60,7 @@ pub async fn generate(args: Args) {
|
||||
coconut_dkg_contract_address: coconut_dkg_contract_address.to_string(),
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {instantiate_msg:?}");
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
let res =
|
||||
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
||||
|
||||
@@ -21,7 +21,7 @@ pub struct Args {
|
||||
pub async fn generate(args: Args) {
|
||||
info!("Starting to generate vesting contract instantiate msg");
|
||||
|
||||
debug!("Received arguments: {args:?}");
|
||||
debug!("Received arguments: {:?}", args);
|
||||
|
||||
let mixnet_contract_address = args.mixnet_contract_address.unwrap_or_else(|| {
|
||||
let address = std::env::var(nym_network_defaults::var_names::MIXNET_CONTRACT_ADDRESS)
|
||||
@@ -39,7 +39,7 @@ pub async fn generate(args: Args) {
|
||||
mix_denom,
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {instantiate_msg:?}");
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
let res =
|
||||
serde_json::to_string(&instantiate_msg).expect("failed to convert instantiate msg to json");
|
||||
|
||||
@@ -72,7 +72,7 @@ pub async fn init(args: Args, client: SigningClient, network_details: &NymNetwor
|
||||
.await
|
||||
.expect("failed to instantiate the contract!");
|
||||
|
||||
info!("Init result: {res:?}");
|
||||
info!("Init result: {:?}", res);
|
||||
|
||||
println!("{}", res.contract_address)
|
||||
}
|
||||
|
||||
@@ -47,5 +47,5 @@ pub async fn migrate(args: Args, client: SigningClient) {
|
||||
.expect("failed to migrate the contract!")
|
||||
};
|
||||
|
||||
info!("Migrate result: {res:?}");
|
||||
info!("Migrate result: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ pub async fn upload(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to upload the contract!");
|
||||
|
||||
info!("Upload result: {res:?}");
|
||||
info!("Upload result: {:?}", res);
|
||||
|
||||
println!("{}", res.code_id)
|
||||
}
|
||||
|
||||
@@ -47,5 +47,5 @@ pub async fn delegate_to_mixnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to delegate to mixnode!");
|
||||
|
||||
info!("delegating to mixnode: {res:?}");
|
||||
info!("delegating to mixnode: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
let records = match InputFileReader::new(&args.input) {
|
||||
Ok(records) => records,
|
||||
Err(e) => {
|
||||
println!("Error reading input file: {e}");
|
||||
println!("Error reading input file: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -262,11 +262,11 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
}
|
||||
|
||||
if !undelegation_msgs.is_empty() {
|
||||
println!("Undelegation records : \n{undelegation_table}\n\n");
|
||||
println!("Undelegation records : \n{}\n\n", undelegation_table);
|
||||
}
|
||||
|
||||
if !delegation_msgs.is_empty() {
|
||||
println!("Delegation records : \n{delegation_table}\n\n");
|
||||
println!("Delegation records : \n{}\n\n", delegation_table);
|
||||
}
|
||||
|
||||
let ans = inquire::Confirm::new("Do you want to continue with the shown operations?")
|
||||
@@ -275,7 +275,7 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
.prompt();
|
||||
|
||||
if let Err(e) = ans {
|
||||
info!("Aborting, {e}...");
|
||||
info!("Aborting, {}...", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ pub async fn delegate_to_multiple_mixnodes(args: Args, client: SigningClient) {
|
||||
|
||||
if args.output.is_some() {
|
||||
if let Err(e) = write_to_csv(output_details, args.output) {
|
||||
info!("Failed to write to CSV, {e}");
|
||||
info!("Failed to write to CSV, {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,5 @@ pub async fn migrate_vested_delegation(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to migrate delegation!");
|
||||
|
||||
info!("migration result: {res:?}")
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@ pub async fn claim_delegator_reward(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to claim delegator-reward");
|
||||
|
||||
info!("Claiming delegator reward: {res:?}")
|
||||
info!("Claiming delegator reward: {:?}", res)
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,5 +40,5 @@ pub async fn vesting_claim_delegator_reward(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to claim vesting delegator-reward");
|
||||
|
||||
info!("Claiming vesting delegator reward: {res:?}")
|
||||
info!("Claiming vesting delegator reward: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@ pub async fn undelegate_from_mixnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to remove stake from mixnode!");
|
||||
|
||||
info!("removing stake from mixnode: {res:?}")
|
||||
info!("removing stake from mixnode: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -53,5 +53,5 @@ pub async fn vesting_delegate_to_mixnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to delegate to mixnode!");
|
||||
|
||||
info!("vesting delegating to mixnode: {res:?}");
|
||||
info!("vesting delegating to mixnode: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@ pub async fn vesting_undelegate_from_mixnode(args: Args, client: SigningClient)
|
||||
.await
|
||||
.expect("failed to remove stake from vesting account on mixnode!");
|
||||
|
||||
info!("removing stake from vesting mixnode: {res:?}")
|
||||
info!("removing stake from vesting mixnode: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -73,5 +73,5 @@ pub async fn bond_gateway(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to bond gateway!");
|
||||
|
||||
info!("Bonding result: {res:?}")
|
||||
info!("Bonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -52,5 +52,5 @@ pub async fn migrate_to_nymnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to migrate gateway!");
|
||||
|
||||
info!("migration result: {res:?}")
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -56,5 +56,5 @@ pub async fn update_config(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("updating gateway config");
|
||||
|
||||
info!("gateway config updated: {res:?}")
|
||||
info!("gateway config updated: {:?}", res)
|
||||
}
|
||||
|
||||
+1
-1
@@ -57,5 +57,5 @@ pub async fn vesting_update_config(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("updating vesting gateway config");
|
||||
|
||||
info!("gateway config updated: {res:?}")
|
||||
info!("gateway config updated: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ pub async fn unbond_gateway(client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to unbond gateway!");
|
||||
|
||||
info!("Unbonding result: {res:?}")
|
||||
info!("Unbonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -73,5 +73,5 @@ pub async fn vesting_bond_gateway(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to bond gateway!");
|
||||
|
||||
info!("Vesting bonding gateway result: {res:?}")
|
||||
info!("Vesting bonding gateway result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ pub async fn vesting_unbond_gateway(client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to unbond vesting gateway!");
|
||||
|
||||
info!("Unbonding vesting result: {res:?}")
|
||||
info!("Unbonding vesting result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -106,5 +106,5 @@ pub async fn bond_mixnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to bond mixnode!");
|
||||
|
||||
info!("Bonding result: {res:?}")
|
||||
info!("Bonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ pub async fn decrease_pledge(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to decrease pledge!");
|
||||
|
||||
info!("decreasing pledge: {res:?}");
|
||||
info!("decreasing pledge: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ pub async fn migrate_vested_mixnode(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to migrate mixnode!");
|
||||
|
||||
info!("migration result: {res:?}")
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ pub async fn migrate_to_nymnode(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to migrate mixnode!");
|
||||
|
||||
info!("migration result: {res:?}")
|
||||
info!("migration result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ pub async fn pledge_more(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to pledge more!");
|
||||
|
||||
info!("pledging more: {res:?}");
|
||||
info!("pledging more: {:?}", res);
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,5 +17,5 @@ pub async fn claim_operator_reward(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to claim operator reward");
|
||||
|
||||
info!("Claiming operator reward: {res:?}")
|
||||
info!("Claiming operator reward: {:?}", res)
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,5 +20,5 @@ pub async fn vesting_claim_operator_reward(client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to claim vesting operator reward");
|
||||
|
||||
info!("Claiming vesting operator reward: {res:?}")
|
||||
info!("Claiming vesting operator reward: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -64,5 +64,5 @@ pub async fn update_config(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("updating mix-node config");
|
||||
|
||||
info!("mixnode config updated: {res:?}")
|
||||
info!("mixnode config updated: {:?}", res)
|
||||
}
|
||||
|
||||
+1
-1
@@ -65,5 +65,5 @@ pub async fn vesting_update_config(client: SigningClient, args: Args) {
|
||||
.await
|
||||
.expect("updating vesting mix-node config");
|
||||
|
||||
info!("mixnode config updated: {res:?}")
|
||||
info!("mixnode config updated: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ pub async fn unbond_mixnode(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to unbond mixnode!");
|
||||
|
||||
info!("Unbonding result: {res:?}")
|
||||
info!("Unbonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -106,5 +106,5 @@ pub async fn vesting_bond_mixnode(client: SigningClient, args: Args, denom: &str
|
||||
.await
|
||||
.expect("failed to bond vesting mixnode!");
|
||||
|
||||
info!("Bonding vesting result: {res:?}")
|
||||
info!("Bonding vesting result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ pub async fn vesting_decrease_pledge(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to vesting decrease pledge!");
|
||||
|
||||
info!("vesting decreasing pledge: {res:?}");
|
||||
info!("vesting decreasing pledge: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -26,5 +26,5 @@ pub async fn vesting_pledge_more(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to pledge more!");
|
||||
|
||||
info!("vesting pledge more: {res:?}");
|
||||
info!("vesting pledge more: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@ pub async fn vesting_unbond_mixnode(client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to unbond vesting mixnode!");
|
||||
|
||||
info!("Unbonding vesting result: {res:?}")
|
||||
info!("Unbonding vesting result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -85,5 +85,5 @@ pub async fn bond_nymnode(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to bond nymnode!");
|
||||
|
||||
info!("Bonding result: {res:?}")
|
||||
info!("Bonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ pub async fn decrease_pledge(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to decrease pledge!");
|
||||
|
||||
info!("decreasing pledge: {res:?}");
|
||||
info!("decreasing pledge: {:?}", res);
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ pub async fn increase_pledge(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to pledge more!");
|
||||
|
||||
info!("pledging more: {res:?}");
|
||||
info!("pledging more: {:?}", res);
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,5 +17,5 @@ pub async fn claim_operator_reward(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to claim operator reward");
|
||||
|
||||
info!("Claiming operator reward: {res:?}")
|
||||
info!("Claiming operator reward: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@ pub async fn update_config(args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("updating nym node config");
|
||||
|
||||
info!("nym node config updated: {res:?}")
|
||||
info!("nym node config updated: {:?}", res)
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,6 +68,6 @@ pub async fn update_cost_params(args: Args, client: SigningClient) -> anyhow::Re
|
||||
.await
|
||||
.expect("failed to update cost params");
|
||||
|
||||
info!("Cost params result: {res:?}");
|
||||
info!("Cost params result: {:?}", res);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ pub async fn unbond_nymnode(_args: Args, client: SigningClient) {
|
||||
.await
|
||||
.expect("failed to unbond Nym Node!");
|
||||
|
||||
info!("Unbonding result: {res:?}")
|
||||
info!("Unbonding result: {:?}", res)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ pub fn sign(args: Args, prefix: &str, mnemonic: Option<bip39::Mnemonic>) {
|
||||
println!("{}", json!(output));
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to sign message. {e}");
|
||||
error!("Failed to sign message. {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ pub fn sign(args: Args, prefix: &str, mnemonic: Option<bip39::Mnemonic>) {
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Failed to derive accounts. {e}");
|
||||
error!("Failed to derive accounts. {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ pub async fn verify(args: Args, client: &QueryClient) {
|
||||
|
||||
let public_key = match AccountId::from_str(&args.public_key_or_address) {
|
||||
Ok(address) => {
|
||||
info!("Found account address instead of public key, so looking up public key for {address} from chain");
|
||||
info!("Found account address instead of public key, so looking up public key for {} from chain", address);
|
||||
match client.get_account_public_key(&address).await.ok() {
|
||||
Some(public_key) => {
|
||||
if let Some(k) = public_key {
|
||||
@@ -48,7 +48,8 @@ pub async fn verify(args: Args, client: &QueryClient) {
|
||||
}
|
||||
None => {
|
||||
error!(
|
||||
"Address {address} does not have a public key recorded on the chain. This is probably because the account has never signed a transaction."
|
||||
"Address {} does not have a public key recorded on the chain. This is probably because the account has never signed a transaction.",
|
||||
address
|
||||
);
|
||||
None
|
||||
}
|
||||
@@ -57,7 +58,7 @@ pub async fn verify(args: Args, client: &QueryClient) {
|
||||
Err(_) => match PublicKey::from_json(&args.public_key_or_address) {
|
||||
Ok(parsed) => Some(parsed),
|
||||
Err(e) => {
|
||||
error!("Public key should be JSON. Unable to parse: {e}");
|
||||
error!("Public key should be JSON. Unable to parse: {}", e);
|
||||
None
|
||||
}
|
||||
},
|
||||
@@ -77,7 +78,7 @@ pub async fn verify(args: Args, client: &QueryClient) {
|
||||
) {
|
||||
Ok(()) => println!("SUCCESS ✅ signature verified"),
|
||||
Err(e) => {
|
||||
error!("FAILURE ❌ Signature verification failed: {e}");
|
||||
error!("FAILURE ❌ Signature verification failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,6 @@ pub async fn create(args: Args, client: SigningClient, network_details: &NymNetw
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
info!("Vesting result: {res:?}");
|
||||
info!("Coin send result: {send_coin_response:?}");
|
||||
info!("Vesting result: {:?}", res);
|
||||
info!("Coin send result: {:?}", send_coin_response);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ pub async fn query(args: Args, client: QueryClient, address_from_mnemonic: Optio
|
||||
.address
|
||||
.unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic"));
|
||||
|
||||
info!("Checking account {account_id} for a vesting schedule...");
|
||||
info!("Checking account {} for a vesting schedule...", account_id);
|
||||
|
||||
let vesting_address = account_id.to_string();
|
||||
let denom = client.current_chain_details().mix_denom.base.as_str();
|
||||
|
||||
@@ -44,17 +44,6 @@ pub struct RewardEstimate {
|
||||
pub operating_cost: Decimal,
|
||||
}
|
||||
|
||||
impl RewardEstimate {
|
||||
pub const fn zero() -> RewardEstimate {
|
||||
RewardEstimate {
|
||||
total_node_reward: Decimal::zero(),
|
||||
operator: Decimal::zero(),
|
||||
delegates: Decimal::zero(),
|
||||
operating_cost: Decimal::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[derive(Copy, Default)]
|
||||
pub struct RewardDistribution {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
pub mod storage_keys {
|
||||
pub const CONTRACT_ADMIN: &str = "contract-admin";
|
||||
pub const INITIAL_EPOCH_ID: &str = "initial-epoch-id";
|
||||
pub const LAST_SUBMISSION: &str = "last-submission";
|
||||
pub const MIXNET_CONTRACT: &str = "mixnet-contract";
|
||||
pub const AUTHORISED_COUNT: &str = "authorised-count";
|
||||
pub const AUTHORISED: &str = "authorised";
|
||||
|
||||
@@ -7,9 +7,9 @@ use cosmwasm_schema::cw_serde;
|
||||
#[cfg(feature = "schema")]
|
||||
use crate::types::{
|
||||
EpochMeasurementsPagedResponse, EpochPerformancePagedResponse,
|
||||
FullHistoricalPerformancePagedResponse, LastSubmission, NetworkMonitorResponse,
|
||||
NetworkMonitorsPagedResponse, NodeMeasurementsResponse, NodePerformancePagedResponse,
|
||||
NodePerformanceResponse, RetiredNetworkMonitorsPagedResponse,
|
||||
FullHistoricalPerformancePagedResponse, NetworkMonitorResponse, NetworkMonitorsPagedResponse,
|
||||
NodeMeasurementsResponse, NodePerformancePagedResponse, NodePerformanceResponse,
|
||||
RetiredNetworkMonitorsPagedResponse,
|
||||
};
|
||||
|
||||
#[cw_serde]
|
||||
@@ -113,10 +113,6 @@ pub enum QueryMsg {
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
},
|
||||
|
||||
/// Returns information regarding the latest submitted performance data
|
||||
#[cfg_attr(feature = "schema", returns(LastSubmission))]
|
||||
LastSubmittedMeasurement {},
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
|
||||
@@ -2,28 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::{Addr, Env, Timestamp};
|
||||
use cosmwasm_std::{Addr, Env};
|
||||
use nym_contracts_common::Percent;
|
||||
|
||||
pub type EpochId = u32;
|
||||
pub type NodeId = u32;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct LastSubmission {
|
||||
pub block_height: u64,
|
||||
pub block_time: Timestamp,
|
||||
|
||||
// not as relevant, but might as well store it
|
||||
pub data: Option<LastSubmittedData>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct LastSubmittedData {
|
||||
pub sender: Addr,
|
||||
pub epoch_id: EpochId,
|
||||
pub data: NodePerformance,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct NetworkMonitorDetails {
|
||||
pub address: Addr,
|
||||
|
||||
@@ -95,7 +95,7 @@ where
|
||||
} else if let Some(final_timestamp) = epoch.final_timestamp_secs() {
|
||||
// Use 1 additional second to not start the next iteration immediately and spam get_current_epoch queries
|
||||
let secs_until_final = final_timestamp.saturating_sub(current_timestamp_secs) + 1;
|
||||
info!("Approximately {secs_until_final} seconds until coconut is available. Sleeping until then. You can safely kill the process at any moment.");
|
||||
info!("Approximately {} seconds until coconut is available. Sleeping until then. You can safely kill the process at any moment.", secs_until_final);
|
||||
tokio::time::sleep(Duration::from_secs(secs_until_final)).await;
|
||||
} else if matches!(epoch.state, EpochState::WaitingInitialisation) {
|
||||
info!("dkg hasn't been initialised yet and it is not known when it will be. Going to check again later");
|
||||
|
||||
@@ -7,9 +7,9 @@ use std::env;
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let database_path = format!("{out_dir}/gateway-stats-example.sqlite");
|
||||
let database_path = format!("{}/gateway-stats-example.sqlite", out_dir);
|
||||
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path))
|
||||
.await
|
||||
.expect("Failed to create SQLx database connection");
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ use std::env;
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let database_path = format!("{out_dir}/gateway-example.sqlite");
|
||||
let database_path = format!("{}/gateway-example.sqlite", out_dir);
|
||||
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path))
|
||||
.await
|
||||
.expect("Failed to create SQLx database connection");
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ impl std::fmt::Display for ClientType {
|
||||
ClientType::EntryWireguard => "entry_wireguard",
|
||||
ClientType::ExitWireguard => "exit_wireguard",
|
||||
};
|
||||
write!(f, "{s}")
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
format!("{user_agent}"),
|
||||
format!("{}", user_agent),
|
||||
"nym-mixnode/0.11.0/x86_64-unknown-linux-gnu/abcdefg"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ colored = { workspace = true, optional = true }
|
||||
futures = { workspace = true, optional = true }
|
||||
mime = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = { workspace = true, optional = true }
|
||||
subtle = { workspace = true, optional = true }
|
||||
time = { workspace = true, optional = true, features = ["macros"] }
|
||||
|
||||
@@ -7,6 +7,7 @@ use axum::http::{header, HeaderValue};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use serde::Serialize;
|
||||
use utoipa::gen::serde_json;
|
||||
|
||||
// don't use axum's Json directly as we need to be able to define custom headers
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@@ -191,7 +191,7 @@ impl fmt::Display for IpPacketRequestData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
IpPacketRequestData::Data(_) => write!(f, "Data"),
|
||||
IpPacketRequestData::Control(c) => write!(f, "Control({c})"),
|
||||
IpPacketRequestData::Control(c) => write!(f, "Control({})", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ fn main() {
|
||||
|
||||
for var in variables_to_track {
|
||||
// if script fails, debug with `cargo check -vv``
|
||||
println!("Looking for {var}");
|
||||
println!("Looking for {}", var);
|
||||
|
||||
// read pattern that looks like:
|
||||
// <var>: &str = "<whatever is between quotes>"
|
||||
@@ -41,7 +41,7 @@ fn main() {
|
||||
.captures(source_of_truth)
|
||||
.and_then(|caps| caps.get(1).map(|match_| match_.as_str().to_string()))
|
||||
.expect("Couldn't find var in source file");
|
||||
println!("Storing {var}={value}");
|
||||
println!("Storing {}={}", var, value);
|
||||
replace_with.insert(var, value);
|
||||
}
|
||||
|
||||
@@ -57,11 +57,13 @@ fn main() {
|
||||
// <var>=<value>
|
||||
let re = Regex::new(&pattern).unwrap();
|
||||
contents = re
|
||||
.replace(&contents, |_: ®ex::Captures| format!(r#"{var}={value}"#))
|
||||
.replace(&contents, |_: ®ex::Captures| {
|
||||
format!(r#"{}={}"#, var, value)
|
||||
})
|
||||
.to_string();
|
||||
}
|
||||
|
||||
println!("File contents to write:\n{contents}");
|
||||
println!("File contents to write:\n{}", contents);
|
||||
if output_path.exists() {
|
||||
fs::write(output_path, contents).unwrap();
|
||||
} else {
|
||||
|
||||
@@ -25,7 +25,7 @@ fn print_env_vars_with_keys_in_file<P: AsRef<Path> + Copy>(config_env_file: P) {
|
||||
.expect("Invalid path to environment configuration file");
|
||||
for item in items {
|
||||
let (key, val) = item.expect("Invalid item in environment configuration file");
|
||||
log::debug!("{key}: {val}");
|
||||
log::debug!("{}: {}", key, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ impl NymNetworkDetails {
|
||||
}
|
||||
}
|
||||
Err(VarError::NotPresent) => None,
|
||||
err => panic!("Unable to set: {err:?}"),
|
||||
err => panic!("Unable to set: {:?}", err),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -344,9 +344,9 @@ impl fmt::Display for MetricsController {
|
||||
let metrics = self.gather();
|
||||
let output = match String::from_utf8(metrics) {
|
||||
Ok(output) => output,
|
||||
Err(e) => return write!(f, "Error decoding metrics to String: {e}"),
|
||||
Err(e) => return write!(f, "Error decoding metrics to String: {}", e),
|
||||
};
|
||||
write!(f, "{output}")
|
||||
write!(f, "{}", output)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ mod tests {
|
||||
assert_eq!(literal, "nym_metrics_foo");
|
||||
|
||||
let bar = "bar";
|
||||
let format = format!("foomp_{bar}");
|
||||
let format = format!("foomp_{}", bar);
|
||||
let formatted = prepend_package_name!(format);
|
||||
assert_eq!(formatted, "nym_metrics_foomp_bar");
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ impl GroupParameters {
|
||||
pub fn new(attributes: usize) -> GroupParameters {
|
||||
assert!(attributes > 0);
|
||||
let gammas = (1..=attributes)
|
||||
.map(|i| hash_g1(format!("gamma{i}")))
|
||||
.map(|i| hash_g1(format!("gamma{}", i)))
|
||||
.collect();
|
||||
|
||||
let delta = hash_g1("delta");
|
||||
|
||||
@@ -197,7 +197,7 @@ where
|
||||
let res = tokio::select! {
|
||||
biased;
|
||||
message = receiver.next() => {
|
||||
log::debug!("Received message: {message:?}");
|
||||
log::debug!("Received message: {:?}", message);
|
||||
match message {
|
||||
Some(Socks5ControlMessage::Stop) => {
|
||||
log::info!("Received stop message");
|
||||
@@ -209,7 +209,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
Some(msg) = shutdown.wait_for_error() => {
|
||||
log::info!("Task error: {msg:?}");
|
||||
log::info!("Task error: {:?}", msg);
|
||||
Err(msg)
|
||||
}
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
|
||||
@@ -579,7 +579,7 @@ impl SocksClient {
|
||||
);
|
||||
// Get valid auth methods
|
||||
let methods = self.get_available_methods().await?;
|
||||
trace!("methods: {methods:?}");
|
||||
trace!("methods: {:?}", methods);
|
||||
|
||||
let mut response = [0u8; 2];
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ impl MixnetResponseListener {
|
||||
control_response: ControlResponse,
|
||||
) -> Result<(), Socks5ClientCoreError> {
|
||||
error!("received a control response which we don't know how to handle yet!");
|
||||
error!("got: {control_response:?}");
|
||||
error!("got: {:?}", control_response);
|
||||
|
||||
// I guess we'd need another channel here to forward those to where they need to go
|
||||
|
||||
@@ -88,7 +88,7 @@ impl MixnetResponseListener {
|
||||
}
|
||||
Socks5ResponseContent::Query(response) => {
|
||||
error!("received a query response which we don't know how to handle yet!");
|
||||
error!("got: {response:?}");
|
||||
error!("got: {:?}", response);
|
||||
|
||||
// I guess we'd need another channel here to forward those to where they need to go
|
||||
|
||||
|
||||
@@ -122,7 +122,8 @@ where
|
||||
biased;
|
||||
_ = &mut shutdown_future => {
|
||||
debug!(
|
||||
"closing inbound proxy after outbound was closed {SHUTDOWN_TIMEOUT:?} ago"
|
||||
"closing inbound proxy after outbound was closed {:?} ago",
|
||||
SHUTDOWN_TIMEOUT
|
||||
);
|
||||
// inform remote just in case it was closed because of lack of heartbeat.
|
||||
// worst case the remote will just have couple of false negatives
|
||||
@@ -168,7 +169,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
trace!("{connection_id} - inbound closed");
|
||||
trace!("{} - inbound closed", connection_id);
|
||||
shutdown_notify.notify_one();
|
||||
|
||||
shutdown_listener.disarm();
|
||||
|
||||
@@ -72,12 +72,12 @@ pub(super) async fn run_outbound(
|
||||
}
|
||||
}
|
||||
_ = &mut mix_timeout => {
|
||||
warn!("didn't get anything from the client on {connection_id} mixnet in {MIX_TTL:?}. Shutting down the proxy.");
|
||||
warn!("didn't get anything from the client on {} mixnet in {:?}. Shutting down the proxy.", connection_id, MIX_TTL);
|
||||
// If they were online it's kinda their fault they didn't send any heartbeat messages.
|
||||
break;
|
||||
}
|
||||
_ = &mut shutdown_future => {
|
||||
debug!("closing outbound proxy after inbound was closed {SHUTDOWN_TIMEOUT:?} ago");
|
||||
debug!("closing outbound proxy after inbound was closed {:?} ago", SHUTDOWN_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
_ = shutdown_listener.recv() => {
|
||||
@@ -87,7 +87,7 @@ pub(super) async fn run_outbound(
|
||||
}
|
||||
}
|
||||
|
||||
trace!("{connection_id} - outbound closed");
|
||||
trace!("{} - outbound closed", connection_id);
|
||||
shutdown_notify.notify_one();
|
||||
|
||||
shutdown_listener.disarm();
|
||||
|
||||
@@ -360,7 +360,7 @@ impl Socks5RequestContent {
|
||||
let query_bytes: Vec<u8> = make_bincode_serializer()
|
||||
.serialize(&query)
|
||||
.tap_err(|err| {
|
||||
log::error!("Failed to serialize query request: {query:?}: {err}");
|
||||
log::error!("Failed to serialize query request: {:?}: {err}", query);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
std::iter::once(RequestFlag::Query as u8)
|
||||
|
||||
@@ -213,7 +213,7 @@ impl Socks5ResponseContent {
|
||||
let query_bytes: Vec<u8> = make_bincode_serializer()
|
||||
.serialize(&query)
|
||||
.tap_err(|err| {
|
||||
log::error!("Failed to serialize query response: {query:?}: {err}");
|
||||
log::error!("Failed to serialize query response: {:?}: {err}", query);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
std::iter::once(ResponseFlag::Query as u8)
|
||||
|
||||
@@ -77,7 +77,7 @@ impl GatewayStatsControl {
|
||||
fn report_counters(&self) {
|
||||
log::trace!("packet statistics: {:?}", &self.stats);
|
||||
let (summary_sent, summary_recv) = self.stats.summary();
|
||||
log::debug!("{summary_sent}");
|
||||
log::debug!("{summary_recv}");
|
||||
log::debug!("{}", summary_sent);
|
||||
log::debug!("{}", summary_recv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ impl NymApiStatsControl {
|
||||
fn report_counters(&self) {
|
||||
log::trace!("packet statistics: {:?}", &self.stats);
|
||||
let (summary_sent, summary_recv) = self.stats.summary();
|
||||
log::debug!("{summary_sent}");
|
||||
log::debug!("{summary_recv}");
|
||||
log::debug!("{}", summary_sent);
|
||||
log::debug!("{}", summary_recv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,8 +529,8 @@ impl PacketStatisticsControl {
|
||||
fn report_counters(&self) {
|
||||
log::trace!("packet statistics: {:?}", &self.stats);
|
||||
let (summary_sent, summary_recv) = self.stats.summary();
|
||||
log::debug!("{summary_sent}");
|
||||
log::debug!("{summary_recv}");
|
||||
log::debug!("{}", summary_sent);
|
||||
log::debug!("{}", summary_recv);
|
||||
}
|
||||
|
||||
fn check_for_notable_events(&self) {
|
||||
|
||||
@@ -41,7 +41,7 @@ fn generate_stats_id<M: AsRef<[u8]>>(prefix: &str, id_seed: M) -> String {
|
||||
hasher.update(prefix);
|
||||
hasher.update(&id_seed);
|
||||
let output = hasher.finalize();
|
||||
format!("{output:x}")
|
||||
format!("{:x}", output)
|
||||
}
|
||||
|
||||
pub fn hash_identifier<M: AsRef<[u8]>>(identifier: M) -> String {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user