Q10 — Specification Anatomy Reference

Constants, Variables & Actions

The concrete building blocks of REF's TLA+ specifications. What parameters are fixed, what state TLC explores, and what transitions define the protocol's behavior — sourced directly from the verified artifacts.

Consensus Spec
REFConsensus v1.9 (EV-008)
Token Spec
TokenLifecycle (EV-009)
Consensus Actions
8 Honest + 3 Byzantine (11 total action families in Next)
Token Actions
4 (+ 1 negative test)
Structural Frame
In TLA+, a specification has three elements: Constants (fixed parameters), Variables (mutable state TLC explores), and Actions (guarded state transitions). Together they define every possible behavior of the system.
01 — Constants

Fixed Parameters per Model-Checking Run

Constants define the boundaries of the state space TLC explores. They are fixed before each run — different values produce different verification scopes.

REFConsensus v1.9

Validators
SET of model values
The validator set of the model. Honest validators can execute the honest action families in Next; Byzantine validators can execute the Byzantine action families. The canonical v1.9 model has no explicit network/message-delay layer.
{v1, v2, v3, v4}
Byzantine
SUBSET of Validators
Validators controlled by the adversary. May propose conflicting values and may vote for any existing proposal, including conflicting proposals; the executable Byzantine vote actions remain bounded by existing proposal records.
{v4}
Values
SET of model values
Abstract proposals that validators agree on. Two values ensure the model tests conflicting proposals.
{val1, val2}
MaxHeight
Nat
Maximum blockchain height to explore. Bounds the state space to keep TLC tractable.
1
MaxView
Nat
Maximum view (round) per height. MaxView=0 means view changes are not exercised in this harness.
0
NIL
Model value
Sentinel value representing "no decision yet" or "no locked value." Used in per-validator state maps.
NIL
EV-008 TLC Configuration (actual values used in verification)
Validators{v1, v2, v3, v4}
Byzantine{v4}
Values{val1, val2}
MaxHeight1
MaxView0
States generated152,658,351
Distinct states17,588,825
Depth31
Time11m 06s

TokenLifecycle

Purchases
SET of model values
Finite set of purchase identifiers. Two purchases test cross-purchase isolation.
{p1, p2}
Nullifiers
SET of model values
Available nullifier identifiers. Three nullifiers (2 tokens + 1 spare) test uniqueness and collision attempts.
{n1, n2, n3}
Contents
SET of model values
Abstract review content values. Two distinct contents test review uniqueness per token.
{c1, c2}
EV-009 TLC Configuration (actual values used in verification)
Purchases{p1, p2}
Nullifiers{n1, n2, n3}
Contents{c1, c2}
CHECK_DEADLOCKFALSE (quiescence is correct behavior)
States generated269
Distinct states148
Depth7

Mechanism Design (Monte Carlo Parameters)

α (alpha)
Float — cost scaling exponent
Controls how fast attack costs grow per additional fake review. Higher α = steeper exponential cost curve.
[0.037 – 0.205]
C₀ (base cost)
Float — dollars
Baseline cost of a single attestation forgery. Includes bond escrow, validator fees, and platform integration costs.
[549 – 39,125]
γ (gamma)
Float — network exponent
How much the validator network amplifies attack difficulty. Network effects make fraud harder as N grows.
[1.77 – 2.90]
N
Integer — network size
Total validators in the network. Larger N strengthens security via the Nγ term in the cost function.
[1,041 – 19,969]
k
Float — reward curvature
Controls diminishing returns on fake reviews. R(v) = k·ln(1+v). The dominance condition requires α·C₀·Nγ > k.
[42,645 – 1,374,630]
02 — Variables

Mutable State TLC Explores

Variables define the state space. TLC exhaustively explores every reachable combination of variable values, checking invariants at each state.

REFConsensus v1.9 — 10 State Variables

Variable
Type
Purpose
height
[Validators -> 0..MaxHeight]
Current blockchain height per validator
view
[Validators -> 0..MaxView]
Current view (round) within the current height
decision
[Validators -> Values \cup {NIL}]
Transient per-validator decision state. Canonical Agreement is instead quantified over honest records in decided at equal height; NoConflictingDecisions is the separate transient-state predicate and is not selected by the EV-008 cfg.
lockedValue
[Validators -> Values \cup {NIL}]
Per-validator lock value set by Lock. CanVoteFor permits the locked value unless a strictly higher highestQC governs the vote.
lockedView
[Validators -> -1..MaxView]
The view at which lockedValue was set. -1 = not yet locked.
highestQC
[Validators -> [view: -1..MaxView, value: Values \cup {NIL}]]
Per-validator highest QC record. CanVoteFor reads highestQC; Lock and ReceiveQC update it; ViewChange preserves it unchanged.
prepareVotes
SUBSET [validator: Validators, h: 0..MaxHeight, v: 0..MaxView, val: Values]
Modeled set of PREPARE vote records. The v1.9 state machine does not model an explicit network/message-delay layer; matching distinct-validator records can satisfy HasPrepareQuorum.
commitVotes
SUBSET [validator: Validators, h: 0..MaxHeight, v: 0..MaxView, val: Values]
Modeled set of COMMIT vote records. A matching commit quorum enables Decide when its other guards hold.
decided
SUBSET [validator: Validators, h: 0..MaxHeight, val: Values]
Monotonic set of decision-history records. Canonical Agreement compares records whose validators are in Honest and whose heights are equal.
proposals
SUBSET [proposer: Validators, h: 0..MaxHeight, v: 0..MaxView, val: Values]
Proposal registry used by phase-separated Propose/Prepare/Byzantine actions.

TokenLifecycle — 4 State Variables

Variable
Type
Purpose
purchases
SUBSET Purchases
Set of registered purchase identifiers. Grows monotonically.
tokens
SUBSET TokenRec
Set of issued token records, each binding a registered purchase to a nullifier and a lifecycle status. One-token-per-purchase is enforced by TokensForPurchase(p) = {}.
reviews
SUBSET ReviewRec
Set of published review records, each bound to a token.
nullifierSet
SUBSET Nullifiers
Set of spent nullifiers. Append-only. Membership prevents double-spend.
03 — Actions

State Transitions — The Next Relation

Every action has a guard (precondition) and an effect (state mutation). TLC fires all enabled actions nondeterministically at each state, building the complete reachable state graph. Click any action to expand its guard and effect.

REFConsensus v1.9 — Honest Actions

Propose(v) Proposal
Guard (precondition)

v ∈ Honest
height[v] < MaxHeight
view[v] <= MaxView
decision[v] = NIL
∃ val ∈ Values
CanVoteFor(v, val)
Let HProps be the honest proposals at height[v]/view[v]: HProps = {} OR ∃ p ∈ HProps with p.val = val
No proposal already exists from v at height[v]/view[v]

Changed state

proposals' = proposals ∪ {[proposer ↦ v, h ↦ height[v], v ↦ view[v], val ↦ val]}
UNCHANGED: height, view, lockedValue, lockedView, decision, prepareVotes, commitVotes, highestQC, decided

Present in Next; canonical source is authoritative for the exact guard and UNCHANGED set.
Prepare(v) Prepare
Guard

v ∈ Honest
height[v] < MaxHeight
view[v] <= MaxView
decision[v] = NIL
HonestHasNotVoted(v, prepareVotes)
∃ p ∈ proposals with p.h = height[v] and p.v = view[v]
CanVoteFor(v, p.val)

Changed state

prepareVotes' adds [validator ↦ v, h ↦ p.h, v ↦ p.v, val ↦ p.val]
UNCHANGED: height, view, lockedValue, lockedView, decision, commitVotes, highestQC, decided, proposals

Lock(v) Lock
Guard

v ∈ Honest
height[v] < MaxHeight
view[v] <= MaxView
decision[v] = NIL
∃ val ∈ Values with HasPrepareQuorum(height[v], view[v], val)
view[v] > lockedView[v]

Changed state

lockedValue[v] ← val
lockedView[v] ← view[v]
highestQC[v] ← [view ↦ view[v], value ↦ val]
UNCHANGED: height, view, decision, prepareVotes, commitVotes, decided, proposals

Lock state constrains later honest voting through CanVoteFor; a strictly higher highestQC can override an older lock.
Commit(v) Commit
Guard

v ∈ Honest
height[v] < MaxHeight
view[v] <= MaxView
decision[v] = NIL
∃ val ∈ Values with HasPrepareQuorum(height[v], view[v], val)
lockedValue[v] = val
lockedView[v] = view[v]
HonestHasNotVoted(v, commitVotes)

Changed state

commitVotes' adds [validator ↦ v, h ↦ height[v], v ↦ view[v], val ↦ val]
UNCHANGED: height, view, lockedValue, lockedView, decision, prepareVotes, highestQC, decided, proposals

Decide(v) Decide
Guard

v ∈ Honest
height[v] < MaxHeight
decision[v] = NIL
∃ val ∈ Values with HasCommitQuorum(height[v], view[v], val)

Changed state

decision[v] ← val
decided' adds [validator ↦ v, h ↦ height[v], val ↦ val]
UNCHANGED: height, view, lockedValue, lockedView, prepareVotes, commitVotes, highestQC, proposals

The decided history is monotonic; AdvanceHeight is a separate action.
AdvanceHeight(v) Height
Guard

v ∈ Honest
decision[v] ≠ NIL
height[v] < MaxHeight

Changed state

height[v] ← height[v] + 1
view[v] ← 0; decision[v] ← NIL; lockedValue[v] ← NIL; lockedView[v] ← -1; highestQC[v] ← [view ↦ -1, value ↦ NIL]
UNCHANGED: prepareVotes, commitVotes, decided, proposals

ViewChange(v) View Change
Guard

v ∈ Honest
view[v] < MaxView
decision[v] = NIL

Changed state

view[v] ← view[v] + 1
UNCHANGED: height, lockedValue, lockedView, decision, prepareVotes, commitVotes, highestQC, decided, proposals

EV-008 golden coverage: 0 executions because MaxView=0.
ReceiveQC(v) QC Propagation
Guard

v ∈ Honest
∃ other ∈ Validators
other ≠ v
height[other] = height[v]
highestQC[other].view > highestQC[v].view

Changed state

highestQC[v] ← highestQC[other]
UNCHANGED: height, view, lockedValue, lockedView, decision, prepareVotes, commitVotes, decided, proposals

EV-008 final coverage record: 83,394 executions / 9,327,900 evaluations.

REFConsensus v1.9 — Byzantine Actions

These actions model adversarial behavior. The Byzantine validator (v4) can equivocate, vote for conflicting values, and attempt to break safety. The invariants must hold despite these actions firing.

ByzPropose Byzantine
Guard

validator ∈ Byzantine
∃ h ∈ 0..MaxHeight, vw ∈ 0..MaxView, val ∈ Values
Let prop = [proposer ↦ validator, h ↦ h, v ↦ vw, val ↦ val]
prop ∉ proposals

Changed state

proposals' = proposals ∪ {prop}
UNCHANGED: height, view, lockedValue, lockedView, decision, prepareVotes, commitVotes, highestQC, decided

TLC executions: 251,966
ByzPrepare Byzantine
Guard

validator ∈ Byzantine
∃ p ∈ proposals
Let vote = [validator ↦ validator, h ↦ p.h, v ↦ p.v, val ↦ p.val]
vote ∉ prepareVotes

Changed state

prepareVotes' = prepareVotes ∪ {vote}
UNCHANGED: height, view, lockedValue, lockedView, decision, commitVotes, highestQC, decided, proposals

TLC executions: 1,901,481
ByzCommit Byzantine
Guard

validator ∈ Byzantine
∃ p ∈ proposals
Let vote = [validator ↦ validator, h ↦ p.h, v ↦ p.v, val ↦ p.val]
vote ∉ commitVotes

Changed state

commitVotes' = commitVotes ∪ {vote}
UNCHANGED: height, view, lockedValue, lockedView, decision, prepareVotes, highestQC, decided, proposals

TLC executions: 12,863,638

TokenLifecycle — Actions

CreatePurchase Lifecycle
Guard

p ∈ Purchases
p ∉ purchases (not already registered)

Effect

purchases' = purchases ∪ {p}
UNCHANGED: tokens, reviews, nullifierSet

IssueToken Lifecycle
Guard

p ∈ purchases
TokensForPurchase(p) = {}
n ∈ Nullifiers
n ∉ NullifiersInUse

Effect

tokens' = tokens ∪ {[purchase ↦ p, status ↦ "valid", nullifier ↦ n]}
UNCHANGED: purchases, reviews, nullifierSet

SubmitReview Lifecycle
Guard

t ∈ tokens
t.status = "valid"
c ∈ Contents
ReviewsForToken(t) = {}
t.nullifier ∉ nullifierSet

Effect

reviews' = reviews ∪ {[token ↦ t, content ↦ c]}
nullifierSet' = nullifierSet ∪ {t.nullifier}
UNCHANGED: purchases, tokens

Model transition: review added and nullifier added; the token record is unchanged.
RevokeToken Lifecycle
Guard

t ∈ tokens
t.status = "valid"
ReviewsForToken(t) = {}
t.nullifier ∉ nullifierSet

Effect

tokens' = (tokens \ {t}) ∪ {[purchase ↦ t.purchase, status ↦ "revoked", nullifier ↦ t.nullifier]}
UNCHANGED: purchases, reviews, nullifierSet

Handles ATK-10 (Refund Cycling) — token revoked on refund before review
04 — The Next-State Relation

How TLC Builds the State Graph

The Next relation is the disjunction of all actions. At every state, TLC fires every enabled action, exploring all possible interleavings.

REFConsensus_v1.9.tla
\* Action-family membership from REFConsensus_v1.9.tla; canonical source is authoritative Next == v Validators : \/ Propose(v) \/ Prepare(v) \/ Lock(v) \/ Commit(v) \/ Decide(v) \/ AdvanceHeight(v) \/ ViewChange(v) \/ ReceiveQC(v) \/ ByzPropose(v) \/ ByzPrepare(v) \/ ByzCommit(v) Spec == Init /\ [][Next]_vars
TokenLifecycle.tla
\* Next-state relation: token lifecycle transitions Next == \/ p Purchases: CreatePurchase(p) \/ p Purchases, n Nullifiers: IssueToken(p, n) \/ p Purchases, c Contents: SubmitReview(p, c) \/ p Purchases: RevokeToken(p) Spec == Init /\ [][Next]_vars
ViewChange Is Present but Dormant in EV-008

The exact v1.9 action is ViewChange; there is no AdvanceView action in v1.9. The EV-008 harness sets MaxView=0, so the golden log records zero ViewChange executions. ReceiveQC is present and was exercised, but EV-008 still does not exercise distinct-view safety behavior.

05 — EV-008 / v1.9 Source Status

Current Bound Specification and Checked Scope

This section uses only the bound canonical REFConsensus_v1.9.tla, EV-008 cfg, and EV-008 golden log. It makes no predecessor-version or introduction/delta claim.

Aspect
Bound v1.9 / EV-008 status
Source boundary
State variables
10: height, view, lockedValue, lockedView, decision, prepareVotes, commitVotes, highestQC, decided, proposals
REFConsensus_v1.9.tla VARIABLES / vars
Next action families
11: Propose, Prepare, Lock, Commit, Decide, AdvanceHeight, ViewChange, ReceiveQC, ByzPropose, ByzPrepare, ByzCommit
REFConsensus_v1.9.tla Next
Honest / Byzantine capability
Honest action guards require validator \in Honest; Byzantine actions are separately guarded by validator \in Byzantine.
No explicit network/message-delay/partial-synchrony/timeout state is modeled.
EV-008 cfg-selected invariants
Agreement, LockedValueSafety, UniqueHonestProposalPerRound, PrepareVotesReferenceProposals
Exactly the four names under INVARIANTS in the bound cfg.
Defined but not EV-008 cfg-selected
TypeOK, NoConflictingDecisions, NoConflictingPrepareQCs, NoConflictingCommitsAtHeight
Defined in canonical v1.9; not listed under the bound cfg INVARIANTS.
EV-008 TLC result
152,658,351 states generated; 17,588,825 distinct states; model checking completed with no error.
Bound golden log. Bounded model-checking result only.
ViewChange / ReceiveQC coverage
ViewChange: 0 executions at MaxView=0. ReceiveQC: 83,394 final recorded executions.
Cross-view safety is not established by this EV-008 run.
Traceability

Bound current evidence: evidence/REFConsensus_v1.9.tla, evidence/REFConsensus_v1.9_bft_tiny.cfg, and evidence/tlc_bft_tiny_COMPLETE.log. Historical predecessor comparisons are not verification evidence.