Skip to content

feat(challenge): serve a joined miner its own admission-trial job (S2) - #33

Merged
Mathis (echobt) merged 2 commits into
mainfrom
feat/trial-job-route-v2
Oct 25, 2026
Merged

Mathis (echobt) merged 2 commits into
mainfrom
feat/trial-job-route-v2

Conversation

@echobt

@echobt Mathis (echobt) commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Why

probe-v2 needed a way to fetch its own admission trial without the admin token.

What

  • challenge: GET job route (app.py +26) that serves a joined miner only its own admission trial; requires subnet_member, X-Hotkey == admitted hotkey and a valid signature of hypertrain/trial-job/2|{run_id}|{admission_id} before any side effect. Admin token never replaces the signature. Existing error codes kept (404/409/403).
  • miner: probe-v2 fetches its trial when --job is omitted (path-safe, hash-verified, identity-encoding only, private 0700 dir).
  • docs +17, tests (3 files).

Evidence

  • Independent review (Lens): mergeable, 0 B / 0 I / 3 M; 8 mutants, 7 killed, 1 equivalent; 46 tests passed on a clean archive. livrables/lens/2026-10-25_hypertrain-s2-trial-job-route.md.
  • Full suite and smoke: left to CI (smoke exceeds 120 s on base already).

Risk / rollback

Repeated export_trial_v2 cost per call (option A, separate ticket). Static signature without nonce (M-S2-1), harmless while payload is derivable from public data. Rollback: revert the two commits.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • probe-v2 can now retrieve and probe an open trial without manually providing job and challenge files.
    • Trial access is verified against the miner’s registered identity, and downloaded trial data is validated before use.
    • Trial inputs are stored in a private temporary location and cleaned up after probing.
  • Documentation

    • Added guidance for running probe-v2 with automatically retrieved trial data.

Mathis (echobt) and others added 2 commits October 25, 2026 13:14
A public miner could not start a trial in one command: the trial job
(IslandJobV1, its input objects, the challenge body) was only reachable
through the admin export route, so an operator had to hand the miner a
--job folder.

GET /v2/runs/{run_id}/join/{admission_id}/job returns the admin export
payload (ChallengeStore.export_trial_v2, reused as is) to the currently
registered hotkey that owns the admission, never publicly. Unlike the
challenge route, the caller is authenticated: admission ids are public
through the admission status route, so gating only on the admission's
hotkey being registered would let any caller read any miner's trial.
The caller sends X-Hotkey and X-Trial-Signature, a hotkey signature of
"hypertrain/trial-job/2|{run_id}|{admission_id}" (founder decision,
option A, 2026-10-25).

Refusals reuse existing codes, in this order: unknown run 404, unknown
admission 409 UNKNOWN_ADMISSION and a deregistered or revoked owner 403,
all as the challenge route answers; then another hotkey or a missing or
bad signature 403 "hotkey is not current accepted identity" (the
message of _owner_v2); then the export's own 409/503 refusals. The admin
bearer token is not accepted in place of the signature.

Rejected: copying the challenge route gate alone (cross-miner reads),
and one identical 403 for every caller failure (misleading message for
a registered miner using the wrong admission id).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the owner-signed trial job route, probe-v2 no longer needs an
operator-made folder. Without --job and --challenge it reads its
admission id from the admission status, GETs the challenge (which
issues the trial when none is open, otherwise returns the open one),
GETs the signed job route, and checks the job, objects and signed
challenge with the same models and bindings as trial_export.py. Each
input is streamed into a private temporary folder under the miner's
workdir and verified by sha256, then the probe runs as with --job and
the folder is deleted, also on failure (a re-run starts over).

The inputs are whole plain objects (the export puts each file as one
object), so the 1 MiB part bound of _get_object cannot be used. Like
trial_export they are streamed to disk, with no compression added;
unlike it, the miner talks to any configured api, so it keeps the
_get_object defences: Accept-Encoding identity, refusal of an encoded
body, and a bound of MAX_PARTS * PART_BYTES per object (the largest
object the round-input path accepts). Measured on the CPU test fixture
(824 params): job JSON 5289 bytes, start_state 4256, ef_in 4256, v0 16,
samples 20, sample_proofs 271; start_state grows ~4 bytes/param under
reset.

Rejected: comparing job.manifest with the signed manifest, which
IslandJobV1 already forces through manifest.validate_run_id(run_id).

--job and --challenge still work as before and must be given together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 37bae729-4a18-4caf-bdfa-10af8145c1a1
Commits

Reviewing files that changed from the base of the PR and between add3950 and 39e2265.

Files selected for processing: 7
  • docs/network-v2.md
  • src/hypertrain/challenge/app.py
  • src/hypertrain/miner/cli.py
  • src/hypertrain/miner/core.py
  • tests/challenge/test_subnet_gate_v2.py
  • tests/challenge/test_trial_export.py
  • tests/miner/test_probe_trial_v2.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

probe-v2 can now fetch an admission’s trial without local job and challenge files. The challenge service serves the job to the currently registered admission owner after signature checks. The miner validates the trial data, downloads its inputs to a temporary directory, and probes.

Changes: Self-service trial probing

Layer / File(s) Summary
Authenticated trial-job access
src/hypertrain/challenge/app.py, tests/challenge/test_trial_export.py, tests/challenge/test_subnet_gate_v2.py
The job route checks subnet registration and verifies the hotkey signature over the run and admission IDs before exporting the trial. Tests cover owner access, mismatched identity, unknown IDs, and registration changes.
Trial fetching and validation
src/hypertrain/miner/core.py, tests/miner/test_probe_trial_v2.py
NetworkMiner.probe_trial() fetches the challenge, job, and input objects. It validates trial bindings, signatures, paths, encoding, size, and digests before probing. Tests cover successful proof submission and invalid or mismatched trial data.
probe-v2 trial selection
src/hypertrain/miner/cli.py, docs/network-v2.md, tests/miner/test_probe_trial_v2.py
probe-v2 accepts both --job and --challenge, or neither. When neither is supplied, it fetches the miner’s trial. The documentation describes this flow, and tests check that supplying only one option is rejected.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant MinerCLI
  participant NetworkMiner
  participant ChallengeRoute
  MinerCLI->>NetworkMiner: Call probe_trial
  NetworkMiner->>ChallengeRoute: Request challenge and signed job
  ChallengeRoute-->>NetworkMiner: Return challenge and job
  NetworkMiner->>ChallengeRoute: Download trial objects
  ChallengeRoute-->>NetworkMiner: Return trial objects
  NetworkMiner-->>MinerCLI: Probe using fetched job and challenge
Loading
Merge Risk: Low · up to 39e22

A captured trial-job signature may be reusable. This known, bounded access risk merits owner acceptance, but the supplied evidence does not establish a merge-blocking failure.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 23.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 30 functions across 6 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: serving a joined miner its own admission-trial job through the challenge flow.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 23.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 30 functions across 6 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@echobt
Mathis (echobt) merged commit 0313989 into main Oct 25, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant