Skip to content

fix(similarity): exclude same-coldkey prior art (Design + Prism) - #82

Merged
echobt merged 1 commit into
mainfrom
fix/similarity-exclude-coldkey
Aug 7, 2026
Merged

fix(similarity): exclude same-coldkey prior art (Design + Prism)#82
echobt merged 1 commit into
mainfrom
fix/similarity-exclude-coldkey

Conversation

@echobt

@echobt echobt commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Similarity / copy corpora for Design and Prism now exclude prior art from the same hotkey or coldkey, so miners iterating via new hotkeys under 1-max gating are not treated as cross-miner copies.
  • Coldkey comes from bulk SubtensorModule.Owner on the cached metagraph (15m TTL) and is persisted at intake (miner_coldkey on design_harness / prism_submission, migration 0014).
  • Shared helper: challenge_agentic::same_miner_identity; Design corpus.rs + Prism gate / LLM similarity / agentic corpus all use it. Docs + design-check pin updated.

Test plan

  • Unit tests: same hotkey excluded; different hotkey + same coldkey excluded; different coldkey still compared (Design + Prism)
  • cargo fmt --check, clippy -D warnings, cargo test --workspace
  • xtask loc-cap, design-check, external-docs-check, consensus-lint, spec-check
  • After merge: apply migration 0014 on prod DB; redeploy design-challenge (live similarity cares)
  • Prism: redeploy prism-challenge only if prod binary needs the corpus filter (same code path on main)

Deploy notes

Summary by CodeRabbit

  • New Features

    • Added coldkey tracking across miner identity, metagraph data, submissions, and harness records.
    • Miner identity matching now supports hotkey and coldkey combinations.
    • Metagraph updates now include coldkey information, including safe handling of missing data.
  • Behavior Changes

    • Copy and similarity checks now exclude prior work associated with the same hotkey or coldkey, while retaining eligible work from other miners.
  • Documentation

    • Updated design challenge, scoring, and anti-copy guidance to reflect the revised comparison rules.

Hotkey 1-max gating forces miners to iterate under new hotkeys of the same
coldkey; treat those revisions as self, not cross-miner copies, in gate and
review corpora. Persist Owner coldkey at intake from the cached metagraph.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds coldkey data to metagraphs, caches, harnesses, and submissions. It persists coldkeys and applies hotkey/coldkey miner identity checks when building copy-gate and review corpora.

Changes

Metagraph coldkey loading

Layer / File(s) Summary
Metagraph coldkey loading and cache propagation
crates/chain-live/..., crates/chain/..., crates/submission-gating/...
Chain metagraph reads now batch owner-derived coldkeys. Metagraph, FakeChainConfig, and MetagraphView store UID-aligned coldkeys.
Metagraph and fixture validation
crates/chain-live/src/tests.rs, crates/challenge-common/src/expected_set.rs, crates/prism-challenge/src/api.rs
Tests and simulated metagraphs now provide and validate coldkey mappings.

Coldkey persistence and capture

Layer / File(s) Summary
Database coldkey schema and models
crates/db/migrations/..., crates/db/src/..., crates/design-db/..., crates/design-store/..., crates/prism-store/...
Both submission tables store nullable, validated miner coldkeys. Row models, projections, inserts, and conversions carry the field.
HTTP submission and harness capture
crates/design-http/src/api.rs, crates/prism-challenge/src/api.rs
Submission and harness creation resolve coldkeys from the metagraph snapshot and persist them when available.

Same-miner corpus filtering

Layer / File(s) Summary
Miner identity matching
crates/challenge-agentic/src/lib.rs, crates/design-challenge/src/corpus.rs
Shared identity checks match case-insensitive hotkeys or matching non-empty coldkeys. Corpus tests cover same- and different-coldkey cases.
Copy-gate and review corpus integration
crates/prism-challenge/src/agentic.rs, crates/prism-challenge/src/orchestrator.rs
Copy-gate, similarity, and agentic corpora exclude the candidate and prior submissions from the same miner.

Fixtures and documentation

Layer / File(s) Summary
Compatibility fixtures and documentation
crates/*/tests/..., bins/design-challenge/tests/..., docs/..., xtask/src/design_check.rs
Existing fixtures initialize absent coldkeys. Documentation and content checks describe same-hotkey and same-coldkey exclusions.
Host simulation and scoring documentation
crates/design-challenge/src/host_sim.rs, crates/design-challenge/src/score.rs
Module documentation is shortened and the production-environment expression is simplified without changing its behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: excluding same-coldkey prior art from Design and Prism similarity checks.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/similarity-exclude-coldkey

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
echobt merged commit 392cdfa into main Aug 7, 2026
2 of 3 checks passed
@echobt
echobt deleted the fix/similarity-exclude-coldkey branch August 7, 2026 14:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
crates/chain-live/src/tests.rs (1)

658-659: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mock actual Owner keys and assert resolved coldkeys.

The mocked changes contain Keys storage keys, not Owner storage keys. Therefore, fetch_coldkeys_for_hotkeys cannot match either response, and coldkeys remains zero-filled. Line 659 checks only the vector length.

Return storage_map_key_account_blake2("SubtensorModule", "Owner", ...) keys with distinct coldkeys. Assert the values in UID order. Return them out of order to verify the index mapping.

Also applies to: 680-693

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/chain-live/src/tests.rs` around lines 658 - 659, Update the mock
responses in the test around fetch_coldkeys_for_hotkeys to use
storage_map_key_account_blake2 with the “SubtensorModule” and “Owner” map,
associating distinct coldkeys with the requested hotkeys. Return the mocked
Owner entries out of order, then assert the resolved coldkeys by UID order and
retain the length assertion.
crates/design-http/src/api.rs (1)

1170-1171: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Use distinct coldkey data in the metagraph fixture.

Line [1171] passes raw for both hotkeys and coldkeys. Each test hotkey therefore owns itself. This cannot detect UID-to-owner alignment errors or the required case where two hotkeys share one coldkey.

Add a fixture with distinct hotkeys and one shared coldkey. Assert that intake persists the expected HarnessRow.miner_coldkey values. This targets the PR objective of excluding same-coldkey prior art across rotated hotkeys.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/design-http/src/api.rs` around lines 1170 - 1171, Update the metagraph
fixture around the cache.update call to use distinct hotkey data and a separate
coldkey fixture with at least two hotkeys sharing one coldkey. Extend the intake
test assertions to verify each persisted HarnessRow.miner_coldkey matches the
expected shared-owner mapping, covering UID-to-owner alignment and rotated
hotkeys.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/db/migrations/0014_miner_coldkey.sql`:
- Around line 9-15: Revise migration 0014_miner_coldkey.sql for the
transactional sqlx::migrate! deployment: add the CHECK constraint as NOT VALID,
create the partial index with CREATE INDEX CONCURRENTLY, and move constraint
validation into a separate non-transactional deployment step using VALIDATE
CONSTRAINT. If the migration framework cannot execute these steps online,
document the required write outage instead.

In `@crates/design-challenge/src/host_sim.rs`:
- Around line 2-7: Update is_prod_env to classify deploy_env value "staging" as
restricted alongside "prod" and "production", while preserving the netuid 100
behavior. Add a regression test confirming staging with a non-100 netuid cannot
enable host simulation through host_sim_allowed.

In `@crates/design-http/src/api.rs`:
- Around line 364-372: In the intake flow around the first metagraph snapshot
that resolves uid, capture and retain coldkey_hex_of(&hotkey) from that same
view. Update the HarnessRow construction to use the retained miner coldkey, and
remove the later st.snapshot() lookup near the miner_coldkey assignment so
persisted identity remains consistent with the uid-producing snapshot.

In `@crates/submission-gating/src/lib.rs`:
- Around line 477-486: Update the key construction logic around the hotkeys and
coldkeys collections so filtering invalid hotkeys preserves their original
source indexes; pair each retained hotkey with the coldkey at that same index
instead of taking the first keys.len() coldkeys. Keep zero-value fallback and
resizing behavior for missing or invalid coldkeys, and add a test covering an
invalid leading hotkey followed by valid paired entries.

In `@docs/DESIGN_CHALLENGE.md`:
- Around line 381-385: Replace the ambiguous same-miner corpus wording with one
consistent phrase meaning “other miners’ prior art only.” Apply the same
corrected phrase in docs/DESIGN_CHALLENGE.md lines 381-385,
docs/DESIGN_CHALLENGE_CHECKLIST.md line 49 (`selfsim_excluded`), and
xtask/src/design_check.rs lines 42-45 (`CONTENT_PINS`).

---

Nitpick comments:
In `@crates/chain-live/src/tests.rs`:
- Around line 658-659: Update the mock responses in the test around
fetch_coldkeys_for_hotkeys to use storage_map_key_account_blake2 with the
“SubtensorModule” and “Owner” map, associating distinct coldkeys with the
requested hotkeys. Return the mocked Owner entries out of order, then assert the
resolved coldkeys by UID order and retain the length assertion.

In `@crates/design-http/src/api.rs`:
- Around line 1170-1171: Update the metagraph fixture around the cache.update
call to use distinct hotkey data and a separate coldkey fixture with at least
two hotkeys sharing one coldkey. Extend the intake test assertions to verify
each persisted HarnessRow.miner_coldkey matches the expected shared-owner
mapping, covering UID-to-owner alignment and rotated hotkeys.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c5e62321-5700-40b4-beb4-b84bd0feb472

📥 Commits

Reviewing files that changed from the base of the PR and between 6e159e2 and 99bb2d8.

📒 Files selected for processing (40)
  • bins/design-challenge/tests/resanitize_backfill.rs
  • crates/chain-live/src/lib.rs
  • crates/chain-live/src/storage.rs
  • crates/chain-live/src/tests.rs
  • crates/chain/src/lib.rs
  • crates/challenge-agentic/src/lib.rs
  • crates/challenge-common/src/expected_set.rs
  • crates/db/migrations/0014_miner_coldkey.sql
  • crates/db/src/prism_store.rs
  • crates/design-challenge/src/corpus.rs
  • crates/design-challenge/src/host_sim.rs
  • crates/design-challenge/src/score.rs
  • crates/design-challenge/tests/cheat_fixtures.rs
  • crates/design-challenge/tests/e2e_sim.rs
  • crates/design-challenge/tests/orchestrator_retry.rs
  • crates/design-challenge/tests/screenshot_backfill.rs
  • crates/design-db/src/lib.rs
  • crates/design-http/src/api.rs
  • crates/design-http/tests/admin_winners.rs
  • crates/design-store/src/dbstore.rs
  • crates/design-store/src/store.rs
  • crates/prism-challenge/src/agentic.rs
  • crates/prism-challenge/src/api.rs
  • crates/prism-challenge/src/orchestrator.rs
  • crates/prism-challenge/tests/arch_competition.rs
  • crates/prism-challenge/tests/cheat_arch_copy.rs
  • crates/prism-challenge/tests/cheat_metrics.rs
  • crates/prism-challenge/tests/copy_gate.rs
  • crates/prism-challenge/tests/e2e_orchestrate_sim.rs
  • crates/prism-emit/tests/epoch_semantics.rs
  • crates/prism-store/src/dbprism.rs
  • crates/prism-store/src/store.rs
  • crates/submission-gating/src/lib.rs
  • docs/DESIGN_CHALLENGE.md
  • docs/DESIGN_CHALLENGE_CHECKLIST.md
  • docs/PRISM.md
  • docs/PRISM_RECIPE.md
  • docs/external-miner/design.md
  • docs/external-miner/prism.md
  • xtask/src/design_check.rs

Comment on lines +9 to +15
ALTER TABLE design_harness
ADD CONSTRAINT design_harness_miner_coldkey_hex
CHECK (miner_coldkey IS NULL OR miner_coldkey ~ '^[0-9a-f]{64}$');

CREATE INDEX ix_design_harness_coldkey
ON design_harness (miner_coldkey)
WHERE miner_coldkey IS NOT NULL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n 'sqlx::migrate|Migrator|migrate!|no_transaction|no-tx|CREATE INDEX' \
  --glob '*.rs' --glob '*.toml' --glob '*.sql' .

Repository: BaseIntelligence/base

Length of output: 5550


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- candidate files ---\n'
fd -a 'lib.rs|0014_miner_coldkey.sql' .

printf '\n--- crates/db/src/lib.rs relevant section ---\n'
sed -n '90,115p' crates/db/src/lib.rs

printf '\n--- 0014_miner_coldkey.sql line-numbered ---\n'
cat -n crates/db/migrations/0014_miner_coldkey.sql

printf '\n--- migrations containing BEGIN/COMMIT/LOCK/CREATE INDEX NOT CONCURRENTLY/ALTER TABLE ... VALIDATE CONSTRAINT ---\n'
python3 - <<'PY'
import subprocess, re, pathlib
sql_files = sorted(pathlib.Path('crates/db/migrations').glob('*.sql'))
for f in sql_files:
    text = f.read_text()
    if any(tok in text.upper() for tok in ['BEGIN WORK', 'BEGIN TRANSACTION', 'CREATE INDEX', 'LOCK TABLE', 'ALTER TABLE', 'NO VALIDATE', 'VALIDATE CONSTRAINT', 'ON DATABASE', 'ON ROLE', 'ROLLBACK']):
        print(f'-- {f}')
        for i,line in enumerate(text.splitlines(),1):
            if re.search(r'(^|\s)(BEGIN WORK|BEGIN TRANSACTION|COMMIT|ROLLBACK|CREATE INDEX|LOCK TABLE|ALTER TABLE|ON TABLE|NOT VALID|VALIDATE CONSTRAINT|ON DATABASE|ON ROLE)\b', line.strip().upper()):
                print(f'{i}: {line}')
PY

printf '\n--- repo config for migrations/deploy docs mentioning migration outage/lock/concurrent ---\n'
rg -n 'migration|concurrent|CREATE INDEX|VALIDATE CONSTRAINT|LOCK|outage|CREATE INDEX CONCURRENTLY|sqlx' \
  --glob '!target/**' --glob '!node_modules/**' \
  README.md docs crates Cargo.toml 2>/dev/null || true

Repository: BaseIntelligence/base

Length of output: 250


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- candidate files ---'
fd 'lib.rs|0014_miner_coldkey.sql' .

printf '%s\n' ''
printf '%s\n' '--- crates/db/src/lib.rs relevant section ---'
sed -n '90,115p' crates/db/src/lib.rs

printf '%s\n' ''
printf '%s\n' '--- 0014_miner_coldkey.sql line-numbered ---'
cat -n crates/db/migrations/0014_miner_coldkey.sql

printf '%s\n' ''
printf '%s\n' '--- migrations containing relevant SQL statements ---'
python3 - <<'PY'
import re
from pathlib import Path
for f in sorted(Path('crates/db/migrations').glob('*.sql')):
    text = f.read_text()
    tokens = ['BEGIN WORK', 'BEGIN TRANSACTION', 'COMMIT', 'ROLLBACK', 'CREATE INDEX', 'LOCK TABLE', 'ALTER TABLE', 'NOT VALID', 'VALIDATE CONSTRAINT']
    if any(tok in text.upper() for tok in tokens):
        print(f'-- {f}')
        for i, line in enumerate(text.splitlines(), 1):
            stripped = line.strip().upper()
            if any(tok in stripped for tok in tokens) or re.search(r'ALTER TABLE\s+\w+\s+ADD\s+CONSTRAINT\s+\w+\s+CHECK', stripped) or re.search(r'CREATE\s+INDEX\s+(CONCURRENTLY\s+)?\w+', stripped):
                print(f'{i}: {line}')
PY

printf '%s\n' ''
printf '%s\n' '--- deployment/migration guidance mentions ---'
rg -n 'migration|concurrent|CREATE INDEX|VALIDATE CONSTRAINT|LOCK|outage|CREATE INDEX CONCURRENTLY|sqlx|deploy|deployment plan' \
  --glob '!target/**' --glob '!node_modules/**' \
  README.md docs crates Cargo.toml 2>/dev/null || true

Repository: BaseIntelligence/base

Length of output: 50377


Use an online deployment plan for 0014_miner_coldkey.sql.

sqlx::migrate!("./migrations").run(pool) runs this as a transaction. The added CHECK constraints scan existing rows during ADD CONSTRAINT, and the two new indexes acquire table writes while they build. Split the migration into non-transactional online steps: use NOT VALID for both constraints, add the indexes with CREATE INDEX CONCURRENTLY, then schedule a separate VALIDATE CONSTRAINT step. If that cannot be automated, document the required write outage before deploying this migration.

🧰 Tools
🪛 Squawk (2.61.0)

[warning] 10-11: By default new constraints require a table scan and block writes to the table while that scan occurs. Use NOT VALID with a later VALIDATE CONSTRAINT call.

(constraint-missing-not-valid)


[warning] 13-15: During normal index creation, table updates are blocked, but reads are still allowed. Use concurrently to avoid blocking writes.

(require-concurrent-index-creation)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/db/migrations/0014_miner_coldkey.sql` around lines 9 - 15, Revise
migration 0014_miner_coldkey.sql for the transactional sqlx::migrate!
deployment: add the CHECK constraint as NOT VALID, create the partial index with
CREATE INDEX CONCURRENTLY, and move constraint validation into a separate
non-transactional deployment step using VALIDATE CONSTRAINT. If the migration
framework cannot execute these steps online, document the required write outage
instead.

Source: Linters/SAST tools

Comment on lines +2 to +7
//! Prod/staging must use Docker; host sim needs `BASE_ALLOW_HOST_SIM` + non-prod.

/// Mainnet netuid / explicit deploy env → prod (host Sim forbidden).
#[must_use]
pub fn is_prod_env(netuid: u16, deploy_env: Option<&str>) -> bool {
if netuid == 100 {
return true;
}
matches!(deploy_env, Some("prod" | "production"))
netuid == 100 || matches!(deploy_env, Some("prod" | "production"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Block host simulation in staging.

When BASE_DEPLOY_ENV is staging and netuid is not 100, is_prod_env returns false. host_sim_allowed then permits host simulation when allow_host_sim is true. Include staging in the restricted-environment predicate and add a regression test.

As per coding guidelines, “Never host Sim in staging or production. Use Docker sandbox there.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/design-challenge/src/host_sim.rs` around lines 2 - 7, Update
is_prod_env to classify deploy_env value "staging" as restricted alongside
"prod" and "production", while preserving the netuid 100 behavior. Add a
regression test confirming staging with a non-100 netuid cannot enable host
simulation through host_sim_allowed.

Source: Coding guidelines

Comment on lines +364 to +372
let miner_coldkey = st
.metagraph
.as_ref()
.and_then(|c| c.snapshot())
.and_then(|v| v.coldkey_hex_of(&hotkey));
let row = HarnessRow {
id: id.clone(),
miner_hotkey: hotkey.clone(),
miner_coldkey,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Capture miner_coldkey from the membership snapshot.

The intake validates the hotkey with one metagraph snapshot at Line [320]. Lines [364-368] call snapshot() again before persisting the row. A cache refresh between these calls can change the SubtensorModule.Owner value or return no owner.

The persisted identity can then disagree with the snapshot that supplied uid. Capture coldkey_hex_of(&hotkey) from the first view that returned uid, and remove the second snapshot lookup. This identity feeds same-miner corpus exclusion.

Proposed snapshot-consistent capture
 let mut uid = None;
+let mut miner_coldkey = None;
 if !exists {
     if let Some(cache) = &st.metagraph {
         match cache.snapshot() {
             Some(view) => match view.uid_of_hex(&hotkey) {
-                Some(u) => uid = Some(u),
+                Some(u) => {
+                    uid = Some(u);
+                    miner_coldkey = view.coldkey_hex_of(&hotkey);
+                }
                 None => {
                     return json_err(
                         StatusCode::FORBIDDEN,
@@
-    let miner_coldkey = st
-        .metagraph
-        .as_ref()
-        .and_then(|c| c.snapshot())
-        .and_then(|v| v.coldkey_hex_of(&hotkey));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/design-http/src/api.rs` around lines 364 - 372, In the intake flow
around the first metagraph snapshot that resolves uid, capture and retain
coldkey_hex_of(&hotkey) from that same view. Update the HarnessRow construction
to use the retained miner coldkey, and remove the later st.snapshot() lookup
near the miner_coldkey assignment so persisted identity remains consistent with
the uid-producing snapshot.

Comment on lines 477 to +486
let keys: Vec<[u8; 32]> = hotkeys
.iter()
.filter_map(|h| <[u8; 32]>::try_from(h.as_slice()).ok())
.collect();
let mut cks: Vec<[u8; 32]> = coldkeys
.iter()
.take(keys.len())
.map(|c| <[u8; 32]>::try_from(c.as_slice()).unwrap_or([0; 32]))
.collect();
cks.resize(keys.len(), [0; 32]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve coldkey source indexes when filtering hotkeys.

keys removes invalid hotkeys, but cks takes the first keys.len() coldkeys. For hotkeys = [invalid, A] and coldkeys = [X, Y], hotkey A receives coldkey X.

Build each retained hotkey and coldkey from the same source index. Add a test with an invalid leading hotkey.

Proposed fix
-        let keys: Vec<[u8; 32]> = hotkeys
-            .iter()
-            .filter_map(|h| <[u8; 32]>::try_from(h.as_slice()).ok())
-            .collect();
-        let mut cks: Vec<[u8; 32]> = coldkeys
-            .iter()
-            .take(keys.len())
-            .map(|c| <[u8; 32]>::try_from(c.as_slice()).unwrap_or([0; 32]))
-            .collect();
-        cks.resize(keys.len(), [0; 32]);
+        let mut keys = Vec::with_capacity(hotkeys.len());
+        let mut cks = Vec::with_capacity(hotkeys.len());
+        for (uid, hotkey) in hotkeys.iter().enumerate() {
+            let Ok(hotkey) = <[u8; 32]>::try_from(hotkey.as_slice()) else {
+                continue;
+            };
+            let coldkey = coldkeys
+                .get(uid)
+                .and_then(|coldkey| <[u8; 32]>::try_from(coldkey.as_slice()).ok())
+                .unwrap_or([0; 32]);
+            keys.push(hotkey);
+            cks.push(coldkey);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let keys: Vec<[u8; 32]> = hotkeys
.iter()
.filter_map(|h| <[u8; 32]>::try_from(h.as_slice()).ok())
.collect();
let mut cks: Vec<[u8; 32]> = coldkeys
.iter()
.take(keys.len())
.map(|c| <[u8; 32]>::try_from(c.as_slice()).unwrap_or([0; 32]))
.collect();
cks.resize(keys.len(), [0; 32]);
let mut keys = Vec::with_capacity(hotkeys.len());
let mut cks = Vec::with_capacity(hotkeys.len());
for (uid, hotkey) in hotkeys.iter().enumerate() {
let Ok(hotkey) = <[u8; 32]>::try_from(hotkey.as_slice()) else {
continue;
};
let coldkey = coldkeys
.get(uid)
.and_then(|coldkey| <[u8; 32]>::try_from(coldkey.as_slice()).ok())
.unwrap_or([0; 32]);
keys.push(hotkey);
cks.push(coldkey);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/submission-gating/src/lib.rs` around lines 477 - 486, Update the key
construction logic around the hotkeys and coldkeys collections so filtering
invalid hotkeys preserves their original source indexes; pair each retained
hotkey with the coldkey at that same index instead of taking the first
keys.len() coldkeys. Keep zero-value fallback and resizing behavior for missing
or invalid coldkeys, and add a test covering an invalid leading hotkey followed
by valid paired entries.

Comment thread docs/DESIGN_CHALLENGE.md
Comment on lines +381 to +385
**other hotkeys' and same-coldkey prior art only** — entries owned by the
candidate's own `miner_hotkey` **or** `miner_coldkey` are excluded, and so is
anything created at or after the candidate. After 1-max gating a miner iterates
via a new hotkey under the same coldkey; those revisions must not be treated as
cross-miner copies. Selection lives in one place,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Use one unambiguous same-miner corpus marker.

The shared phrase says that same-coldkey prior art is included, while the surrounding contract excludes the candidate's hotkey and coldkey. Keep the specification, checklist, and design-check marker on one corrected phrase.

  • docs/DESIGN_CHALLENGE.md#L381-L385: replace the ambiguous phrase with other miners' prior art only or equivalent wording.
  • docs/DESIGN_CHALLENGE_CHECKLIST.md#L49-L49: update selfsim_excluded to the same corrected phrase.
  • xtask/src/design_check.rs#L42-L45: update CONTENT_PINS to require the corrected phrase.
📍 Affects 3 files
  • docs/DESIGN_CHALLENGE.md#L381-L385 (this comment)
  • docs/DESIGN_CHALLENGE_CHECKLIST.md#L49-L49
  • xtask/src/design_check.rs#L42-L45
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/DESIGN_CHALLENGE.md` around lines 381 - 385, Replace the ambiguous
same-miner corpus wording with one consistent phrase meaning “other miners’
prior art only.” Apply the same corrected phrase in docs/DESIGN_CHALLENGE.md
lines 381-385, docs/DESIGN_CHALLENGE_CHECKLIST.md line 49 (`selfsim_excluded`),
and xtask/src/design_check.rs lines 42-45 (`CONTENT_PINS`).

echobt added a commit that referenced this pull request Aug 7, 2026
…c-challenges

chore(deploy): promote prod design+prism pins for 392cdfa (#82)
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