* feat(db): add SQL query wrapper for PostgreSQL placeholder conversion - Created query_wrapper module with functions to automatically convert SQLite ? placeholders to PostgreSQL $1, $2, ... format - Updated build.rs to handle mutually exclusive feature flags - Modified one query in mixnodes.rs as proof of concept - Added type conversions for PostgreSQL compatibility (u32->i64, u16->i32) This is a checkpoint commit before converting all queries to use the wrapper. * feat(nym-node-status-api): add PostgreSQL database support via feature flags Implement dual database support for SQLite and PostgreSQL through Cargo feature flags. The implementation uses a query wrapper that automatically converts SQLite-style ? placeholders to PostgreSQL-style $1, $2, ... placeholders at runtime. Key changes: - Add query wrapper functions that handle placeholder conversion - Convert all sqlx::query\! macros to use wrapper functions - Handle type conversions between databases (i64 vs i32) - Add feature-gated implementations for database-specific SQL syntax - Update Makefile with clippy targets for both database features - Document database support in README * feat(nym-node-status-agent): add multi-API support with random selection Agents can now connect to multiple APIs and randomly select one for each testrun: - Accept multiple --server arguments in format "address:port:auth_key" - Randomly shuffle server list before attempting connections - Try each server until a testrun is obtained - Submit results back only to the API that provided the testrun - Continue to next server if one is down or has no testruns available * feat(nym-node-status): implement primary/secondary server architecture - Agent now requests testruns only from primary server (first in list) - Results are submitted to all configured servers in parallel - Secondary servers accept external testruns via new v2 endpoint - Added auto-creation of gateway and testrun records on secondary servers - New database queries: get_or_create_gateway, insert_external_testrun - Client library enhanced with submit_results_with_context method * Bump Node status API version * Fix build workdir * Bump to 3.1.4 * Fix types and queries * 3.1.6 * Fix gateway perf, bump 3.1.7 * NodeId -> i32, 3.1.8 * Bump agent version * i64 -> i32 * Use image yq * Migration and more types * Update remaining JSONB columns * Simplify server config * Update build path * Change delimiter * bump agent * Split up pg and sqlite builds * More typing fixes, build-and-push script * Fix Dockerfile-pg * Bump node-status-api * TYping * Agent build script * More logging around testruns * Fail loudly on read errors * Cleanup * Debug get gateways query * Fix get_gateways query * Use pg cert, 3.1.16 * Submit regular results to primary server * Bump freshenss cutoff * Update Cargo.lock * fix: resolve rebase conflicts and compilation errors After rebasing onto develop, fixed several issues: - Fixed borrowed data escapes error by using sqlx::query directly in transaction functions - Removed unused imports and cleaned up code - Maintained database-specific implementations for transaction functions * fmt * Make PG default to make lives easier * Performance improvements for Explorer v2 * Fix sqlite build * Fix PG migration * Tests round 1 * DB tests * More tests * And some more tests * And some more, more tests * cargo fmt * Fix some failing lints * Fix lioness version problems * Clippy in tests --------- Co-authored-by: dynco-nym <173912580+dynco-nym@users.noreply.github.com>
20 KiB
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
# 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
# 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
# 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
# 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
# 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
# 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:
-
Core Mixnet Infrastructure:
nym-node: Core binary supporting mixnode and gateway modescommon/nymsphinx: Implementation of the Sphinx packet formatcommon/topology: Network topology managementcommon/types: Shared data types across components
-
Network Monitoring:
nym-network-monitor: Monitors the network's reliability and performancenym-api: API server for network stats and monitoring data- Metrics tracking for nodes, routes, and overall network health
-
Client Implementations:
clients/native: Native Rust client implementationclients/socks5: SOCKS5 proxy client for standard applicationswasm: WebAssembly client implementations (for browsers)nym-connect: Desktop and mobile clients
-
Blockchain & Smart Contracts:
common/cosmwasm-smart-contracts: Smart contract implementationscontracts: CosmWasm contracts for the Nym networkcommon/ledger: Blockchain integration
-
Utilities & Tools:
tools: Various CLI tools and utilitiessdk: SDKs for different languages and platformsdocumentation: Documentation generation and management
Packet System
Nym uses a modified Sphinx packet format for its mixnet:
-
Message Chunking:
- Messages are divided into "sets" and "fragments"
- Each fragment fits in a single Sphinx packet
- The
common/nymsphinx/chunkingmodule handles message fragmentation
-
Routing:
- Packets traverse through 3 layers of mixnodes
- Routing information is encrypted in layers (onion routing)
- The final gateway receives and processes the messages
-
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:
-
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
-
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)
-
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
-
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:
- The
nym-network-monitorsends test packets through the network - These packets follow predefined routes through multiple mixnodes
- Metrics are collected about:
- Successful and failed packet deliveries
- Node reliability (percentage of successful packet handling)
- Route reliability (which specific route combinations work best)
- Results are stored in the database and used by
nym-apito:- 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-opttool frombinaryen - 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
# 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
# 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
-
Install Prerequisites
# 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 -
Clone and Setup Repository
git clone https://github.com/nymtech/nym.git cd nym/nym # Install JavaScript dependencies yarn install # Build the project make build -
Database Setup (Optional, for API development)
# Install PostgreSQL # Create database createdb nym_api # Run migrations (from nym-api directory) cd nym-api sqlx migrate run
Quick Start
# 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:
-
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)
-
Release Process:
- Binary artifacts are published on release tags
- Multiple platform builds are created
-
Documentation:
- Documentation is automatically built and deployed
Database Structure
The system uses SQLite databases with tables like:
mixnode_status: Status information about mixnodesgateway_status: Status information about gatewaysroutes: 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:
# 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
.envfiles 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 componentscommon/crypto: Cryptographic primitives and wrapperscommon/client-core: Core client functionalitycommon/gateway-client: Client-gateway communicationcommon/task: Task management and concurrency utilitiescommon/nymsphinx: Sphinx packet implementation for mixnetcommon/topology: Network topology managementcommon/credentials: Credential system for privacy-preserving authenticationcommon/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 testbefore submitting PRs - Follow Rust naming conventions
- Use
clippyto 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 checkto verify dependency compliance - Test against both sandbox and local environments when possible
- Update relevant documentation and CHANGELOG.md
Development Tools
Useful Cargo Commands
# 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
# 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 filesscripts/node_api_check.py: Verify node API endpointsscripts/network_tunnel_manager.sh: Manage network tunnelsscripts/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 configurationsmixnode/: Mixnode deployment playbooksgateway/: Gateway deployment playbooksvalidator/: Validator node deploymentsandbox-v2/: Complete sandbox environment setupbig-dipper-2/: Block explorer deployment
Sandbox V2 Deployment
The sandbox-v2 deployment (deployment/sandbox-v2/) provides a complete test environment:
# 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:
- Copy an existing env file:
cp envs/sandbox.env envs/custom.env - Modify the network endpoints and contract addresses
- Update the
NETWORK_NAMEto your identifier - 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:
# 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:
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
- API health:
Build Problems
- Clean dependencies with
cargo cleanfor 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:
rustup target add wasm32-unknown-unknown - For "cannot find -lpq" errors, install PostgreSQL development files:
# 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
-
Route monitoring metrics are stored in a
routestable with:- Layer node IDs (layer1, layer2, layer3, gw)
- Success flag (boolean)
- Timestamp
-
To analyze routes:
- Check
NetworkAccountandAccountingRouteinnym-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_dbfunction
- Check
Performance Optimization
Profiling and Benchmarking
# 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
jemallocfor better memory allocation performance