Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
3ba4fba
refactor(trust): drop the signed trust-root ceremony; the gateway ser…
echobt Oct 19, 2026
034a889
feat(validator): only the weight-setting role needs a validator hotkey
echobt Oct 19, 2026
1e46373
feat(cli): keep keygen for challenge leaf keys
echobt Oct 19, 2026
e2f6cd7
refactor(profile): rename trust root to challenge profile in code, ch…
echobt Oct 19, 2026
cccfa5a
docs: describe the gateway-served challenge profile; drop the trust-r…
echobt Oct 19, 2026
27d6b33
test(gateway): validator without local trust uses the gateway-served …
echobt Oct 19, 2026
4c24c76
docs,deploy: drop gateway/leaf keys, keygen and signature docs for wi…
echobt Oct 19, 2026
b463ce4
Remove signatures from leaves, bundle and gateway; wire format v2
echobt Oct 19, 2026
6606ebb
Remove cortex keygen command
echobt Oct 19, 2026
33d2cf8
Refuse a v1 gateway store that only holds trust profiles
echobt Oct 19, 2026
c699f87
Dissent unsupported version for a v1 bundle before decoding it
echobt Oct 19, 2026
3951660
docs: remove stale gateway/leaf-key mentions, document operator-beare…
echobt Oct 19, 2026
b6de502
Test the strict leaf epoch check of verify_inputs
echobt Oct 19, 2026
0d534b9
Refresh wire-format docstrings for v2
echobt Oct 19, 2026
6af357f
Persist trust-version watermarks only after verification
echobt Oct 19, 2026
97fd3a9
Test the validator-reconcile CLI end to end
echobt Oct 19, 2026
fe4ecc6
Reject a non-integer profile epoch/version with a clear error
echobt Oct 19, 2026
f03b843
docs: never set introduced_epoch in the future; third challenge needs…
echobt Oct 19, 2026
d846671
feat(gateway): require a separate bearer for raw leaf intake
echobt Oct 19, 2026
6263a2a
feat(validator): add an operator-only watermark reset command
echobt Oct 19, 2026
0f594d3
docs: describe raw intake under the separate intake bearer
echobt Oct 19, 2026
927eb55
fix(cli): report a sqlite failure in watermark reset without traceback
echobt Oct 19, 2026
6dc89eb
fix(validator): fail fast on an unreadable hotkey or half a wallet
echobt Oct 19, 2026
f8f10a9
fix(validator): say the chain preflight is skipped without a hotkey
echobt Oct 19, 2026
6c6b843
docs(deploy): add the validator to weight-setter upgrade note
echobt Oct 19, 2026
2d8f3cb
docs(deploy): keep consensus.key out of the verify-only identity dir
echobt Oct 19, 2026
d9b2885
docs: drop the last signed-profile and leaf-signing claims
echobt Oct 19, 2026
3151f6e
test(config): pin the 503 for a placeholder challenge profile
echobt Oct 19, 2026
05bd7c2
fix(protocol): cap measurements_version before the watermark moves
echobt Oct 19, 2026
7a8ce56
fix(gateway): refuse raw intake while an epoch is being sealed
echobt Oct 19, 2026
5e1a0e3
fix(http): re-check bearer distinctness and length on every request
echobt Oct 19, 2026
9e504c4
fix(cli): open the watermark-reset target read-only before writing
echobt Oct 19, 2026
a08d5f6
fix(config): validate challenge profile field types before decoding
echobt Oct 19, 2026
748eaae
fix(deploy): give the weight-setter its own identity directory variable
echobt Oct 19, 2026
d909255
docs(changelog): describe algorithm 2 activation in the past tense
echobt Oct 19, 2026
922112a
fix(gateway): scope the sealing refusal to the epoch being sealed
echobt Oct 19, 2026
1a7754f
fix(cli): keep watermark-reset preflight free of sidecars and schema
echobt Oct 19, 2026
5fb36cd
fix(deploy): check the operator env file and real volume names
echobt Oct 19, 2026
b3ec7db
fix(protocol): cap challenges_version like measurements_version
echobt Oct 19, 2026
3eda466
docs(changelog): explain the version cap upgrade consequence
echobt Oct 19, 2026
dfad4d3
test(master): pin the intake refusal across the whole emit window
echobt Oct 19, 2026
1826891
fix(config): map a deeply nested challenge profile to the clean 503
echobt Oct 19, 2026
60f7ac7
fix(cli): give watermark-reset fixed reasons for unusable state files
echobt Oct 19, 2026
1161319
fix(cli): read the watermark-reset preflight without sidecars
echobt Oct 19, 2026
4145240
fix(deploy): read validator env values as compose does and refuse nes…
echobt Oct 19, 2026
3196cc3
docs(security): state the 32-byte bearer minimum and per-request check
echobt Oct 19, 2026
5a330f7
test(cli): cover watermark-reset --netuid on a journal without netuid
echobt Oct 19, 2026
94a680a
test(master): pin the 32-byte bearer boundary on a rotated intake file
echobt Oct 19, 2026
3d4e315
docs(config): describe profile reload and cautious restart in comments
echobt Oct 19, 2026
b05daf0
docs(deploy): describe profile activation as cautious, not required
echobt Oct 19, 2026
cb8179d
docs(validator): state the reset lock guard limits and drop gateway key
echobt Oct 19, 2026
9eec8ea
docs(changelog): describe the master restart on share change as caution
echobt Oct 19, 2026
aed7efe
docs(review): describe wire v2 rules in coderabbit and AGENTS
echobt Oct 19, 2026
1c4c1f4
fix(deploy): refuse nested validator identity directories
echobt Oct 19, 2026
71b0cca
test(validator): skip read-only watermark reset cases as root
echobt Oct 19, 2026
b50cb7a
docs(validator): cover both profile version caps and restart wording
echobt Oct 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,32 @@ reviews:
- path: "**"
instructions: |
Cortex review rules.
Cortex is a Python Bittensor research subnet. The owner-signed trust root lists
Cortex is a Python Bittensor research subnet. The challenge profile (`config/challenges.toml`, served by the gateway at `GET /v1/trust`) lists
the live challenges: legacy bounty/proof 2,000/8,000 (algorithm 1), 3,000/7,000
(algorithm 2, version >=2) or 1..64 unique ids (algorithm 3, version >=3). The
sum is always 10,000. Proof is built in; every other challenge is a Docker
container per docs/CHALLENGES.md. Design, Prism and Relearn are retired and removed.

- Preserve frozen SCALE encodings, Merkle construction, aggregation and every
`base-*-v1` signature preimage. Cross-language vectors must remain green.
- Wire format v2 (no signatures on leaves, bundle or gateway) was decided by
the founder on 2026-10-19. docs/BUNDLE_SPEC.md was changed on purpose by the
PR that introduced v2 and is byte-pinned again at its v2 content
(`FROZEN_SPECS` in `scripts/check_repo.py` holds the hash). The
`base-trustroot-v1`, `base-rawweight-v1` and `base-bundle-v1` preimages are
retired; `tests/protocol/vectors/rust_wire.json` keeps only what still exists
and `tests/protocol/vectors/wire_v2.json` is generated by
`scripts/gen_wire_vector.py`.
- Preserve the v2 SCALE encodings, Merkle construction, aggregation and every
remaining `base-*-v1` signature preimage. Cross-language vectors must remain
green. Any new wire change needs explicit maintainer approval and a
second-implementation or independently pinned vector when one exists.
Algorithm 2 counts each valid Bounty report once, distributes proportionally,
scales its 30% share by min(total_valid/10, 1), and burns unused/quarantined
mass. The total includes only the signed expected participant population.
mass. The total includes only the expected participant set validators derive
from the unsigned challenge-profile policy (docs/BUNDLE_SPEC.md section 7).
Algorithm 3 pays each challenge share * min(sum(leaves), 10^12) / 10^12 and
burns the rest; unpaid mass never moves to another challenge.
Never allow an algorithm 1 body under the new profile or activate before
the owner-signed epoch; historical seals and journals stay immutable.
the profile's activation epoch; historical seals and journals stay immutable.
- Preserve existing `BASE_*` names and deployed compatibility paths. New master
settings may add the matching `CORTEX_*` alias but conflicting values fail.
- Missing or unknown image digests, offers, baselines, topics, keys, feeds and
Expand All @@ -43,7 +54,7 @@ reviews:
- Shared observations are untrusted and private until owner-signed approval.
- A trusted challenge container that is unregistered, failing or returns invalid
weights yields explicit `ChallengeInternal` leaves; never a stale or guessed
score. Containers never receive a leaf seed; only `challenge-supervisor`
score. Containers never receive a signing key; only `challenge-supervisor`
mounts the Docker socket; the proxy never forwards `internal/` paths.
- Validators independently fetch historical chain state, recompute exact u16
weights and refuse the unsealed UID0 fallback. A sealed UID0 burn is valid.
Expand All @@ -52,5 +63,5 @@ reviews:
- CI remains offline: no OpenRouter call, Lium rent, Firecracker boot or chain
submission. Fake-boundary tests cannot be described as live evidence.
- API changes update the matching `docs/external-miner/` guide.
- Do not edit the byte-pinned frozen specification (docs/BUNDLE_SPEC.md). Do not weaken
- Do not edit the byte-pinned v2 specification (docs/BUNDLE_SPEC.md). Do not weaken
`scripts/check_repo.py` to accept protocol drift.
6 changes: 2 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ BASE_NETUID=1
BASE_CHAIN_ENDPOINT=finney
BASE_CHAIN_FALLBACK_ENDPOINTS=[]
BASE_STATE_DIR=.local/state
BASE_OWNER_PUBKEY_FILE=config/owner.pubkey
BASE_CHALLENGES_FILE=config/challenges.toml
BASE_MEASUREMENTS_FILE=config/measurements.toml
BASE_GATEWAY_SK_FILE=.local/secrets/gateway.seed
BASE_GATEWAY_ADMIN_TOKEN_FILE=.local/secrets/operator.token
# Separate bearer for POST /v1/weights/raw; must differ from the admin bearer.
BASE_GATEWAY_INTAKE_TOKEN_FILE=.local/secrets/intake.token
PROOF_SK_FILE=.local/secrets/proof.seed
# Leaf seeds of container challenges: <dir>/<id>.key for every trusted id but proof.
BASE_CHALLENGE_KEYS_DIR=.local/secrets
# Optional operator registry; see docs/CHALLENGES.md. Unset runs no container challenge.
# BASE_CHALLENGE_REGISTRY_FILE=deploy/challenges/registry.toml
BASE_CHALLENGE_SECRETS_DIR=.local/challenge-secrets
Expand Down
48 changes: 28 additions & 20 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ canonical documentation instead of duplicating runbooks.
Cortex is an autonomous research subnet on Bittensor. Proof runs inside the
master. Every other challenge is a Docker container that implements
[the challenge contract](docs/CHALLENGES.md); the master loads it from an
operator registry and signs its leaves.
operator registry and records its leaves.

| Challenge | Source | Purpose |
| --- | --- | --- |
| `proof` | this repository | operator-created research topics evaluated by Cortex's recursive language-model engine |
| `bounty` | [CortexLM/bounty](https://github.com/CortexLM/bounty) container | useful vulnerability reports, scored from the CortexLM/backend public feed |
| `opentype` | [OpentypeAI/challenge](https://github.com/OpentypeAI/challenge) container | exact-gold typed-decision duels on DiffusionGemma weights |

Shares always sum to 10,000 basis points. Algorithm 1 is the legacy signed
Shares always sum to 10,000 basis points. Algorithm 1 is the legacy
bounty/proof 2,000/8,000 profile; algorithm 2 is bounty/proof 3,000/7,000
(document version >=2); algorithm 3 (document version >=3) admits any 1..64
unique ids and pays each challenge `share * min(sum(leaves), 10^12) / 10^12`.
Activation is an offline owner ceremony. Design, Prism and Relearn are retired
Activation is a profile version bump on the master (`config/challenges.toml`). Design, Prism and Relearn are retired
products and their documentation has been removed. No active code, service,
trust-root row or leaf may register them.
challenge profile row or leaf may register them.

Start with [the architecture](docs/ARCHITECTURE.md),
[Proof](docs/PROOF.md), [challenge containers](docs/CHALLENGES.md) and
Expand All @@ -34,7 +34,7 @@ reproduction or on-chain payment.

| Path | Responsibility |
| --- | --- |
| `src/cortex/protocol/` | frozen SCALE, signatures, Merkle and aggregation |
| `src/cortex/protocol/` | frozen v2 SCALE (unsigned wire), Merkle and aggregation |
| `src/cortex/gateway/` | durable leaves, immutable seals and burn fallback |
| `src/cortex/validator/` | independent recomputation, root consensus and chain dispatch |
| `src/cortex/challenges/` | container registry, weights client, public proxy and auto-updating supervisor |
Expand All @@ -48,10 +48,18 @@ The working branch is `main`. Production releases are annotated `v*.*.*` tags.

## Consensus and compatibility

- Preserve `BASE_*` names, deployed compatibility paths and every `base-*-v1`
signature domain. `CORTEX_*` is an accepted master alias only.
- Do not edit `docs/BUNDLE_SPEC.md`. Its exact SHA-256 value is checked by
`scripts/check_repo.py`.
- Wire format v2 (no signatures on leaves, bundle or gateway) was decided by the
founder on 2026-10-19. `docs/BUNDLE_SPEC.md` was changed on purpose by the PR
that introduced v2; the `base-trustroot-v1`, `base-rawweight-v1` and
`base-bundle-v1` preimages are retired. `tests/protocol/vectors/rust_wire.json`
keeps only what still exists; `tests/protocol/vectors/wire_v2.json` is generated
by `scripts/gen_wire_vector.py`.
- Preserve `BASE_*` names, deployed compatibility paths and every remaining
`base-*-v1` signature domain. `CORTEX_*` is an accepted master alias only.
- Do not edit the v2 `docs/BUNDLE_SPEC.md`. Its exact SHA-256 value is pinned in
`FROZEN_SPECS` in `scripts/check_repo.py`; do not weaken that check. Any new
wire change needs explicit maintainer approval and a second-implementation or
independently pinned vector when one exists.
- Production image references are digest-only. Never invent a digest; an empty
or unknown pin remains fail-closed.
- Secrets are private files. Do not put seeds, mnemonics, bearer values, BYOK,
Expand All @@ -69,24 +77,24 @@ or permit UID is not a submit path.

| Key or token | Role |
| --- | --- |
| owner seed | signs challenge and measurement trust documents offline |
| gateway seed | signs immutable epoch bundles |
| challenge seed | `<id>.key`; signs that container challenge's leaves and must match the trust root |
| Proof seed | signs Proof topics and leaves and must match the trust root |
| operator bearer | protects master administrative routes |
| Proof seed | signs Proof topics (`PROOF_SK_FILE`); no bundle, leaf or gateway key exists |
| operator bearer | protects master administrative routes, including sealing (`/v1/admin/seal`) |
| intake bearer | protects raw leaf intake (`/v1/weights/raw`) only; must differ from the operator bearer |
| VM orchestrator bearer | authenticates master to the dedicated KVM host; not a wallet |
| validator hotkey | signs root/dissent evidence and Bittensor submissions |
| validator hotkey | weight-setting role only: signs root/dissent evidence and Bittensor submissions |
| challenge internal token | master bearer for a container's `get_weights`; never a signing key |
| miner hotkey | signs Bounty pairing or Proof submission payloads |

Do not conflate gateway sealing, master ownership and validator chain signing.
Follow [the trust-root ceremony](docs/how-to/trust-root.md).
Operator and intake bearers are at least 32 bytes and re-checked on every request.

Do not conflate gateway sealing (unsigned), master ownership and validator chain signing.
Validators build their view from the gateway profile at `GET /v1/trust`; the gateway is the single source of truth.

## Challenge container contracts

- The owner-signed trust root decides emission; the unsigned registry
- The challenge profile decides emission; the unsigned registry
(`deploy/challenges/registry.toml`) only decides what runs. A container never
receives a leaf-signing seed.
receives a signing key.
- `challenge-supervisor` is the only process with the Docker socket. It verifies
image labels and GitHub build provenance, canaries without secrets, rolls back
on failure and never reads a secret.
Expand Down Expand Up @@ -180,7 +188,7 @@ uv build --no-build-isolation
```

Challenge verification must exercise a real intake request, failure probes,
signed leaves, gateway seal, a `sealed: true` fetch and validator recomputation.
leaves, gateway seal, a `sealed: true` fetch and validator recomputation.
Health endpoints alone do not verify a challenge. CI must not contact OpenRouter,
rent provider compute, boot Firecracker or submit an on-chain transaction.

Expand Down
Loading
Loading