Get started mining on the Quantus Network testnet in minutes.
Note: This guide contains both practical setup instructions for miners and technical protocol specifications for developers. If you're building custom miner implementations, see the External Miner Protocol Specification section at the end.
- You provide a 32-byte preimage when starting mining
- The system derives your wormhole address using Poseidon hashing
- All mining rewards are sent to this derived wormhole address
- This ensures all miners use privacy-preserving wormhole addresses
- CPU: 2+ cores
- RAM: 4GB
- Storage: 100GB available space
- Network: Stable internet connection (3+ Mbps)
- OS: Linux (Ubuntu 20.04+), macOS (10.15+), or Windows WSL2
β οΈ Connections below 3 Mbps will likely fail to keep the node synced with the network.
- CPU: 4+ cores (higher core count improves mining performance - coming soon)
- RAM: 8GB+
- Storage: 500GB+ SSD
- Network: Broadband connection (10+ Mbps)
If you prefer manual installation or the script doesn't work for your system:
-
Download Binary
Get the latest binary GitHub Releases
-
Generate Node Identity
./quantus-node key generate-node-key --file ~/.quantus/node_key.p2p -
Generate Wormhole Address & Preimage
./quantus-node key quantus --scheme wormhole
This generates a wormhole key pair and shows:
Address: Your wormhole address (where rewards will be sent)inner_hash: Your 32-byte preimage (use this for mining)
Save the preimage - you'll need it for the
--rewards-addressparameter. -
Run the node (Planck network)
Minimal command - see --help for many more options
./quantus-node \
--validator \
--chain planck \
--node-key-file ~/.quantus/node_key.p2p \
--rewards-inner-hash <YOUR_PREIMAGE_FROM_STEP_3> \
--max-blocks-per-request 64 \
--sync fullNote: Use the inner_hash from step 3 as your --rewards-inner-hash. The node will derive your wormhole address and log it on startup.
For users who prefer containerized deployment or have only Docker installed:
Follow these steps to get your Docker-based validator node running:
Step 1: Prepare a Local Directory for Node Data
Create a dedicated directory on your host machine to store persistent node data, such as your P2P key and rewards address file.
mkdir -p ./quantus_node_dataThis command creates a directory named quantus_node_data in your current working directory.
Optional Linux On linux you may need to make sure this directory has generous permissions so Docker can access it
chmod 755 quantus_node_dataStep 2: Generate Your Node Identity (P2P Key)
Your node needs a unique P2P identity to connect to the network. Generate this key into your data directory:
# If on Apple Silicon, you may need to add --platform linux/amd64
docker run --rm --platform linux/amd64 \
-v "$(pwd)/quantus_node_data":/var/lib/quantus_data_in_container \
ghcr.io/quantus-network/quantus-node:latest \
key generate-node-key --file /var/lib/quantus_data_in_container/node_key.p2pReplace quantus-node:v0.0.4 with your desired image (e.g., ghcr.io/quantus-network/quantus-node:latest).
This command saves node_key.p2p into your local ./quantus_node_data directory.
Step 3: Generate Your Wormhole Address
# If on Apple Silicon, you may need to add --platform linux/amd64
docker run --rm ghcr.io/quantus-network/quantus-node:latest key quantus --scheme wormholeThis generates a wormhole key pair. Save the inner_hash value - this is your preimage for mining.
Step 4: Run the Validator Node
# If on Apple Silicon, you may need to add --platform linux/amd64
# Replace YOUR_PREIMAGE with the inner_hash from step 3
docker run -d \
--name quantus-node \
--restart unless-stopped \
-v "$(pwd)/quantus_node_data":/var/lib/quantus \
-p 30333:30333 \
-p 9944:9944 \
ghcr.io/quantus-network/quantus-node:latest \
--validator \
--base-path /var/lib/quantus \
--chain planck \
--node-key-file /var/lib/quantus/node_key.p2p \
--rewards-inner-hash <YOUR_PREIMAGE>Note for Apple Silicon (M1/M2/M3) users: As mentioned above, if you are using an amd64 based Docker image on an ARM-based Mac, you will likely need to add the --platform linux/amd64 flag to your docker run commands.
Your node should now be starting up! You can check its logs using docker logs -f quantus-node.
View logs
docker logs -f quantus-nodeStop node
docker stop quantus-nodeStart node again
docker start quantus-nodeRemove container
docker stop quantus-node && docker rm quantus-nodeWhen a new version is released:
# Stop and remove current container
docker stop quantus-node && docker rm quantus-node
# Pull latest image
docker pull ghcr.io/quantus-network/quantus-node:latest
# Start new container (data is preserved in ~/.quantus)
./run-node.sh --mode validator --rewards YOUR_ADDRESS_HERECustom data directory
./run-node.sh --data-dir /path/to/custom/data --name "my-node"Specific version
docker run -d \
--name quantus-node \
--restart unless-stopped \
-p 30333:30333 \
-p 9944:9944 \
-v ~/.quantus:/var/lib/quantus \
ghcr.io/quantus-network/quantus-node:latest \
--validator \
--base-path /var/lib/quantus \
--chain planck \
--rewards-address YOUR_ADDRESS_HEREDocker system requirements
- Docker 20.10+ or compatible runtime
- All other system requirements same as binary installation
For high-performance mining, you can offload the mining process to a separate service, freeing up node resources.
-
Download Node Binary:
Get the latest
quantus-nodebinary from GitHub Releases. -
Download External Miner Binary:
Get the latest
quantus-minerbinary from GitHub Releases.
-
Generate Your Wormhole Address:
./quantus-node key quantus --scheme wormhole
Save the
inner_hashvalue. -
Start the Node (QUIC server for miners):
# Replace <YOUR_PREIMAGE> with the inner_hash from step 1 RUST_LOG=info,sc_consensus_pow=debug ./quantus-node \ --validator \ --chain planck \ --miner-listen-port 9833 \ --rewards-inner-hash <YOUR_PREIMAGE>
The node binds a QUIC server on
0.0.0.0:9833and waits for miners to connect. When--miner-listen-portis set, local mining is disabled. -
Start External Miner (in separate terminal, connects to the node):
RUST_LOG=info ./quantus-miner serve --node-addr 127.0.0.1:9833
Useful flags:
--cpu-workers <N>,--gpu-devices <N>,--metrics-port <PORT>(default9900). If the node is on another host, replace127.0.0.1with its IP.
For developers building custom miner implementations, see the External Miner Protocol Specification section below.
| Parameter | Description | Default |
|---|---|---|
--node-key-file |
Path to P2P identity file | Required |
--rewards-inner-hash |
Wormhole preimage (inner_hash from key generation) | Required |
--chain |
Chain specification | planck |
--port |
P2P networking port | 30333 |
--prometheus-port |
Metrics endpoint port | 9616 |
--name |
Node display name | Auto-generated |
--base-path |
Data directory | ~/.local/share/quantus-node |
View Logs
# Real-time logs
tail -f ~/.local/share/quantus-node/chains/planck/network/quantus-node.log
# Or run with verbose logging
RUST_LOG=info quantus-node [options]Prometheus Metrics
Visit http://localhost:9616/metrics to view detailed node metrics.
RPC Endpoint
Use the RPC endpoint at http://localhost:9944 to query blockchain state:
# Check latest block
curl -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"chain_getBlock","params":[]}' \
http://localhost:9944View Balance at Your Wormhole Address
# Replace YOUR_WORMHOLE_ADDRESS with your wormhole address from key generation
curl -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"faucet_getAccountInfo","params":["YOUR_WORMHOLE_ADDRESS"]}' \
http://localhost:9944Find Your Wormhole Address
- From key generation: Use the
Addressfield from./quantus-node key quantus --scheme wormhole - From node logs: Check startup logs for "Mining rewards will be sent to wormhole address"
- Chain: Planck network
- Consensus: Quantum Proof of Work (QPoW)
- Block Time: ~6 seconds target
- Network Explorer: Coming soon
- Faucet: See Telegram
Port Already in Use
# Use different ports
quantus-node --port 30334 --prometheus-port 9617 [other options]Database Corruption
# Purge and resync
quantus-node purge-chain --chain planckMining Not Working
- Check that
--validatorflag is present - Verify your preimage from
inner_hashfield in key generation - Ensure node is synchronized (check logs for "Imported #XXXX")
Wormhole Address Issues
- Can't find rewards: Check the
Addressfield from your key generation - Invalid preimage: Use the exact
inner_hashvalue from key generation - Wrong address: Rewards go to the wormhole address, not the preimage
Connection Issues
- Check firewall settings (allow port 30333)
- Verify internet connection
- Try different bootnodes if connectivity problems persist
- GitHub Issues: Report bugs and issues
- Discord: Join our community (link coming soon)
- Documentation: Technical docs
Enable Debug Logging
RUST_LOG=debug,sc_consensus_pow=trace quantus-node [options]Export Node Info
# Node identity
quantus-node key inspect-node-key --file ~/.quantus/node_key.p2p
# Network info
curl -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"system_networkState","params":[]}' \
http://localhost:9944- Automatic Wormhole Addresses: All mining rewards go to your wormhole address
- Privacy by Design: Your reward address is derived from your preimage
- Block Rewards: Earned by successfully mining blocks
- Transaction Fees: Collected from transactions in mined blocks
- Network Incentives: Additional rewards for network participation
Mining performance depends on:
- CPU performance (cores and clock speed)
- Network latency to other nodes
- Node synchronization status
- Competition from other miners
- Backup Your Keys: Securely store your wormhole key pair from key generation
- Backup Node Keys: Store copies of your node identity keys safely
- Secure Storage: Keep preimages and private keys in encrypted storage
- Firewall: Only expose necessary ports (30333 for P2P)
- Updates: Keep your node binary updated
- Monitoring: Watch for unusual network activity or performance
This is testnet software for testing purposes only:
- Tokens have no monetary value
- Network may be reset periodically
- Expect bugs and breaking changes
- Do not use for production workloads
- Join the Community: Connect with other miners and developers
- Monitor Performance: Track your mining efficiency and rewards at your wormhole address
- Experiment: Try different configurations and optimizations
- Contribute: Help improve the network by reporting issues and feedback
Happy mining! π
This section defines the QUIC-based protocol for communication between the Quantus Network node and external miner services. This is technical documentation for developers building custom miner implementations.
The node delegates the mining task (finding a valid nonce) to external miner services over persistent QUIC connections. The node provides the necessary parameters (header hash, difficulty) and each external miner independently searches for a valid nonce according to the PoW rules defined in the qpow-math crate (using Poseidon2 hash function). Miners push results back when found.
- Lower latency: Results are pushed immediately when found (no polling)
- Connection resilience: Built-in connection migration and recovery
- Multiplexed streams: Multiple operations on single connection
- Built-in TLS: Encrypted by default
βββββββββββββββββββββββββββββββββββ
β Node β
β (QUIC Server on port 9833) β
β β
ββββββββββββ β Broadcasts: NewJob β
β Miner 1 β ββconnectββββΊ β Receives: JobResult β
ββββββββββββ β β
β Supports multiple miners β
ββββββββββββ β First valid result wins β
β Miner 2 β ββconnectββββΊ β β
ββββββββββββ βββββββββββββββββββββββββββββββββββ
ββββββββββββ
β Miner 3 β ββconnectββββΊ
ββββββββββββ
- Node acts as the QUIC server, listening on port 9833 (default)
- Miners act as QUIC clients, connecting to the node
- Single bidirectional stream per miner connection
- Connection persists across multiple mining jobs
- Multiple miners can connect simultaneously
When multiple miners are connected:
- Node broadcasts the same
NewJobto all connected miners - Each miner independently selects a random starting nonce
- First miner to find a valid solution sends
JobResult - Node uses the first valid result, ignores subsequent results for same job
- New job broadcast implicitly cancels work on all miners
The protocol uses three message types:
| Direction | Message | Description |
|---|---|---|
| Miner β Node | Ready |
Sent immediately after connecting to establish the stream |
| Node β Miner | NewJob |
Submit a mining job (implicitly cancels any previous job) |
| Miner β Node | JobResult |
Mining result (completed, failed, or cancelled) |
Messages are length-prefixed JSON:
βββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β Length (4 bytes)β JSON payload (MinerMessage) β
β big-endian u32 β β
βββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββ
Maximum message size: 16 MB
See the quantus-miner-api crate for the canonical Rust definitions.
pub enum MinerMessage {
Ready, // Miner β Node: establish stream
NewJob(MiningRequest), // Node β Miner: submit job
JobResult(MiningResult), // Miner β Node: return result
}| Field | Type | Description |
|---|---|---|
job_id |
String | Unique identifier (UUID recommended) |
mining_hash |
String | Header hash (64 hex chars, no 0x prefix) |
distance_threshold |
String | Difficulty (U512 as decimal string) |
Note: Nonce range is not specified - each miner independently selects a random starting point.
| Field | Type | Description |
|---|---|---|
status |
ApiResponseStatus | Result status (see below) |
job_id |
String | Job identifier |
nonce |
Option | Winning nonce (U512 hex, no 0x prefix) |
work |
Option | Winning nonce as bytes (128 hex chars) |
hash_count |
u64 | Number of nonces checked |
elapsed_time |
f64 | Time spent mining (seconds) |
miner_id |
Option | Miner ID (set by node, not miner) |
| Value | Description |
|---|---|
completed |
Valid nonce found |
failed |
Nonce range exhausted without finding solution |
cancelled |
Job was cancelled (new job received) |
running |
Job still in progress (not typically sent) |
Miner Node
β β
βββββ QUIC Connect ββββββββββββββββββββββββββΊβ
βββββ Connection Established βββββββββββββββββ
β β
βββββ Ready βββββββββββββββββββββββββββββββββΊβ (establish stream)
β β
βββββ NewJob { job_id: "abc", ... } ββββββββββ
β β
β (picks random nonce, starts mining) β
β β
βββββ JobResult { job_id: "abc", ... } ββββββΊβ (found solution!)
β β
β (node submits block, gets new work) β
β β
βββββ NewJob { job_id: "def", ... } ββββββββββ
β β
When a new block arrives before the miner finds a solution, the node simply sends a new NewJob. The miner automatically cancels the previous job:
Miner Node
β β
βββββ NewJob { job_id: "abc", ... } ββββββββββ
β β
β (mining "abc") β
β β
β (new block arrives at node!) β
β β
βββββ NewJob { job_id: "def", ... } ββββββββββ
β β
β (cancels "abc", starts "def") β
β β
βββββ JobResult { job_id: "def", ... } ββββββΊβ
When a miner connects while a job is active, it immediately receives the current job:
Miner (new) Node
β β (already mining job "abc")
βββββ QUIC Connect ββββββββββββββββββββββββββΊβ
βββββ Connection Established βββββββββββββββββ
β β
βββββ Ready βββββββββββββββββββββββββββββββββΊβ (establish stream)
β β
βββββ NewJob { job_id: "abc", ... } ββββββββββ (current job sent immediately)
β β
β (joins mining effort) β
If a result arrives for an old job, the node discards it:
Miner Node
β β
βββββ NewJob { job_id: "abc", ... } ββββββββββ
β β
βββββ NewJob { job_id: "def", ... } ββββββββββ (almost simultaneous)
β β
βββββ JobResult { job_id: "abc", ... } ββββββΊβ (stale, node ignores)
β β
βββββ JobResult { job_id: "def", ... } ββββββΊβ (current, node uses)
# Listen for external miner connections on port 9833
quantus-node --miner-listen-port 9833# Connect to node
quantus-miner serve --node-addr 127.0.0.1:9833The node generates a self-signed TLS certificate at startup. The miner skips certificate verification by default (insecure mode). For production deployments, consider:
- Certificate pinning: Configure the miner to accept only specific certificate fingerprints
- Proper CA: Use certificates signed by a trusted CA
- Network isolation: Run node and miner on a private network
The miner automatically reconnects with exponential backoff:
- Initial delay: 1 second
- Maximum delay: 30 seconds
The node continues operating with remaining connected miners.
If the miner receives an invalid MiningRequest, it sends a JobResult with status failed.
- All hex values should be sent without the
0xprefix - The miner implements validation logic from
qpow_math::is_valid_nonce - The node uses the
workfield fromMiningResultto constructQPoWSeal - ALPN protocol identifier:
quantus-miner - Each miner independently generates a random nonce starting point using cryptographically secure randomness
- With a 512-bit nonce space, collision between miners is statistically impossible
For technical support and updates, visit the Quantus Network GitHub repository.