Part of the Quantova Consensus Specifications. Mirrors Chapter 17 — Running Nodes & Operator RPC and the JSON-RPC reference of the developer documentation.
How to build the Quantova node from source, run a full / archive / validator node, configure the operator RPC surface safely, and talk to the JSON-RPC API. Validators should read this alongside the staking requirements and the quantum-security spec.
# 1. Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
# 2. Build dependencies
sudo apt-get update && sudo apt-get install -y --no-install-recommends \
clang cmake pkg-config libssl-dev protobuf-compiler libprotobuf-dev \
libclang-dev build-essential git
# 3. Clone + submodules
git clone https://github.com/quantova/quantova.git && cd quantova
git submodule update --init --force --recursive
# 4. Build
cargo build --release --bin quantova-node./target/release/quantova-node --dev --ws-external
# point the SDK at ws://127.0.0.1:9944./target/release/quantova-node \
--base-path ~/.quantova/rpc --chain mainnet --name "RPC-Node-001" \
--port 30333 --rpc-port 9933 --ws-port 9944 \
--ws-external --rpc-cors all \
--rpc-max-connections 1000 --prometheus-port 9615
# add --pruning archive for full historical state (indexers, oracles)./target/release/quantova-node \
--base-path ~/.quantova/validator --chain mainnet --validator \
--name "My-Validator" --port 30333 --rpc-port 9933 --ws-port 9944 \
--bootnodes "/ip4/BOOTNODE_IP/tcp/30333/p2p/BOOTNODE_PEER_ID" \
--prometheus-port 9615Validator checklist: generate / rotate session keys (author_rotateKeys) and register
them on-chain; keep session keys separate from funded accounts; keep P2P reachable; monitor
sync, production, and finality lag; bond a stash, set preferences, then submit
staking.validate and wait for election at an era boundary.
| Flag | Purpose |
|---|---|
--ws-external / --rpc-external |
Bind RPC/WS to all interfaces (place behind a proxy/firewall). |
--rpc-cors all |
Allow browser origins (lock down in production). |
--rpc-methods=Safe|Unsafe |
Keep Safe in production. Unsafe only on trusted networks. |
--rpc-max-connections |
Cap concurrent clients. |
--pruning archive |
Retain full historical state (indexer / oracle workloads). |
--prometheus-port |
Expose metrics (peers, import queue, height / finality lag). |
Treat RPC as an edge surface. P2P ports must stay reachable for sync and consensus. RPC ports are an application interface — authenticate, rate-limit expensive methods, disable unnecessary modules, and never expose unsafe methods or dev signers publicly.
Every method is a POST to the HTTP endpoint with a JSON body
{jsonrpc, id, method, params}. params is a JSON array in the documented order. Account
addresses are passed as Q-format strings; numeric results (balances, gas) come back as
QUANTITY hex you convert to a number.
curl -s http://127.0.0.1:9933 \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "q_getBalance",
"params": ["Q8f3c…a91b", "0x1554ec6"]
}'
# -> {"jsonrpc":"2.0","id":1,"result":"0x7b2f1c8a0d9e4000"}
# 0x7b2f1c8a0d9e4000 / 10^18 = 8.876 QTOVparams = [ Q-address, block ]; the result is a QUANTITY in base units. Convert with
parseInt(result, 16) (JavaScript) or int(result, 16) (Python). Named tags like "latest"
are not implemented — pass a block-number QUANTITY.
const RPC = "http://127.0.0.1:9933";
async function q(method, params = []) {
const res = await fetch(RPC, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
const { result, error } = await res.json();
if (error) throw new Error(error.message);
return result;
}
const ADDRESS = "Q8f3c…a91b";
const height = await q("q_blockNumber"); // "0x15536ee"
const balance = await q("q_getBalance", [ADDRESS, height]); // params is an array
console.log("balance:", parseInt(balance, 16) / 1e18, "QTOV");import requests
RPC = "http://127.0.0.1:9933"
def q(method, params=None):
body = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params or []}
r = requests.post(RPC, json=body, timeout=10)
r.raise_for_status()
out = r.json()
if "error" in out:
raise RuntimeError(out["error"]["message"])
return out["result"]
ADDRESS = "Q8f3c…a91b"
height = int(q("q_blockNumber"), 16) # hex QUANTITY -> int
balance = int(q("q_getBalance", [ADDRESS, hex(height)]), 16)
print("balance:", balance / 1e18, "QTOV")| Method | Params | What it does |
|---|---|---|
q_getBalance |
address, block | QTOV balance in base units (QUANTITY). |
q_getTransactionCount |
address, block | Account nonce; set the next transaction's nonce. |
q_getCode |
address, block | Deployed QVM bytecode at an address, or 0x if not a contract. |
q_getStorageAt |
address, slot, block | Raw 32-byte value in a contract storage slot. |
q_call |
call object, block | Read-only contract call; returns return data, spends no QGAS. |
q_estimateGas |
call object | QGAS a call/deployment would consume. |
| Method | Params | What it does |
|---|---|---|
q_blockNumber |
— | Height of the most recent block (QUANTITY). |
q_getBlockByNumber |
number, fullTx | A block by height, with tx hashes or full tx objects. |
q_getBlockByHash |
hash, fullTx | A block by its 32-byte SHA3 hash. |
| Method | Params | What it does |
|---|---|---|
q_sendRawTransaction |
signed tx (DATA) | Submit an already-signed, serialized QVM transaction. Sign locally with a post-quantum key, then broadcast. Returns the 32-byte tx hash. |
q_sendTransaction |
tx object | Submit a tx from an account the node holds (operator/dev use). |
q_getTransactionReceipt |
tx hash | Receipt — status, QGAS used, logs, new contract address. Poll to confirm. |
| Method | Params | What it does |
|---|---|---|
q_chainId |
— | Chain id, used in signing to prevent cross-chain replay. |
q_syncing |
— | Sync-progress object while catching up, or false when synced. |
q_net_version |
— | Network id. |
q_web3_clientVersion |
— | Node client version string. |
The full JSON-RPC reference (fee/gas methods, the
q_callcall-object schema, REST developer endpoints, address encoding, and data types) is in the developer documentation.
Back to README · See also 05 — Quantum Security