|
| 1 | +# Specl Examples |
| 2 | + |
| 3 | +## Directory Structure |
| 4 | + |
| 5 | +| Directory | Description | |
| 6 | +|-----------|-------------| |
| 7 | +| `easy/` | Beginner specs — small state spaces, simple invariants, learn the language | |
| 8 | +| `realistic/` | Mid-complexity protocols — real algorithms with parameterized exploration | |
| 9 | +| `benchmark/` | Production protocols — complex models translated from TLA+ literature | |
| 10 | +| `semaphores/` | Classic concurrency — mutual exclusion, producer-consumer, barriers | |
| 11 | + |
| 12 | +The `benchmarks/` directory at the repo root contains TLC comparison scripts (`.tla`, `.cfg`, `.sh`) for performance benchmarking against TLC — it has no `.specl` files. |
| 13 | + |
| 14 | +## Showcase |
| 15 | + |
| 16 | +The following specs are the best examples for learning, demonstrating, and stress-testing Specl. Each has been reviewed for protocol faithfulness, invariant coverage, and checkability. |
| 17 | + |
| 18 | +### Consensus & Distributed Protocols |
| 19 | + |
| 20 | +| Spec | Protocol | Check Command | States | Time | |
| 21 | +|------|----------|---------------|--------|------| |
| 22 | +| [Paxos](benchmark/02-paxos/paxos.specl) | Single-decree Paxos (Synod) | `specl check paxos.specl -c N=2 -c MaxBallot=2 -c V=1 --no-deadlock` | 11.6K | <1s | |
| 23 | +| [Raft](benchmark/17-raft-vanlightly/raft.specl) | Raft consensus (async, faithful) | `specl check raft.specl -c N=1 -c MaxVal=0 -c MaxElections=2 -c MaxRestarts=0 -c MaxLogLen=2 --no-deadlock` | ~500K | ~5s | |
| 24 | +| [CometBFT](benchmark/09-comet/comet.specl) | Tendermint BFT with Byzantine faults | `specl check comet.specl -c N=3 -c MaxRound=0 -c V=1 -c F=1 --no-deadlock` | 59.5K | <2s | |
| 25 | +| [Simplex](realistic/simplex/simplex.specl) | Simplex consensus (TCC 2023) | `specl check simplex.specl -c N=2 -c MaxIter=2 -c V=1 --no-deadlock` | 277K | ~3s | |
| 26 | +| [Narwhal-Tusk](realistic/narwhal_tusk.specl) | DAG-based BFT consensus | *not yet checkable (Set[Seq] types)* | — | — | |
| 27 | + |
| 28 | +### Transactions & Replication |
| 29 | + |
| 30 | +| Spec | Protocol | Check Command | States | Time | |
| 31 | +|------|----------|---------------|--------|------| |
| 32 | +| [Percolator](benchmark/14-percolator/percolator.specl) | Google Percolator (snapshot isolation) | `specl check percolator.specl -c C=1 -c K=1 -c MaxTs=4 --no-deadlock` | 3.3K | <1s | |
| 33 | +| [Two-Phase Commit](realistic/TwoPhaseCommit.specl) | 2PC transaction coordinator | `specl check TwoPhaseCommit.specl -c MAX_RM=2 --no-deadlock` | ~1K | <1s | |
| 34 | + |
| 35 | +### Hardware & Cache Coherence |
| 36 | + |
| 37 | +| Spec | Protocol | Check Command | States | Time | |
| 38 | +|------|----------|---------------|--------|------| |
| 39 | +| [MESI](benchmark/11-mesi/mesi.specl) | MESI cache coherence | `specl check mesi.specl -c C=2 -c V=1 --no-deadlock` | 144 | <1s | |
| 40 | + |
| 41 | +### Distributed Algorithms |
| 42 | + |
| 43 | +| Spec | Protocol | Check Command | States | Time | |
| 44 | +|------|----------|---------------|--------|------| |
| 45 | +| [Chandy-Lamport](realistic/chandy-lamport/chandy-lamport.specl) | Consistent snapshot algorithm | `specl check chandy-lamport.specl -c N=2 -c MaxMsgs=2 --no-deadlock` | ~5K | <1s | |
| 46 | +| [SWIM](realistic/swim/swim.specl) | Failure detection protocol | `specl check swim.specl -c N=3 -c K=1 -c MaxRound=4 --no-deadlock` | varies | <2s | |
| 47 | + |
| 48 | +### Bug-Finding Demonstrations |
| 49 | + |
| 50 | +| Spec | Protocol | Check Command | Bug Found | |
| 51 | +|------|----------|---------------|-----------| |
| 52 | +| [Redlock](benchmark/05-redlock/redlock.specl) | Redis distributed lock (Kleppmann attack) | `specl check redlock.specl -c N=2 -c M=1 -c TTL=3 -c MaxTime=8` | MutualExclusion violated in 15 steps | |
| 53 | +| [SWIM](realistic/swim/swim.specl) | SWIM accuracy limitation | `specl check swim.specl -c N=3 -c K=1 -c MaxRound=4 --no-deadlock` | AccuracySafety violated in 7 steps | |
| 54 | + |
| 55 | +## Showcase Details |
| 56 | + |
| 57 | +### Paxos — Single-Decree Consensus |
| 58 | + |
| 59 | +Lamport's foundational consensus algorithm. The `SafeAt` function captures the core safety argument: a value is safe at ballot `b` if a quorum has promised `b` and either no one voted below `b`, or the highest vote below `b` was for the same value. Uses `powerset()` for quorum enumeration. 2 invariants: Agreement (two majority-accepted ballots propose the same value) and Validity. |
| 60 | + |
| 61 | +### Raft — Async Consensus with Log Replication |
| 62 | + |
| 63 | +Translated from [Vanlightly's model-checking-optimized TLA+ spec](https://github.com/Vanlightly/raft-tlaplus). Models full async message passing with explicit message sets (request vote, append entries, responses). Covers elections, log replication, commit advancement, term stepping, and server restarts. 2 key invariants: NoLogDivergence (committed entries agree across servers) and LeaderHasAllAckedValues. Note: the simpler `benchmark/01-raft/` is a shared-memory simplification — use this one for faithful Raft verification. |
| 64 | + |
| 65 | +### CometBFT — Byzantine Fault Tolerant Consensus |
| 66 | + |
| 67 | +Models the Tendermint/CometBFT protocol with explicit Byzantine behavior (faulty validators can prevote, precommit, and propose arbitrarily). Correctly implements the locking mechanism: a validator prevotes for a proposal only if unlocked, locked on the same value, or a proof-of-lock exists (quorum prevotes in an earlier round). 1 invariant: Agreement (no two honest validators decide different values). |
| 68 | + |
| 69 | +### Simplex — Modern Crash-Fault Consensus |
| 70 | + |
| 71 | +From Chan & Pass (TCC 2023). Models the crash-fault variant with chain-linking (leaders must re-propose values from earlier real blocks), dummy block voting on timeout, and quorum-based finalization. 2 invariants: FinalizationSafety (pigeonhole argument from the paper) and Agreement. |
| 72 | + |
| 73 | +### Percolator — Distributed Transactions |
| 74 | + |
| 75 | +Based on PingCAP's TLA+ formalization of Google's Percolator protocol. Models the full 2-phase commit with snapshot isolation: start timestamp allocation, primary/secondary prewriting, commit, abort, and 4 variants of stale lock cleanup. 4 invariants: WriteConsistency, LockConsistency, AbortedConsistency, and SnapshotIsolation. |
| 76 | + |
| 77 | +### MESI — Cache Coherence |
| 78 | + |
| 79 | +Models the MESI protocol (Papamarcos & Patel, ISCA 1984) with atomic bus transactions. Covers all state transitions: reads from Invalid (with M-holder flush, E-holder downgrade, S-sharing, or exclusive load), writes (BusRdX from Invalid, BusUpgr from Shared, silent upgrade from Exclusive), and evictions. 4 invariants: SWMR, ExclusiveExclusive, SharedMatchesMemory, ExclusiveMatchesMemory. |
| 80 | + |
| 81 | +### Redlock — Distributed Lock Bug Finding |
| 82 | + |
| 83 | +Models Redis Redlock with Kleppmann's attack scenario. The key bug: validity checking uses the client's local clock (which can lag behind real time due to GC pauses or network delays) rather than the global clock. The model checker finds a 15-step counterexample where locks expire in real time but a paused client still believes it holds the lock. |
| 84 | + |
| 85 | +### SWIM — Failure Detection Tradeoffs |
| 86 | + |
| 87 | +Models the SWIM protocol with direct and indirect pinging. The `DirectTimeout` action can fire for alive targets (modeling network non-determinism), which means the protocol can falsely suspect alive nodes. The checker finds this accuracy violation in 7 steps, demonstrating SWIM's fundamental accuracy-completeness tradeoff. 3 invariants including a safety encoding of bounded completeness. |
| 88 | + |
| 89 | +### Narwhal-Tusk — DAG-Based BFT Consensus |
| 90 | + |
| 91 | +Models the Narwhal/Tusk protocol (Danezis et al., 2022) that separates data availability from consensus ordering. Narwhal constructs a DAG of certificates with quorum signatures; Tusk orders the DAG using a deterministic leader commit rule. 6 invariants: SignaturesValid, DAGValidity, NoEquivocation, CommitAgreement, CommittedHaveQuorum, CausalConsistency. Currently not checkable (uses `Set[Seq[Int]]` types) — serves as a design reference. |
| 92 | + |
| 93 | +### Chandy-Lamport — Consistent Snapshots |
| 94 | + |
| 95 | +Models the consistent snapshot algorithm on a token-passing ring. Process 0 initiates by recording its state and sending markers on outgoing channels. Non-initiators record their state upon receiving the first marker. The initiator records channel messages between sending and receiving its own marker. 2 invariants: ConsistentSnapshot (exactly 1 token captured) and NoPhantomMessages. |
| 96 | + |
| 97 | +## Scaling Guide |
| 98 | + |
| 99 | +State spaces grow exponentially with constants. Start small: |
| 100 | + |
| 101 | +| Constant increase | Typical state space growth | |
| 102 | +|-------------------|---------------------------| |
| 103 | +| N: 2 → 3 | 10-100x | |
| 104 | +| N: 3 → 4 | 100-1000x | |
| 105 | +| MaxRound/MaxBallot: +1 | 5-50x | |
| 106 | +| Values: +1 | 2-10x | |
| 107 | + |
| 108 | +For large configurations, use `--fast` (fingerprint-only, 10x less memory) or `--por` (partial order reduction for independent actions). For specs with unbounded types, use `--smart` (symbolic checking). |
| 109 | + |
| 110 | +**Note on types:** Many showcase specs use `Dict[Int, ...]` which the type checker considers unbounded. The tool auto-selects symbolic checking (`--smart`) for these. Specs with bounded types like `Dict[0..N, ...]` (e.g., Two-Phase Commit) can use BFS directly. The Narwhal-Tusk spec uses `Set[Seq[Int]]` which neither BFS nor symbolic currently supports — it serves as a design reference pending future type support. |
0 commit comments