JSON-RPC and dev mode
Quantum exposes standard Ethereum JSON-RPC on port 8545 (HTTP) and 8546 (WebSocket), with a small surface of Quantum-specific extensions. The intent is maximum compatibility: most read endpoints work unchanged with ethers, viem, and other clients. Write endpoints work too, but only for Quantum transactions (EIP-2718 type 0x7A) — there is no legacy / 1559 / 2930 / 4844 / 7702 transaction support.
Standard endpoints
# Check chain ID
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
# Get block by number
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest", true],"id":1}'
# Get transaction by hash
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x..."],"id":1}'
Block headers carry a synthetic timestampMillis = timestamp * 1000 + timestampMillisPart for clients that want sub-second precision. The standard timestamp field is still the second-level value, so existing tooling sees a normal Ethereum-shaped response.
Quantum-specific endpoints
# Consensus status
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"consensus_status","params":[],"id":1}'
Additional endpoints exposed for the Quantum chain are documented alongside the chain spec; the standard eth_* and net_* namespaces work as expected for reads.
Dev mode
cargo run --bin quantum-reth -- node --dev --http.api all brings up a single-validator devnet. Dev mode:
- Auto-generates keys.
- Creates a single-validator set.
- Prefunds 10 ML-DSA-44 derived accounts with 10,000 QBIT each.
- Selects
marshal::standard(single node).
Dev account derivation is deterministic:
seed_i = sha256("quantum-ml-dsa-dev-" + i) for i in 0..9
sk_i, pk_i = MlDsa::generate_from_seed(seed_i)
addr_i = keccak256(pk_i)[12..]
balance = 10,000 QBIT
These keys are deterministic and public — never use them in production.
Wallet configuration
When adding Quantum as a custom network in MetaMask or other wallets:
- Currency Symbol: QBIT
- Decimals: 18
The currency symbol is wallet-side configuration, not an on-chain setting (it lives in chainspec/chain.toml).
Multi-node localnet
The minimum Coding-variant localnet is 4 validators (N ≥ 4 selects marshal::coding, N = 1 selects marshal::standard, N ∈ {2, 3} is rejected):
cargo run --bin quantum-reth -- localnet init --nodes 4 --output ./localnet
localnet init prints one launch command per node — copy each into a separate terminal. If you script the launches with background &, insert sleep 0.1 between launches to avoid the commonware-p2p bind race.
Footprint guidance
Recommended: build with --release if your laptop has under 32 GB of RAM. Debug-build steady-state at empty blocks is roughly:
- ~10 GB total RSS (≈ 2.5 GB per node × 4)
- < 1 core total CPU
Real transaction load grows the numbers. Measured outbound bandwidth at N=4 and N=8 (both Standard and Coding variants) lives in Benchmarks.
Submitting Quantum transactions
The composite tx envelope cannot be built by ethers or viem out of the box — they don't know about EIP-2718 type 0x7A. Use the bundled CLI:
# Bootstrap a new account (first-use registration, creates key_id = 0)
cargo run --bin quantum-send-tx -- bootstrap \
--rpc-url http://localhost:8545 \
--dev-index 0 --fill
# Normal transaction
cargo run --bin quantum-send-tx -- send \
--rpc-url http://localhost:8545 \
--dev-index 0 --fill \
--to 0x... --value 1000000000000000000
# Add co-signer to key_id = 0
cargo run --bin quantum-send-tx -- update-key-auth \
--rpc-url http://localhost:8545 \
--dev-index 0 --fill \
--key-id 0 \
--primary-pubkey 0x... --primary-scheme 1 \
--new-cosigner-pubkey 0x... --cosigner-scheme 2
# Remove co-signer (requires current cosigner sig)
cargo run --bin quantum-send-tx -- update-key-auth \
--rpc-url http://localhost:8545 \
--dev-index 0 --fill \
--key-id 0 \
--primary-pubkey 0x... --primary-scheme 1 \
--cosigner-type p256 --cosigner-dev-index 0 \
--new-cosigner-pubkey "" --cosigner-scheme 0
# Add a new key lane (key_id = 1)
cargo run --bin quantum-send-tx -- add-key \
--rpc-url http://localhost:8545 \
--dev-index 0 --fill \
--key-id 1 \
--primary-pubkey 0x... --primary-scheme 1 \
--permission 0
--dev-indexselects a deterministic dev signing keypair (not a key lane). Bootstrap is always primary-only. Co-signer activation is a separateupdate-key-authstep. The--senderflag supports decoupled account-lane targeting where the signer key does not derive to the sender address.
Lifecycle submission note.
bootstrap,add-key,remove-key, andupdate-key-authdepend on transient bootstrap / auth / lifecycle context written during real transaction validation. RPC simulation rejects those selectors, so use the explicit lifecycle commands instead ofsend/signoreth_call.
Key management operations map
| CLI command | KeyVault operation | Description |
|---|---|---|
bootstrap | bootstrapKey() | First-use registration — creates key_id = 0 as FullAccess primary-only |
add-key | addKey(...) | Add a new key lane — requires FullAccess auth (create-only, not for updates) |
remove-key | removeKey(...) | Remove an existing key lane — requires FullAccess auth (last FullAccess key cannot be removed) |
update-key-auth | updateKeyAuth(...) | Update auth material for an existing key — self-scoped (auth_key_id == target_key_id) |
send / sign | (regular tx) | Normal transaction — rejects KeyVault lifecycle selectors |
Co-signer policy and Scoped delegated permissions are orthogonal controls: a key can independently have co-signer hedging (per-key auth-method policy) and / or Scoped permission restrictions (contract / method / allowance delegation). These are configured separately and coexist.
ERC-20 token operations
The CLI also wraps common ERC-20 flows so you don't need to write Solidity bytecode by hand for testing:
# Deploy MintableERC20 (owner-gated mint / burn)
cargo run --bin quantum-send-tx -- erc20-deploy \
--rpc-url http://localhost:8545 --dev-index 0 --fill \
--name "MultiVM Token" --symbol "MVM" --decimals 18 --initial-supply 1000000
# Read-only query
cargo run --bin quantum-send-tx -- erc20-info \
--rpc-url http://localhost:8545 \
--contract 0x<addr> --balance-of 0x<holder>
# Mint (owner only)
cargo run --bin quantum-send-tx -- erc20-mint \
--rpc-url http://localhost:8545 --dev-index 0 --fill \
--contract 0x<addr> --recipient 0x<to> --amount 10000
# Transfer
cargo run --bin quantum-send-tx -- erc20-transfer \
--rpc-url http://localhost:8545 --dev-index 0 --fill \
--contract 0x<addr> --recipient 0x<to> --amount 100
# Burn from sender's balance
cargo run --bin quantum-send-tx -- erc20-burn \
--rpc-url http://localhost:8545 --dev-index 0 --fill \
--contract 0x<addr> --amount 500
# Transfer ownership
cargo run --bin quantum-send-tx -- erc20-transfer-ownership \
--rpc-url http://localhost:8545 --dev-index 0 --fill \
--contract 0x<addr> --new-owner 0x<new_owner>
--amount is specified in whole tokens and automatically scaled by 10 ^ decimals. erc20-deploy prints the deployed contract address to stdout.
Snapshot and follow-mode
# Sync from a trusted RPC endpoint (no consensus participation)
cargo run --bin quantum-reth -- node --follow ws://127.0.0.1:8561
# Snapshot export (stopped or disposable fresh-node datadirs)
cargo run --bin quantum-reth -- snapshot export \
--datadir /path/to/data --output snapshot
# Snapshot import
cargo run --bin quantum-reth -- snapshot import \
--archive snapshot.tar.lz4 --datadir /path/to/data
Fresh nodes initialize new datadirs with the current storage layout. Snapshot export / import expects the v2 layout (db/, static_files/, and rocksdb/) and is intended for stopped or disposable fresh-node datadirs rather than in-place migration of legacy v1 data.
| Path | Backend | Stores |
|---|---|---|
db/ | MDBX | Canonical hot state and other core execution data |
static_files/ | Static file segments | Receipts, transaction senders, account / storage changesets |
rocksdb/ | RocksDB | History indices, transaction-hash lookups |
Related
- Transaction and block lifecycle — what happens after
eth_sendRawTransaction - Native account abstraction — what's in the envelope you're signing
- Indexer architecture — chain deviations indexers need to account for