SPEC-103-A: Validator Role — Attestations, Credit, and Anti-Foul-Play

Implements: ADR-103 · Status: Draft (pre-acceptance) · Updated: 2026-06-22

This spec defines the contract for the validator role: a first-class, creditable, distributed verifier that publishes signed reproducible attestations, governed so that those attestations earn credit and penalise foul play without ever becoming load-bearing for soundness. It builds on SPEC-049-A (tiered split + mandatory trusted central re-check) and is intentionally implementation-light: the decision and rationale are in ADR-103. It is a draft because ADR-103 is Proposed; constants marked tunable are placeholders pending pilot data.

1. Roles

Three logical roles, separate in protocol / DB / rewards / audit log; one binary may run several (unsorry-node --roles calculator,validator).

2. The load-bearing invariant (normative — inherited)

A validator attestation is a claim about execution, never a trusted input to soundness. SPEC-049-A §2 stands unchanged: a proof is admitted to UnsorryLibrary only by the mandatory trusted central re-check at p = 1, which re-derives the statement from canonical goal source, re-elaborates the changed-module reverse-import closure from source, and runs leanchecker + axiom_audit + ADR-011 binding on the trusted surface. No quorum of attestations, however large, gates promotion in this spec — peers gate only a pre-promotion lane (§7). An attestation that gated a promotion is a soundness defect, not an optimisation. Lowering the central re-check below p = 1 for promotion is not specified here: it would amend ADR-049’s p = 1 invariant and requires its own ADR + SPEC.

Rationale specific to unsorry: accepted proofs become imported dependencies (ADR-009/010), so a falsely-promoted proof cannot be cleanly rolled back — promotion must be prevention, and prevention is the deterministic gate. Attestations provide detection, offload, scaling, and credit, not finality.

3. Attestation record (schema)

A validator publishes one record per (proof, validator) into the audit log (Git/AISP, ADR-003), e.g. attestations/<proof_sha>.<validator_id>.aisp:

attest≜{
  proof_sha≜<sha256 of the candidate's library module(s)>;   # what was checked, byte-exact (ADR-048)
  goal_id≜<id>; commit≜<git sha>;
  verdict≜valid | invalid;
  checker≜leanchecker | lean4export; checker_ver≜<hash>;
  toolchain≜<lean-toolchain hash>; mathlib≜<release tag>;     # reproducibility context (ADR-002)
  validator≜<registered id>;                                  # ADR-054 identity
  assigned_by≜<dispatcher id | self>; independent≜true|false; # false if validator == calculator
  ts≜<iso8601>; deadline_met≜true|false;
  sig≜<ed25519 over the canonical-serialised fields above>    # ADR-054 key
}

An attestation is recorded iff: the signature verifies against a registered validator key; proof_sha/commit/goal_id reference a real pending candidate; toolchain/mathlib are present; and ts is within the assignment deadline. Recording is not acceptance of the verdict — it is an auditable claim. validator≜ becomes a first-class provenance field alongside solver≜/agent≜/provider≜, surfaced as a validator dimension on the leaderboard.

Note (normative): none of these fields prove execution — they are predictable for a deterministic public computation (§5). They bind the claim to an identity and a context so it is auditable and slashable; honest execution is enforced by §5, not by the schema.

4. Credit and penalty

Distinct from calculator credit. On the trusted outcome (central re-check or resolved challenge) for a proof a validator attested:

Event Effect
correct attestation (verdict matches trusted outcome), in deadline, independent base credit
correctly flagged an invalid that others passed bonus credit (the behaviour we most want)
false acceptvalid but trusted outcome is invalid false attestation → penalty (§6)
false rejectinvalid but trusted outcome is valid (suppresses a good proof) false attestation → penalty (§6)
missed deadline / no-show on assignment timeout_count++ (reputation drag, no credit)
valid on a known-invalid honeypot false accept → penalty (§5)
invalid on a known-valid honeypot false reject → penalty (§5)

Credit is never granted for agreeing with the majority per se — only for matching the trusted outcome. This removes the rubber-stamp incentive in both directions: a validator is scored the same whether it rubber-stamps “valid” or lazily/maliciously stamps “invalid”. A peer rejection therefore is not a free action — the rejected candidate still reaches a trusted outcome via the appeal/sample lane (§7), so a false reject is caught and penalised exactly like a false accept.

5. Honeypot discipline (anti-rubber-stamping — normative)

Proof-of-execution is unattainable for deterministic public computation (ADR-103): a node can emit a correct §3 record without running anything. The defence is statistical.

6. Reputation and penalty (ADR-054 substrate)

Per-validator signals: correct_attestations, false_attestation_count, timeout_count, dispute_success_rate.

7. Promotion rule (phased — mirrors ADR-103)

8. Conformance (defined for the eventual implementation)

9. Phasing (contract milestones)

  1. M1 — schema + identity + audit log: signed attestations recorded in Git/AISP, validator≜ provenance, leaderboard dimension. Measured-only; central gate unchanged. (Phase 1.)
  2. M2 — honeypots + reputation: injection, detection, scoring, penalties; standing thresholds. (Phase 1→2.)
  3. M3 — pre-promotion quorum lane + challenge window: central re-check stays p = 1 at promotion. (Phase 2.)
  4. M4 — cheaper/portable p = 1 promotion gate (e.g. lean4export); sampling the promotion gate (p < 1) is deferred to a separate ADR amending ADR-049. (Phase 3.)

10. Out of scope (each its own decision)