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 accept — valid but trusted outcome is invalid false attestation → penalty (§6)
false reject — invalid 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)