“Don’t trust, verify” is only a real promise if you can run the verifier. On TensorCash you can: the verifier is open source, the proof a miner produces is self-contained, and standing up the thing that checks it is a documented, reproducible job.
There’s one decision that shapes everything else, so make it first.
The dichotomy: for yourself, or as a service
It’s the same open-source engine either way. What changes is who it answers for.
| For yourself | As a service | |
|---|---|---|
| Who it serves | you — your node, your proofs | many consumers at once |
| Why | trust nobody for “the model ran" | "compute once, serve many” |
| Shape | the engine co-located with your node | the engine behind an HTTP gateway |
| Reach | one box, inward | miners, nodes, explorers, other validators |
For yourself is the sovereign self-check: you re-check every block proof — or a single proof you didn’t create — on your own machine, and trust no third party for the AI-execution claim. As a service turns that same engine outward: behind its HTTP gateway, one verifier you operate answers “did the work run, and which model?” for everyone who points at it.
Pick the half you need; the rest of this post covers both.
What the verifier actually checks
The verifier is a small ladder of checks, cheapest first, that ends in a verdict of GREEN / AMBER / RED:
- quick and quick-smell — fast structural and statistical screens. These run on CPU.
- pow — the proof-of-work over the inference output.
- model — re-runs the claimed model on a GPU and checks that the replayed logits match and that the model’s measured compute is consistent with the claimed difficulty. This is the “which model ran” assertion.
- full — the complete check; logits exposes the raw replay.
So a verdict answers the two questions everything else on the chain rests on: did the work run, and which model produced it. (Model approvals themselves are operator-gated — a model check can land in a pending-review state for a human to approve or reject before it’s trusted.)
Run it for yourself
The sovereign setup co-locates the open-source verifier engine with your node, so
every block your node accepts is re-checked on your own box — no third party in the
loop. The core-validation-api stack is exactly that topology: node + your own
verifier + a local gateway, no miner. It runs the full/model re-run on your own
hardware, so it needs a GPU and the model, plus an OPERATOR_API_KEY (the compose
won’t start without one) and a VERIFY_SHARED_API_KEY that keys the node-to-gateway
calls. Chain and pruning come from a bitcoin.conf you mount at the data dir, and
the core-node image’s mining supervisor needs a compose override to silence — so
bringing this up cleanly is a from-the-repo job, covered in
How to run a node.
If you’d rather just stand up the engine on its own to verify proofs — without
a node attached — run it directly from source; that’s the next section. And if you
want to mine on the same box too, the full-sovereignty stack
core-miner-validation-api adds the worker — the other end of the mining
sovereignty switch in
How to mine.
Check a single proof you didn’t create. The engine exposes the verifier ladder
over HTTP. A proof is a binary FlatBuffer; the /json variants take it as a
base64-encoded proof_b64 field (there are raw application/octet-stream
endpoints too). Submit it, then read the verdict — or look a proof up by id:
# Base64-encode the proof blob and submit it to the full check:
PROOF_B64=$(base64 -i proof.bin)
curl -s http://127.0.0.1:9000/v1/verify/full/json \
-H "Content-Type: application/json" \
-d "{\"proof_b64\": \"$PROOF_B64\"}"
# Poll an async submission, or read a proof's status by id. The public endpoint
# is cache-backed (no durable store in the OSS build), so it answers for proofs
# this instance has recently seen — others come back as "NAN":
curl -s http://127.0.0.1:9000/v1/verify/status/<hash_id>
curl -s http://127.0.0.1:9000/v1/public/status/<hash_id>
A RED verdict is the interesting one: it’s what rules out a faked proof — grinding a result without doing the work, or substituting a different model. You don’t have to take anyone’s word that the network rejects those; you can watch your own verifier do it.
Run it as a service
Pointed outward, the same engine sits behind an HTTP gateway and answers for many consumers. The OSS reference gateway bridges HTTP to the engine:
# Both processes use local imports, so run them from the service's src/ dir.
cd services/verification-api/src
# The engine (ZMQ in, verdict out). Quick checks run CPU-only; model/full need a GPU.
python main.py
# The HTTP gateway in front of it (bridges HTTP → the engine's ZMQ).
uvicorn extapi_stub.app:create_app --factory --host 0.0.0.0 --port 9000
In Docker, the core-validation-api stack wires the engine plus a
verification-http-gateway together. For production there’s a hardened gateway
(gateway/verification-service) that adds caching and request coalescing,
token-bucket rate limiting, API-key + JWT auth, request signatures, and Prometheus
metrics.
What it needs to answer:
- Quick / quick-smell: CPU only — useful as a cheap pre-screen.
- Model / full: a GPU and the model weights loaded (the stack fetches the registered model into a mounted volume). This is the compute that re-runs the forward pass.
- Config worth knowing:
VERIFY_AUTH_ENABLED,VERIFY_API_KEYS, andVERIFY_RATE_LIMIT_PER_MINgate and meter callers; health is on/healthand/v1/verify/health.
The avenues one instance can serve
The reason “as a service” is worth it: a single verifier answers several different consumers at once. From a running instance you can serve —
- Delegating miners. A miner that doesn’t run its own verifier points
VALIDATOR_BASE_URL(+VALIDATOR_API_KEY) at you, and you check its proofs. - Delegating full nodes. A full node pointed at your service over HTTP
(
VALIDATOR_BASE_URL) hands you the full/model check instead of running it locally — it still verifies everything else itself, but trusts you for that one claim. - Other validators (compute once, serve many). The async
/v1/verify/*/requestendpoints cache results by proof id, so a verdict you computed once can be served to everyone who asks for the same proof. - Explorers and public lookups. Anyone — a block explorer, a miner checking
their own share — can read a proof’s verdict with the public, no-auth
GET /v1/public/status/{hash_id}. - Operators. A separate review interface lets an operator approve or reject the model checks that land in pending review.
Run as a service responsibly: it’s a convenience that centralises trust for everyone who delegates to it. That’s exactly why the for-yourself path exists — a delegating miner or node can always stop trusting your service and run its own verifier instead. It’s the same open-source engine, so there’s nothing new to learn; the work is real, though — they have to stand the engine up on their own hardware (GPU + model) and point the node at it, as How to run a node walks through.
The other side of mining
If you read How to mine, this is the piece on the far end of
the sovereignty switch. A delegated miner says “someone else checks my proofs” by
pointing VALIDATOR_BASE_URL somewhere. A verification-as-a-service operator is
that someone. Mining and verification are two ends of one pipeline; running the
verifier is choosing which end you’re on.
Where to go next
- The OSS verifier API — every endpoint: /docs/verifier/api/
- Proof & FlatBuffers schemas — /docs/schemas/
- Run a node to validate against — How to run a node
- Mine on the same proofs — How to mine
- Why faking is expensive — the Verification whitepaper
The verifier doesn’t take our word for it. Run your own — for yourself or for a crowd — and neither will you.
Authored pseudonymously by Imosuke Takakuni.