Skip to content

fix(validation): directional gating for copycat detection#65

Merged
erfanMhi merged 2 commits intomainfrom
feat/copycat-directional-gating
Apr 9, 2026
Merged

fix(validation): directional gating for copycat detection#65
erfanMhi merged 2 commits intomainfrom
feat/copycat-directional-gating

Conversation

@erfanMhi
Copy link
Copy Markdown
Contributor

@erfanMhi erfanMhi commented Apr 9, 2026

Summary

  • Stops the copycat detector from zeroing honest victims alongside attackers
  • Uses S3 LastModified to identify the later uploader as the copier; abstains when unresolved
  • Archives per-miner upload times across the interval so cross-window attribution keeps working when a victim goes offline

Test plan

  • 32 unit tests pass including 9 new directional-gating regression tests
  • ruff + pyright clean on modified files
  • Deployed to basilica-grail-validator with live log verification

Summary by CodeRabbit

Release Notes

  • New Features

    • Copycat violations now include directional attribution identifying which miner copied from which.
  • Improvements

    • Miner sampling now captures upload timestamp data for more accurate validation.
    • Copycat detection enhanced with better handling for unresolved attribution cases.
    • Updated test mode miner selection logic.
  • Tests

    • Added comprehensive test coverage for directional attribution scenarios.

erfanMhi added 2 commits April 9, 2026 16:34
- Replace symmetric `flagged.update((a, b))` with `_attribute_pair_direction`
  that uses S3 LastModified to identify the later uploader (copier) and
  flag only the copier; abstain when direction is unresolved.
- Bundle per-miner copycat state in `MinerCopycatSubmission` so `detect_cheaters`
  takes one argument per miner instead of parallel digest/upload parameters.
…bution

- CopycatTracker now remembers per-miner S3 LastModified across the whole
  submission interval, so interval-scope directional attribution survives a
  victim going offline mid-interval (caught by two independent reviewers).
- Add regression tests for the victim-offline scenario and for the
  reset_interval clearing the archived timestamps.
@erfanMhi erfanMhi merged commit 9ed4d43 into main Apr 9, 2026
6 checks passed
@erfanMhi erfanMhi deleted the feat/copycat-directional-gating branch April 9, 2026 22:54
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 9, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 85218864-1630-4cac-b5eb-ce7a2ca72681

📥 Commits

Reviewing files that changed from the base of the PR and between 82a701c and 2f881b7.

📒 Files selected for processing (5)
  • grail/validation/copycat_service.py
  • grail/validation/sampling.py
  • grail/validation/service.py
  • grail/validation/window_processor.py
  • tests/unit/validation/test_copycat_detection.py

Walkthrough

This PR refactors the copycat detection pipeline to incorporate S3 upload timestamp attribution. It introduces MinerCopycatSubmission bundling digest counter, rollouts, and upload time per miner, updates the detection flow to thread timing metadata from sampling through window processing to copycat analysis, and implements directional gating (flagging only the later uploader as copier).

Changes

Cohort / File(s) Summary
Core Copycat Detection Logic
grail/validation/copycat_service.py
Introduced MinerCopycatSubmission dataclass and UploadTimesByHotkey type. Added _attribute_pair_direction and _PairAttribution for resolving copier/victim via S3 LastModified timestamps. Extended CopycatViolation with optional copier and victim fields. Updated ingest_window to accept submissions, _find_cheaters to gate only the resolved copier (unresolved cases suppress gating but log warnings), and both detect_cheaters methods to accept submissions instead of rollout counters.
Data Collection & Flow
grail/validation/sampling.py, grail/validation/service.py, grail/validation/window_processor.py
discover_active_miners now returns (active_hotkeys, upload_times) tuple with S3 LastModified timestamps. Service threads this timing data to WindowProcessor.process_window via new uploads_by_hotkey parameter. WindowProcessor constructs MinerCopycatSubmission objects by joining digest counters and rollouts with upload times before invoking copycat detection. Service also refactored test_mode miner selection to use validator's own wallet hotkey instead of constant TRAINER_UID.
Tests
tests/unit/validation/test_copycat_detection.py
Updated all ingest_window calls to use MinerCopycatSubmission format with explicit upload_time values. Adjusted assertions to expect cheater set containing only later uploader (copier) with validated attribution fields. Added TestDirectionalGating class covering directional gating behavior, role swapping by upload order, abstention on missing/equal timestamps, interval persistence, and regression cases.

Sequence Diagram(s)

sequenceDiagram
    participant Sampler as MinerSampler
    participant Service as CopycatService
    participant Processor as WindowProcessor
    participant Copycat as CopycatTracker
    participant S3 as S3 API

    Sampler->>S3: Check active miners
    S3-->>Sampler: active_hotkeys, upload_times (LastModified)
    Sampler-->>Service: (active_hotkeys, upload_times)
    
    Service->>Processor: process_window(uploads_by_hotkey=upload_times)
    
    Processor->>Processor: Validate miners<br/>Collect digest_counters<br/>total_rollouts
    
    Processor->>Processor: Construct MinerCopycatSubmission<br/>Join with upload_times
    
    Processor->>Copycat: detect_cheaters(submissions)
    
    Copycat->>Copycat: _attribute_pair_direction<br/>(Compare S3 timestamps)
    
    Copycat->>Copycat: Gate only resolved copier<br/>Log unresolved cases
    
    Copycat-->>Processor: CopycatViolation<br/>(copier, victim, resolved)
    
    Processor-->>Service: WindowResults
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 With timestamps from S3's halls so high,
We chase the copiers, uploaders sly—
Attribution flows through sampling's dance,
Till only the later uploader's gait plants
A "cheater" mark on the window's command! ⏱️

✨ 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 feat/copycat-directional-gating

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 and usage tips.

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