REAX.docs Pre-release · not on testnet
MenuMiner guide

Participate

Miner guide

A REAX miner serves an approved decision model behind a signed HTTP endpoint. It answers finite-answer questions with complete probability distributions, fast and faithfully to the reference model. This guide covers what you serve, the contract you implement, what validators expect, and how the reference miner runs.

No miner can join yet

There is no public miner package, no registration and no netuid. The reference miner is private pre-release code that runs locally. Image serving is disabled at the network miner, and the permissionless route carries synthetic traffic only. To discuss operating a miner, use reax.co/apply.

What a miner serves

Miners serve approved model manifests only. The v1 catalog is closed: the owner-signed catalog reax.catalog.v1 maps each public model alias to a list of approved manifests, and a manifest is approved for a question family only after it passes both an absolute quality grade and a power-admission check (see incentives). You cannot bring your own model. An open-model competition would need a new major spec version.

A manifest is identified by manifest_sha256, the SHA-256 of the canonical JSON object:

{
  "model_alias": "…",
  "weights": [{"path": "…", "sha256": "…"}],
  "tokenizer_sha256": "…",
  "config_sha256": "…",
  "adapter_sha256": null,
  "engine_image_digest": "…",
  "inference_config": {
    "dtype": "…",
    "quantization": "…",
    "max_context": 0,
    "prob_extraction": "label_logits_v1",
    "prompt_template_sha256": "…"
  }
}

Probabilities must come from a deterministic extraction, never from sampled text:

label_logits_v1
Candidates rendered in dispatch order with single-token labels; one forward pass; softmax (float32 or higher) over the label-token logits at the answer position.
seq_logprob_v1
For multi-token candidates: p_k ∝ exp(Σ log p(token_j | prefix)) with teacher forcing.

Temperature, top-p and seeds are irrelevant to p. Free-text generation followed by parsing is forbidden as a probability source. The miner and the reference processor must use the same engine image digest and prompt template.

Code today vs spec

The reference miner does not yet sign a full manifest digest. It binds a single model_revision: the exact lowercase SHA-256 revision reported by its local engine. The response is rejected if the engine reports a different revision. The manifest digest and prob_extraction field are spec 0.6 targets.

Request and response contract

The reference miner exposes two routes:

RoutePurpose
POST /v1/decideSigned decision request in, signed decision response out
GET /healthzReturns {"schema":"reax.miner.v1","status":"configured"}. This means the configuration loaded; it is not a model-readiness check

Request

A decide call must carry exactly one Reax-Authorization header, Content-Type: application/json and no Content-Encoding. The header is checked before the body is read, so unknown callers are rejected before intake. The body is a signed reax.request.v2 envelope whose audience is your miner hotkey:

{
  "schema": "reax.request.v2",
  "audience": "<miner hotkey>",
  "caller": "<caller id>",
  "request": { "protocol_version": "1", "request_id": "d_…", "nonce": "…", "tier": "global_permissionless", "model": "…", "state": {}, "questions": {}, "deadline_unix_ms": 0 },
  "signature": "<Ed25519 over the RFC 8785 form of every other field, 128 hex chars>"
}

The miner then checks, in order: the caller grant and signature, audience and grant expiry, the request schema (see protocol reference), the caller's permitted tiers, the image gate, GDPR admission for gdpr_eu requests, that real permissionless traffic is disabled, and finally a durable replay claim on request_id and nonce.

Response

On success the miner returns a reax.response.v1 envelope signed with its serving key:

{
  "schema": "reax.response.v1",
  "miner": "<miner hotkey>",
  "request_digest": "<SHA-256 of the canonical request envelope>",
  "nonce": "<request nonce>",
  "result": {
    "request_id": "d_…",
    "model": "…",
    "answers": { "<question id>": { "type": "choice", "choice": "…", "confidence": 0.0, "probabilities": {} } },
    "usage": { "input_tokens": 0, "output_tokens": 0, "decisions": 1 },
    "latency_ms": 0.0,
    "tokenizer_version": "…",
    "model_revision": "<64 hex chars>"
  },
  "signature": "<128 hex chars>"
}

The gateway rejects the response unless the signature verifies against your registered serving key, every binding (hotkey, nonce, request digest) matches, it arrived before the deadline, every answer passes validation, decisions equals the number of questions, and model_revision matches your approved identity. Answer formats are in the protocol reference.

Spec 0.6 replaces this body with reax.response.v2, which adds serving_key_id, dispatch_id, manifest_sha256 and completed_at_ms; see miner response.

Errors

Errors are generic JSON with no exception contents, because those could contain customer text or credentials:

StatusBodyWhen
400invalid_requestSchema, media type, size or image policy violation
403unauthorized_or_replayedAuthentication, tier, admission or replay failure
404not_foundAny other route or method
429capacityAll max_inflight slots are busy
502inference_failedEngine failure or invalid engine output
504deadline_exceededThe request deadline passed

Latency and availability expectations

Validators score availability and latency from gateway measurements, not from anything the miner reports (latency_ms in the response is informational).

How these combine into a weight is covered in scoring and incentives.

GDPR tier vs permissionless tier

RequirementGDPR tier (gdpr_eu)Permissionless (global_permissionless)
OperatorEU-established legal entity; off-chain KYB, contract and DPAAny chain-registered hotkey
AdmissionListed in a currently valid signed admission snapshot that binds hotkey, models, exact model revision and serving public keySigned miner record plus conformance; eligibility after the first complete fidelity window
LocationEvery processing country and every subprocessor country must be in the EU; establishment country alone never satisfies a regionNo location claim is made or accepted
DataAdmitted EU requests; the operator sees plaintext while inferringSynthetic traffic only; never personal, sensitive or GDPR-tier payloads
EndpointFixed HTTPS origin, TLS SPKI and serving key bound in the admission entryOrigin and serving key declared in the signed record; unproven origin claims fail your own conformance
RevocationA signed, restrict-only revocation feed can remove eligibility for a hotkey, operator, serving key, manifest, origin or subprocessor at any time. Revocations never expire; only an explicit, authorized lift removes one

Spec 0.6 defines the permissionless record as reax.miner.v1, signed by both the hotkey and the serving key, containing the endpoint origin, serving key, manifests, declared max_inflight and declared hw_config. Admission is legal and contractual work as well as technical: evidence digests bind records but do not make them true, and legal review is required before any public GDPR wording.

Running the reference miner

The reference miner is a bounded ASGI app (reax_subnet.miner) that forwards validated requests to your own co-located inference engine and signs the result. You need access to the private source and the server extra.

Configuration

Create a public JSON config outside the repository. It holds public metadata and file paths only, never private keys or tokens. Replace every value with your own; the caller public key below is a placeholder, and expires_at_ms must be a future Unix time in milliseconds.

{
  "schema": "reax.miner.config.v2",
  "hotkey": "operator-assigned-hotkey",
  "model_revision": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "engine_url": "http://127.0.0.1:8010",
  "serving_private_key_file": "/run/reax/secrets/serving-private-key",
  "engine_token_file": "/run/reax/secrets/engine-token",
  "replay_database": "/var/lib/reax/replay.sqlite3",
  "max_inflight": 4,
  "callers": {
    "synthetic-evaluator": {
      "public_key": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
      "tiers": ["global_permissionless"],
      "expires_at_ms": 4102444800000,
      "data_class": "synthetic"
    }
  }
}
FieldRule
hotkeyYour miner identity; also the envelope audience
model_revisionExact lowercase 64-character SHA-256 reported by the engine
engine_urlLoopback origin only: 127.0.0.1 or ::1 over HTTP; localhost only over HTTPS; no path; no CLI override
serving_private_key_fileAbsolute path to exactly 32 raw Ed25519 private-key bytes
engine_token_fileAbsolute path to the engine token as UTF-8 text
replay_databaseAbsolute path to a writable SQLite file shared by all workers on the host
max_inflightOptional, 1–64, default 4
callersCaller grants: 32-byte hex public key, tiers, expiry and exactly one data class. Permissionless grants must be synthetic in this prototype
admissionOptional {"database", "verification_keys"}; required when any grant includes gdpr_eu

Both secret files must be regular, non-symlink files with no group or world permissions, readable by the process owner. Mount them from a secret manager or protected host path; keep secret values out of config, shell history, images, logs and source control.

Start

python3 -m reax_subnet.miner --config /etc/reax/miner.json

By default the server binds 127.0.0.1:8011 (--host and --port override), runs one Uvicorn worker, disables access logging and returns generic errors. A rejected configuration prints only miner configuration rejected and exits with 2. Put a TLS-terminating, authenticated proxy in front before allowing any network access.

Container hardening

The prototype image is designed to run read-only as a non-root user with all capabilities dropped, secrets and config mounted read-only, and one writable state mount:

docker run --rm \
  --read-only \
  --user 10001:10001 \
  --cap-drop=ALL \
  --security-opt=no-new-privileges:true \
  --pids-limit=64 \
  --memory=4g \
  --cpus=2 \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --mount type=bind,src=/etc/reax/miner.json,dst=/run/reax/config/miner.json,readonly \
  --mount type=bind,src=/etc/reax/secrets/serving-private-key,dst=/run/reax/secrets/serving-private-key,readonly \
  --mount type=bind,src=/etc/reax/secrets/engine-token,dst=/run/reax/secrets/engine-token,readonly \
  --mount type=bind,src=/var/lib/reax,dst=/var/lib/reax \
  -p 127.0.0.1:8011:8011 \
  reax-miner:local

These limits apply to the miner container, not to your inference engine. The image build has not been run as part of a release, and it does not register with Bittensor or connect to a chain.

Hardware

No hardware requirements are published. Under spec 0.6 each approved manifest lists admitted_hw_configs (GPU class, driver major version, batch sizes) for which the honest measurement noise has been measured. A miner on a configuration outside that list is unsupported: no weight and no penalty until the configuration is calibrated. No configuration has been admitted yet, so do not buy hardware for REAX on the basis of these docs.

Images

The protocol allows up to four PNG, JPEG or WebP images per request, but image serving is disabled at the network miner. An isolated, sandboxed decode-and-normalize worker exists behind a closed deployment gate; it must pass review and a self-test inside the exact serving image before image traffic is enabled. Requests with images are rejected with 400 today.