Skip to content

feat(proof): lock emission 2000/8000 and add WTA/discovery payouts - #220

Merged
Mathis (echobt) merged 1 commit into
mainfrom
cursor/proof-emission-2000-8000-payout-modes
Sep 4, 2026
Merged

Mathis (echobt) merged 1 commit into
mainfrom
cursor/proof-emission-2000-8000-payout-modes

Conversation

@echobt

Copy link
Copy Markdown
Contributor

Summary

Locks live emission at bounty 2000 / proof 8000 (20%/80%, sum 10000) and makes Proof topics carry two payout modes plus English validation so Mathis can inject research challenges from the operator path.

This is the control-plane half of the Mathis lock. Proof still 503s until a real eval_image_digest is pinned. Do not invent a digest — that pin is owned by Développeur (bc-898689d3). This PR leaves the digest empty.

Emission

  • config/challenges.toml + staging twin: two rows, same pubkeys, bounty 2000 / proof 8000.
  • Throwaway owner ceremony re-signed challenges.toml, challenges.staging.toml, and measurements.toml (secret stayed in /tmp, never git).
  • Current lock is 2000/8000 regardless of digest. Removed 7000/3000 and “5000/5000 until digest” language from AGENTS, PROOF, miner docs, site arenas, trust-root tests, and ctx catalog.

Topic schema (crates/proof-task)

Signed with the rest of the document:

  • payout_mode: wta | discovery (default discovery)
  • validation.{score_on, accept_if, reject_if} — English criteria the RLM + harness enforce
  • discovery.{pass_floor_share_bps, novelty_pool_share_bps} — default 3000/7000, must sum to 10000; ignored for wta

metric.family nll | throughput | custom unchanged. v0 supported_custom() lists harness_success_rate so the agent-harness topic publishes; scoring fail-closes until a real harness fills custom_value. dt-no-ib-v0 remains the throughput wta example.

Scoring (crates/proof-score)

Pass gates unchanged (fail-closed). After pass:

  • wta: best primary among pass=true this epoch takes 100% of that topic’s mass. Exact ties split equally. Non-winners get 0 on that topic.
  • discovery: topic pool = 8000 / n_open. Floor share split equally among verified passes; remainder weighted by improvement vs sealed baseline (and champion if any). Near-duplicate of an accepted artifact: floor only, 0 novelty.
  • Global miner proof score = sum of per-topic masses (not a mean of binary lattices). Empty open set → NoScore(ChallengeInternal).

Operator inject path

  • POST /v1/admin/proof/topics accepts the full signed document (English statement + validation + payout_mode + metric).
  • GET /v1/proof/topics lists published topics.
  • xtask proof-topic accepts YAML/JSON drafts, fills holdout commitment (--synthetic or --holdout), and signs.

Miner docs + ctx proof submit now send claim and declared_flops. Artifact is a reproducible train/eval recipe under budget, not weights-only. Verdict is the agent envelope after eval.

Fail-closed (unchanged)

Empty eval_image_digest → 503. No FORCE_SIM on droplets. No invented sha256. No Modal. No secrets in git. proxy_model may stay empty until the image exists.

Stacking

If Développeur’s digest/harvest PR also touches challenges.toml or proof-task topic schema, rebase that PR onto this one. This PR does not publish a proof-eval image.

Greptile

Every PR is reviewed by Greptile before merge. Config: .greptile/.

  • Greptile has reviewed this PR; findings are fixed or answered
  • If the bot was silent, I commented @greptileai review

Test plan

  • cargo fmt --all
  • cargo clippy -p proof-task -p proof-score -p proof-store -p proof-eval -p proof-http -p proof-challenge -p proof-harvest -p ctx -p xtask -p site-api -p site-data -p site-types --all-targets -- -D warnings
  • cargo test -p proof-task -p proof-score -p proof-store -p proof-eval -p proof-http -p proof-challenge -p proof-harvest -p ctx -p xtask -p trustroot -p site-api -p site-data -p site-types
  • cargo run -p xtask -- loc-cap
  • cargo run -p xtask -- external-docs-check
  • cargo test --workspace (not run here; focused proof/site/trustroot/xtask/ctx subset above)

Tests cover WTA winner-only, equal-tie WTA, discovery floor+novelty (duplicates get floor only), empty open → NoScore, harness_success_rate publish + fail-closed score, YAML topic draft parse, and trust-root 2000/8000 verify.

Risk

Emission impact: Proof now holds 80% of the subnet. Until a digest is pinned, that 8000 bps still cannot score (503 / NoScore) and burns rather than paying. Challenge pubkeys were not rotated — only the throwaway owner key and emission bps. No BASE_* renames, no domain-tag changes, no digest invention.

Naming

I did not rename BASE_* environment variables, deployed host paths (/opt/base, /run/base, …), GHCR baseintelligence/base package names, or base-*-v1 cryptographic domain tags.

Open in Web Open in Cursor 

Lock the live trust root at bounty 2000 / proof 8000 (20%/80%) regardless
of eval digest. Proof still 503s until a digest is pinned; do not invent
one. Re-sign challenges.toml + staging twin + measurements with a throwaway
owner ceremony.

Topics now carry signed payout_mode (wta|discovery), English validation
(score_on/accept_if/reject_if), and discovery floor/novelty shares. Epoch
scoring sums per-topic masses: WTA winner-only (exact ties split),
discovery pass-floor + novelty vs sealed baseline/champion. Empty open set
is NoScore(ChallengeInternal).

Operator POST /v1/admin/proof/topics accepts the full signed document.
xtask proof-topic accepts YAML/JSON drafts and fills the holdout
commitment. ctx proof submit sends claim + declared_flops. listed custom
id harness_success_rate publishes and fail-closes until a real harness
exists.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@greptile-apps

greptile-apps Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Greptile Summary

This change adds Proof payout calculations and topic-run tracking, but three payout-critical paths are incomplete or incorrect: the running service never emits signed Proof leaves, duplicate novelty ownership is chosen by hotkey order rather than claimant provenance, and later topic submissions can erase earlier qualifying results. These failures must be fixed before merging.

Confidence Score: 2/5

Unsafe to merge: accepted Proof work may never be emitted, and payout ownership or eligibility can be lost or assigned incorrectly.

Three independently reproduced payout failures affect the production emission path, duplicate attribution, and persisted submission selection.

Files Needing Attention: crates/proof-challenge/src/lib.rs, crates/proof-score/src/payout.rs, and crates/proof-store/src/lib.rs

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced proofs for multiple posted P1 findings and attached supporting artifacts for review.
  • The runtime validation confirmed the cargo build succeeded and the booted binary served /health and /v1/status with epoch 0.
  • T-Rex demonstrated that provenance order does not decide the duplicate's novelty recipient and summarized the payout facts across pools.
  • The overwrite behavior in the result store was shown, where a later result replaced an earlier one and there is no epoch scope in the store key.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (4)

  1. crates/proof-challenge/src/lib.rs, line 79-102 (link)

    P1 Proof emission is unwired

    The new emit_epoch and store_runs helpers are not called by the production Proof service. The running binary only serves HTTP with a fixed epoch value, so accepted submissions never become signed Proof leaves or receive the configured Proof allocation. Wire an epoch lifecycle to collect runs, calculate scores, emit the leaf set, and publish it before enabling live evaluation.

    Knowledge Base Used: Challenge network and submission lifecycle

    Artifacts

    Evidence from the check

    • The exact authored shell script compared base and HEAD call sites, built the binary, and booted the proof service; it provides the reproducible check.

    Command output from the check

    • The executed base-revision call-site capture shows no production proof-service emission or store-run consumer; the baseline already lacked lifecycle wiring.

    Command output from the check

    • The executed HEAD capture shows the only direct emitter calls are test-local, no store-runs caller exists, and the built production service boots with epoch zero; the claimed production wiring is absent.

    View artifacts

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 Proof payout emission is not wired into the production service lifecycle

    • Bug
      • The changed payout APIs cannot produce production proof emission. emit_epoch and store_runs are defined but never referenced by bins/proof-challenge/src/main.rs or any non-test consumer. The service initializes AppState with a permanent epoch: 0 and only serves HTTP routes.
    • Cause
      • The change added pure orchestration helpers and unit tests in crates/proof-challenge/src/lib.rs, but no epoch coordinator, chain epoch source, scheduled task, route, or service integration calls those helpers.
    • Fix
      • Wire an epoch lifecycle owner into the production service or validator flow: obtain the real epoch and expected hotkeys, collect store_runs(&state.store), load topics/baselines/champion values, call emit_epoch, and persist/publish the resulting signed leaf set. Add an integration test that advances an epoch through that production entry point.

    T-Rex Ran code and verified through T-Rex

  3. General comment

    P1 Digest-duplicate novelty ownership is assigned by lexicographic hotkey order

    • Bug
      • For passed Discovery submissions sharing an identical case-normalized artifact digest, the lexicographically first miner hotkey retains novelty eligibility while every later hotkey is marked near_duplicate and receives only the pass floor. Reversing the supplied submission/provenance order from zulu-first to alpha-first did not alter the result: alpha received 850000 and zulu received 150000 in both executions.
    • Cause
      • score_one_topic gathers passers and calls mark_digest_duplicates; that function explicitly sorts passers by hotkey at crates/proof-score/src/payout.rs:191. It records the first sorted miner for each digest at lines 198-203 and marks subsequent matching-digest miners as duplicates at line 200. discovery then assigns duplicate runs zero novelty weight at lines 250-260.
    • Fix
      • Preserve and use an explicit, validated submission/provenance ordering field when selecting the first accepted digest claimant, rather than sorting by miner hotkey. Define deterministic tie handling for equal provenance values and test that reversing hotkeys without changing provenance does not change the novelty recipient.

    T-Rex Ran code and verified through T-Rex

  4. General comment

    P1 Later topic runs overwrite earlier passing or better results

    • Bug
      • record_topic_run writes a MinerTopicRun into a nested map keyed only by hotkey and topic ID. A later failed run for the same pair replaces an earlier passing/better run, so payout input can be downgraded by a subsequent submission.
    • Cause
      • The changed storage type is BTreeMap<String, BTreeMap<String, MinerTopicRun>>, and the changed implementation calls insert(topic_id.to_owned(), run) without retaining, comparing, or selecting the best prior run. The key and method signature contain no epoch.
    • Fix
      • Scope stored runs by epoch and retain the best eligible run for each (epoch, hotkey, topic_id) according to the topic payout rules; alternatively reject subsequent attempts after a qualifying run. Do not replace a passing/better stored run with a later inferior result.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "feat(proof): lock emission 2000/8000 and..." | Re-trigger Greptile

Comment on lines +190 to +205
fn mark_digest_duplicates(passers: &mut [(String, MinerTopicRun)]) {
passers.sort_by(|a, b| a.0.cmp(&b.0));
let mut seen: BTreeMap<String, String> = BTreeMap::new();
for (miner, run) in passers.iter_mut() {
let digest = run.artifact_digest.trim().to_ascii_lowercase();
if digest.is_empty() {
continue;
}
if let Some(first) = seen.get(&digest) {
if first != miner {
run.near_duplicate = true;
}
} else {
seen.insert(digest, miner.clone());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Duplicate rewards use hotkeys

For passing Discovery submissions with the same artifact digest, this code sorts miners by hotkey and treats the first one as the novelty owner. That is unrelated to when the artifact was submitted or otherwise proven to belong to a miner, so a later copier with a lexicographically earlier hotkey can receive the novelty reward while the original claimant receives only the pass floor. Select the owner using validated submission provenance instead of hotkey order.

Artifacts

Evidence from the check

  • Authored executable source invokes the changed public payout API with identical-digest passers in reversed provenance orders, showing that hotkey ordering determines novelty ownership.

Evidence from the check

  • Authored shell command source creates the temporary Cargo manifest and runs the exact focused executable against the repository crates.

Command output from the check

  • Executed output for the zulu-first provenance case exited 0 and shows alpha still received 850000 while zulu received 150000, proving provenance order did not control novelty.

Command output from the check

  • Executed output for the alpha-first provenance case exited 0 and shows the same alpha=850000 and zulu=150000 payout, confirming the comparison result.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +283 to 294
pub fn record_topic_run(
&self,
hotkey: &str,
topic_id: &str,
run: MinerTopicRun,
) -> Result<(), StoreError> {
self.lock()?
.scores
.entry(hotkey.to_owned())
.or_default()
.insert(topic_id.to_owned(), lattice);
.insert(topic_id.to_owned(), run);
Ok(())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Later runs erase results

record_topic_run stores one value for each hotkey and topic, unconditionally replacing the previous value. A miner can submit a later failed or worse run that replaces an earlier passing result before payout calculation, causing an earned payout to disappear. The storage key and method also contain no epoch, so attempts are not isolated to the epoch being paid. Retain the best eligible run per epoch, hotkey, and topic, or reject inferior follow-up submissions.

Knowledge Base Used: Challenge network and submission lifecycle

Artifacts

Evidence from the check

  • The exact authored Rust program compiled against the actual proof-store crate; it records an initial passing run and then a later failing run for the same hotkey and topic.

Evidence from the check

  • The exact authored shell command source used to build proof-store, compile the Rust harness, and capture both executions.

Command output from the check

  • The first executed harness capture shows one stored passing result with primary 1.0 before any later submission.

Command output from the check

  • The second executed harness capture shows the same single entry now holds the later failing result, proving overwrite and no epoch scope.

Command output from the check

  • The captured zero-context diff identifies the changed store implementation and HTTP persistence call sites; the takeaway is that all paths invoke the unscoped overwrite method.

View artifacts

T-Rex Ran code and verified through T-Rex

@echobt
Mathis (echobt) merged commit 7bb56c3 into main Sep 4, 2026
5 checks passed
@echobt
Mathis (echobt) deleted the cursor/proof-emission-2000-8000-payout-modes branch September 4, 2026 17:11
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.

2 participants