Skip to main content

Verify a day’s scoring

Last updated

You do not have to trust our scoring.

Every day the validator publishes a receipt: the settled outcomes it used, every miner’s predictions exactly as their container produced them, each score’s components, and the formula that ran. Recompute the scores from it and check they match ours.

Nothing here is privileged. The receipt is public and signed, and the feed is anchored on chain. If our numbers were wrong, this is how you would prove it — and the output names the exact entry that disagrees.

First daily scores settle on 18 August 2026. Before then there is nothing to reproduce yet, and a request for an earlier day says so rather than returning an empty document.

The short version.

python scripts/verify_day.py --url https://validator.adtao.io --day 2026-08-18

"ok": true means the scores reproduce. Anything else prints which check failed and why.

To close the loop all the way to the chain, pass the root you read yourself:

python scripts/verify_day.py --url https://validator.adtao.io \
    --day 2026-08-18 --expect-anchor <root you read from chain>

What gets checked, and what each one proves.

Each returns its own verdict. That distinction matters: a signature failure and a score mismatch mean very different things, and a single pass-or-fail would hide which one you are looking at.

Check What it proves
attestation The document is intact and signed by the validator’s key — the bytes you received are the bytes it published.
chain This day links to the previous day’s receipt. The feed has no gaps and no rewrites.
anchor_linkage The day’s anchored summary names this exact receipt.
feed_root This day sits inside the Merkle root the validator commits on chain.
score_reproduction Every score recomputes from the published outcomes and the published predictions.

What the on-chain anchor proves.

The anchor is a Merkle root over every day published so far, not a hash of a single day. The chain stores one commitment per hotkey and each new one overwrites the last, so a per-day hash would mean yesterday’s anchor was gone today and old receipts became unverifiable without an archive node. A rolling root keeps the newest commitment covering your day however old it is, and the inclusion proof is a few dozen bytes.

Read the validator’s commitment from chain yourself and compare it to the root the server serves. If they differ, that server is serving a different history than it anchored, and every proof under it is worthless. It is one call, and it is the single most important thing you can check.

When a check fails.

A failed score reproduction prints the episode, horizon, miner, published score and recomputed score. That is a small, complete, checkable claim — post it in the miner channel. We would rather find out from you than not at all.

A served root that differs from the chain is the serious one. Report it immediately.

The full walkthrough.

Doing it by hand, what each failure means, and what is deliberately not covered: SN21_VERIFYING.md in the public repository. This page mirrors it; where the two disagree, the repository is right.