feat(emission): live challenges are bounty and proof only - #210
Conversation
UID 0 is the owner+validator hotkey, so a sealed uid0=100% vector is a payout, not a burn. Skip Match submit when one UID holds all mass and is SubnetOwnerHotkey or validator_permit. Unsealed latest is not a submit path: do not load or submit LKG. HTTP burn-uid0.v1 fallback is unchanged. Co-authored-by: Mathis <echobt@users.noreply.github.com>
maybe_submit_match exceeded clippy::too_many_lines; record_submit_outcome keeps the Match submit path under the 100-line cap. Co-authored-by: Mathis <echobt@users.noreply.github.com>
Retune challenges.toml to bounty 5000 + proof 5000 (sum 10000), re-sign the throwaway ceremony, profile-gate relearn*, land ctx for the two live ids, and drop relearn from miner/docs/site live surfaces. Co-authored-by: Mathis <echobt@users.noreply.github.com>
Update site-api live-list fixtures, drop the stale design/prism lag log line, and backtick topic_id so ctx clippy is clean. Co-authored-by: Mathis <echobt@users.noreply.github.com>
Empty proof eval_image_digest 503s submits, so 5000/5000 would leave half the subnet unpayable. Retune to 5000/5000 in the ceremony that pins a non-empty proof-eval digest. Same throwaway owner key. Co-authored-by: Mathis <echobt@users.noreply.github.com>
|
@greptileai review |
Greptile SummaryThe PR reduces the live challenge trust root to Bounty and Proof, assigns them a 7000/3000 emission split while Proof remains unavailable, updates validator and deployment paths, and removes obsolete seal-lag guidance. No new issues were identified in the supplied scope. Merging remains blocked by unresolved prior findings affecting submission safety, credential handling, and release integrity. Confidence Score: 0/5Unsafe to merge until the outstanding blocking findings are fixed. The validator-permit read still converts missing, failed, and undecodable permit storage into an empty vector. The submission guard treats an absent permit entry as not permitted, so a pure vector assigned to a validator-permit UID can still be submitted while the safety-critical permit state is unavailable. The ctx gateway client still accepts arbitrary HTTP URLs and sends a configured Lium credential on every request, exposing the credential to a non-loopback plaintext gateway and on-path observers. The pairing-session cache still writes the bearer session before applying mode 0600, and the non-Unix branch does not enforce equivalent protection. The release workflow still grants contents-write authority while invoking dtolnay/rust-toolchain@master, so mutable upstream action code can affect release publishing. The Proof topics parser still does not recognize the endpoint's items envelope, causing that successful response shape to be printed as raw JSON rather than as topics. The validator seal-lag warning was corrected and no longer directs operators to retired sources. Reviews (2): Last reviewed commit: "fix(emission): bounty 7000 / proof 3000 ..." | Re-trigger Greptile |
| match raw { | ||
| Ok(Some(bytes)) => storage::decode_vec_bool(&bytes).unwrap_or_default(), | ||
| Ok(None) | Err(_) => Vec::new(), |
There was a problem hiding this comment.
Malformed, missing, and failed ValidatorPermit reads become an empty permit map. The submission guard treats a missing UID entry as not permitted, so a pure vector assigned to a validator-permit UID can reach chain submission when the safety-critical permit state was unavailable. Propagate these read and decode failures so the submission path fails closed.
Knowledge Base Used:
Artifacts
Populated-permit control script
- The executable runs the control that skips a pure vector for a UID marked by ValidatorPermit.
Malformed-permit submission script
- The executable runs malformed permit decoding and empty-map submission checks.
Populated-permit control output
- The control passed with a populated permit map and no pure-vector submission.
- The checks passed after malformed data became an empty permit map and the pure vector produced one submission call.
| pub fn new(gateway: &str, lium_key: Option<String>) -> Result<Self, String> { | ||
| let base = gateway.trim().trim_end_matches('/').to_owned(); | ||
| if !(base.starts_with("https://") || base.starts_with("http://")) { | ||
| return Err(format!( | ||
| "gateway must be an http(s) URL, got {base:?} (default is {DEFAULT_GATEWAY})" | ||
| )); | ||
| } |
There was a problem hiding this comment.
Plaintext gateways expose keys
The client accepts arbitrary http:// gateway URLs and attaches X-Lium-Api-Key to every request when a key is configured. A miner using a non-loopback plaintext gateway exposes a spendable Lium credential to the gateway and any on-path observer, who can reuse it. Require HTTPS when a key is present, or allow plaintext only for loopback addresses without forwarding the credential.
How this was verified: A plaintext gateway capture received the configured Lium key on both GET and POST requests.
Artifacts
Plaintext gateway capture script
- This executable captures requests to an accepted HTTP gateway before and after configuring a Lium key.
- GET and POST returned successfully and no API-key header was captured.
- Both requests exposed the configured Lium key to the plaintext gateway.
| std::fs::write(&path, format!("{record}\n")).map_err(|e| format!("write session: {e}"))?; | ||
| restrict(&path)?; |
There was a problem hiding this comment.
The submitted cache path writes the bearer session before applying restrictive file permissions, and the non-Unix branch does not enforce an equivalent restriction. A local principal able to read the file during that window, or on an unsupported platform, can reuse the session to submit reports as the paired miner. Create the file with restrictive permissions before writing the credential, and refuse caching where equivalent protection cannot be enforced.
How this was verified: The observed file-operation order wrote the bearer session before applying mode 0600.
Artifacts
- The output records the bearer-session write before chmod, establishing the exposure window.
- The same probe records mode 0600 before the bearer-session write in the corrected ordering.
Session permission probe source
- This capture contains the exact executable ordering probe used to observe session writes and permission changes.
- The attempted Windows-target check was blocked because that Rust target was not installed.
- The complete ctx test suite passed after the corrected file-write ordering.
| let items = reply | ||
| .body | ||
| .as_array() | ||
| .or_else(|| reply.body.get("topics").and_then(Value::as_array)); |
There was a problem hiding this comment.
The command recognizes a root array and a topics envelope but not the endpoint's { "items": [...] } response. A successful response therefore prints raw JSON instead of the intended topic list and empty-state guidance. This is non-blocking, but makes the miner CLI harder to use; read the items array in the parser.
Knowledge Base Used: Challenge network and submission lifecycle
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Artifacts
- This local endpoint harness exercises root-array and items-envelope responses through the actual CLI.
Root-array Proof topics output
- The command formats a root-array response as the expected published-topic list.
Items-envelope Proof topics output
- The command prints the valid items envelope as raw JSON instead of a topic list.
- The ctx unit suite passed while containing no coverage for the items-envelope rendering path.
| ref: ${{ inputs.tag || github.ref }} | ||
|
|
||
| - name: Install Rust toolchain | ||
| uses: dtolnay/rust-toolchain@master |
There was a problem hiding this comment.
Mutable action publishes releases
The release workflow runs dtolnay/rust-toolchain@master while it has authority to write repository contents and publish dist/* release assets. If that mutable upstream reference is retargeted or compromised, its code can publish attacker-controlled CLI binaries and checksums. Pin third-party actions to reviewed full commit SHAs and restrict write authority to only the release work that needs it.
How this was verified: The workflow grants contents-write authority, invokes the mutable @master action, and uploads dist/* through the release step.
Knowledge Base Used: Deployment automation and infrastructure
Artifacts
Release workflow assertion harness
- This executable parses action references, contents permission, and release asset publication in the workflow.
Immutable-action control output
- The control reports immutable references, read-only contents, and no release asset glob.
Release workflow assertion output
- The workflow contains the mutable master ref, contents-write permission, and dist asset publication.
| lag_epochs = lag, | ||
| metagraph_block = ?latest.metagraph_block, | ||
| "pressure verify: sealed weights lag chain epoch; check design/prism emit + base-real-seal" | ||
| "pressure verify: sealed weights lag chain epoch; live sources still design+prism sealed 2026-08-22; Relearn must replace those sources once ready. Do not treat design/prism as the target live set." |
There was a problem hiding this comment.
Lag guidance names retired sources
The seal-lag warning tells operators that Design and Prism are live and that Relearn must replace them, while the active trust root contains only Bounty and Proof. This is non-blocking, but it sends operators toward obsolete remediation during a seal-lag incident. Update the warning to name Bounty and Proof or derive the text from the loaded trust root.
Knowledge Base Used:
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Artifacts
- This executable compares the validator warning with the active trust-root challenge IDs.
Live-source consistency output
- The check fails because active Bounty and Proof sources do not match the warning's retired-source guidance.
Stale-warning diagnostic output
- The diagnostic reports the stale warning condition with Bounty and Proof as the active source IDs.
Warning and trust-root source capture
- The capture shows the stale warning text and the active Bounty and Proof trust-root rows.
|
@greptileai review |
Rebase of #207 onto main post #210/#211. Live catalog stays bounty+proof. ctx relearn|image|agent remain for local stacks and print an off warning. xtask now pins DEFAULT_GATEWAY from the binary and refuses miner-doc placeholders and operator env names. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mathis <echobt@users.noreply.github.com>
Mathis lock for subnet 100, with Architecte emission counter: live challenges are only
bountyandproof. Relearn*, Prism, and Design stay off (no trust-root row, no emission). Relearn* code remains in-repo behind therelearn/mmcompose profiles.Emission (Architecte lock)
Proof's
eval_image_digestis empty — live submits 503. An equal 5000/5000 split would leave half the subnet unpayable. Current ceremony:bountyproofRetune to 5000/5000 only in the same (or next) ceremony that pins a non-empty proof-eval digest. Do not invent a sha256.
config/challenges.tomlandconfig/challenges.staging.tomlre-signed with the existing throwaway owner key (config/CEREMONY.md). Secret never entered git.Also lands
mainvia feat(proof): Proof challenge + dynamic topics + RLM judge digest pin #209.main— kept. Emptyeval_image_digeststill 503.ctxCLI adapted: onlyproof+bountycommands. No relearn/image/agent surface. Default gatewayhttps://network.cortex.foundation.NoScore(ChallengeInternal)) and proof (empty digest / empty open set → 503).Does not merge. No Modal. No secrets/mnemonics in git.
Greptile
Every PR is reviewed by Greptile before merge. Config:
.greptile/.@greptileai reviewTest plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warnings(pre-retune; ctx clippy after retune)trustroot,ctx,site-types,site-api,site-data,proof-scorecargo run -p xtask -- loc-cap consensus-lint spec-check design-check external-docs-check./deploy/scripts/assert-compose-matrix.shwhen Docker is availableRisk
Emission cutover: miners on Relearn* earn nothing under this root. Bounty takes 70% while Proof cannot score (empty digest). Validator LKG/burn refuse from #208 is still required.
Naming
I did not rename
BASE_*environment variables, deployed host paths (/opt/base,/run/base, …), GHCRbaseintelligence/basepackage names, orbase-*-v1cryptographic domain tags.