LeanGuard (Design)
Trace-certificate methodology, canonicalization, and deterministic replay.
LeanGuard follows a “trace certificate” methodology:
- the simulator emits a per-transition event trace (CSV), one row per state-machine transition
- the checker canonicalizes the trace and replays an executable Lean reference model
- the checker returns
ACCEPTif every row is a legal step, otherwiseREJECTwith the first violating row
This narrows the trusted computing base: you do not need to verify the simulator runtime, scheduler, or concurrency model—only that the logged transitions are consistent with the spec-first reference semantics.
Core pipeline
At a high level, each checker is:
- Parse CSV → a typed
Rowlist (reject malformed rows). - Canonicalize rows to a deterministic total order.
- Replay: fold a partial
stepfunction over the canonicalized list. - Report:
ACCEPTorREJECT: ...with the first failing row and a diagnostic.
Canonicalization is part of the specification: logs can be emitted by concurrently simulated components, and physical file order is not treated as semantically meaningful.
In Days’ current checkers, the canonical key is (time_ns, event_id) and duplicates are rejected.
Event vocabulary and replay-oriented schemas
To make replay deterministic, a trace row should contain:
- when and where:
time_nsplus stable identities (endpoint, flow, switch/port if applicable) - what happened: an event kind aligned with the protocol’s transition structure (send/receive/timer/decision)
- guards and parameters: enough information to evaluate gates/thresholds and enforce parameter stability
- post-state snapshot: the state variables updated by that transition, logged in deterministic encodings
Days logs key quantities as integers with explicit units (e.g., time_ns, rates in *_bps, and fixed-point factors like *_ppb) so the checker can compare by exact equality.
How this maps to the Days repository
- Lean code lives in
lean/LeanGuard/. - Each protocol has:
- a
*EventLog.leanthat definesRow, parsing, canonical key, andstep - a
*/Semantics.leanfile that defines executable update equations and helper invariants - a small
*Main.leanCLI entrypoint that printsACCEPT/REJECT
- a
The current executables are defined in lean/lakefile.lean:
dcqcn_check(DCQCN trace replay)pfc_check(PFC trace replay)cubic_check(TCP CUBIC trace replay)drr_check(DRR trace replay)wfq_check(WFQ trace replay)
On the simulator side, Days emits:
dcqcn_events.csvwhen built with--features dcqcn,leanpfc_events.csvwhen built with--features l2_pfc,leancubic_events.csvwhen built with--features leandrr_events.csvwhen built with--features leanwfq_events.csvwhen built with--features lean
Extending LeanGuard to a new protocol
The recommended instantiation recipe is:
- Choose an event vocabulary that matches the protocol’s transition points.
- Define a replay-oriented CSV schema (one row per transition).
- Add Days instrumentation at the transition points, logging post-state snapshots and stable IDs.
- Implement a Lean
Rowparser + canonical key +stepfunction that:- enforces required fields per kind
- enforces parameter stability (where intended)
- checks pairing rules and gates (cooldowns / eligibility windows)
- recomputes the post-state and compares it to the logged snapshot
- Add a
lean_exeentry inlean/lakefile.leanand a CLI wrapper that printsACCEPT/REJECT.