Skip to content

Run a validator

Validators reach agreement through SecureWeave, NDSR’s BFT voting layer (quorum ⌊2n/3⌋+1, equivocation proofs, vote gossip and persistence).

  • Executes direct calls (/v1/execute) and keeps every module’s state, with state sync from peers.
  • Verifies committee votes, audits a random 10 % of rounds plus every contested one, and signs finality records.
  • Checks and signs miner-set snapshots against its own Sepolia RPC.
  • Proposes and attests per-project reward receipts; records slashing evidence.

Finality and audits · State sync

  • An always-on Linux server (x86_64 or aarch64) with a public HTTPS URL (validators receive inbound requests from the Hub and from each other). The testnet validators run on 1 vCPU / 1 GB / 10 GB machines.
  • The ndsr binary built from the runtime’s source (cargo build --release --bin ndsr).
  • One or more Sepolia JSON-RPC endpoints.
  • An EVM payout address.
  1. Create the node identity:

    Terminal window
    ndsr keygen --data-dir /var/lib/ndsr
    # {"key_file":"/var/lib/ndsr/node.key","node_id":"ndsr-…","public_key":"0x…"}
  2. Start the node in committee mode (a non-loopback bind requires an API token of at least 16 characters):

    Terminal window
    export NDSR_API_TOKEN=$(openssl rand -hex 24) # keep it secret; the Hub uses it as a bearer token
    ndsr serve \
    --data-dir /var/lib/ndsr --bind 0.0.0.0:7070 \
    --ccs https://testnet-rpc.necter.network \
    --hub https://testnet-rpc.necter.network \
    --node-url https://node.example.org \
    --payout-address 0xYOUR_PAYOUT_ADDRESS \
    --chain-rpc https://ethereum-sepolia-rpc.publicnode.com --chain-rpc https://1rpc.io/sepolia \
    --chain-id 11155111 --network necter-testnet \
    --persist-ledger

    Put TLS in front of port 7070 (any reverse proxy) so --node-url is reachable over HTTPS.

  3. The node registers itself with a signed request and appears as pending. Once approved and flagged, it syncs the validator set, starts receiving rounds and catches up module state from its peers.

Flag (env) Default
--data-dir (NDSR_DATA_DIR) ndsr-data node.key, state.db, consensus.db, ledger.db, modules/
--bind (NDSR_BIND) 127.0.0.1:7070 non-loopback requires NDSR_API_TOKEN
--ccs (NDSR_CCS_URL) registration, heartbeats, receipts, artifact fetch
--hub (NDSR_HUB_URL) the --ccs URL base URL for /v1 calls
--node-url (NDSR_NODE_URL) public URL the Hub and peers use
--payout-address (NDSR_PAYOUT_ADDRESS) EVM address for this node’s rewards
--chain-rpc (NDSR_CHAIN_RPC) Sepolia RPC, repeatable, tried in order; enables committee mode
--chain-confirmations 32 reorg depth used when finalized lags
--chain-id 11155111 checked against eth_chainId
--chain-start-block 0 first block of event replay (the testnet contracts were deployed at block 11870176)
--staking-contract, --registry-contract from the Hub’s GET /
--network necter-testnet
--network-params FILE built-in testnet values refused if its hash differs from GET /v1/network/params
--epoch-secs, --gas-per-unit 3600, 1000000 network parameters: must match every other validator
--exec-workers, --exec-queue CPUs (2..16), 64 execution pool; /execute answers 503 beyond it
--state-sync true attest module state roots and catch up from peers
--max-gas 10^10 largest gas_limit accepted (must match the network)

ndsr serve --help lists every flag.

Route
GET /health, GET /node liveness and identity (open)
GET /status executions, gas, rounds, gossip, rewards, pool, state sync; capabilities: {committee, receipt_v2, chain_rpc}; full detail with the bearer token
GET /consensus/rounds/{round_id} tally, finality, own vote
GET /consensus/evidence slashing evidence this node recorded
GET /ledger?module=&function=&limit= recent signed receipts (with --persist-ledger)

Committee mode is switched on for the network only when every current validator reports capabilities.committee = true.