Asymptote Fault Tolerance (AFT)
A self-contained consensus and settlement yellowpaper for guardian-backed base finality, proof-carrying canonical ordering, sealed effects, and embedded formal artifacts.
Abstract
Asymptote Fault Tolerance (AFT) is a family of consensus and settlement constructions for high-throughput ordering, guardian-backed base finality, proof-carrying canonical ordering, and deterministic release of irreversible effects. Its central move is to stop treating dense positive voting as the only possible source of ordering truth. Instead, AFT separates throughput-critical publication and chain progression from authority-critical proof verification, omission detection, and effect collapse.
The protocol family has four interacting surfaces. GuardianMajority
supplies the production base-finality path: a validator quorum certificate is
necessary but not sufficient, because each proposal must also carry a
registered guardian committee certificate anchored into shared evidence.
CanonicalOrdering supplies the proof-carrying ordering path: a slot
order is accepted because a canonical certificate is uniquely valid and
recoverable from public inputs, not because a dense validator quorum voted the
order into existence. Asymptote supplies the sealing path for
irreversible effects: BaseFinal chain progress is upgraded to
SealedFinal through deterministic witness or observer-backed collapse,
with canonical observer challenges dominating unsafe releases.
NestedGuardian supplies a
witness-augmented mode for layered threshold constructions.
This paper is self-contained and normative for the protocol family. Its
ordering subtheorem remains 99% equal-authority ordering consensus
under explicit bulletin-publication, cutoff, omission, protocol-native
retrievability, and proof-soundness assumptions. The runtime also
internalizes compact signed publication-frontier metadata on the hot path:
positive committed blocks carry a predecessor-linked frontier summary and
compact availability-receipt binding, while same-slot conflicts or stale parent
links admit short objective contradiction objects. Those frontier objects bind
the claimed bulletin / ordering surface, while the protocol-native
retrievability plane internalizes deterministic extraction-or-abort on the
cold path. The repository's theorem surface is
singular: AFT is relay-free, coordinator-free, pure-software deterministic 99% Byzantine Tolerance. For each closed slot boundary there
exists at most one admissible public execution object, every conflicting fully
specified candidate admits a short public contradiction witness, durable state
advances only through canonical collapse, and sealed-effect release is bound
to the same collapse surface. Compact bindings stay on the hot path while
cold-path recovery / reveal / reconstruction re-materialize the same close,
abort, collapse, replay-prefix, execution-restart, and restart-ancestry
surfaces through the AFT-native recovery-family contract, with restart able to
stream recovered certified ancestry until target height or recovered-history
exhaustion without a theorem-relevant fixed depth bound. Ordinary canonical
collapse / replay history and the AFT recovered-state contract also carry
the historical-retrievability bootstrap surface used for deeper paging, so
recovered history is ordinary endogenous AFT history rather than a theorem-side
qualifier. Across the full promoted AFT theorem surface, the classical
$n > 3f$ / $f < n/3$ threshold is no longer load-bearing. The paper
therefore explicitly claims that AFT universally breaks the classical lower
bound with no external qualifiers, and is relay-free, coordinator-free,
pure-software deterministic 99% Byzantine Tolerance. It is therefore
also a formal and direct claim of unconditional classical 99% Byzantine agreement in the ordinary permissioned setting. Here "ordinary permissioned
setting" means fixed authenticated authorities, deterministic local
verification, public hash-addressed protocol objects, epoch-scoped identity
state, and eventual-fair delivery and persistence of admissible protocol
artifacts, with no trusted relay, no privileged coordinator, no TEE, no
theorem-side bootstrap oracle, and no hidden external recovery service.
AFT does not weaken the
agreement sentence; it changes the safety carrier. The proof-carrying public-
evidence architecture, endogenous historical retrievability, and collapse-
gated durability are the protocol-internal realizing mechanism of that same
classical sentence, not a residual qualifier. Here "no external qualifiers"
excludes hidden helpers: no trusted relay, no privileged coordinator, no TEE,
no theorem-side bootstrap oracle, and no hidden external recovery service. It
does not mean that the paper's explicit system model evaporates. Once the
bulletin / publication-frontier / retrievability / recovery /
historical-continuation machinery named above is fixed as protocol state, no
extra trusted relay, coordinator, or theorem-side bootstrap service remains
hiding behind the classical sentence. Calling those endogenous protocol objects
"qualifiers" merely because they are not dense yes-votes is a category
error. Those objects are
protocol-defined, hash-addressed,
publicly checkable, and governed by the same objective publication and
liveness assumptions as the rest of AFT. Unlike classical partially synchronous Byzantine
agreement, which is usually presented through dense positive quorum
intersection and $> 2/3$ honest-participation thresholds, AFT derives
safety without trusted relays, privileged
coordinators, TEEs, or dense positive quorum intersection. Safety comes from
proof-carrying public evidence, dominant negative proofs, compact signed
frontier consistency, explicit endogenous retrievability of the closed slot
surface, and collapse-gated durability; accountable publication and validator
removal remain operational reinforcement, not the source of correctness. In
that precise sense, the classical $n > 3f$ / $f < n/3$ barrier is no
longer load-bearing for the promoted durable-agreement theorem.
Scope and Status
This paper contains the full architectural and theorem-level description of the instantiated AFT family. It does not require any companion prose specification to be understood.
The instantiated protocol surfaces are:
GuardianMajorityas the production guardian-backed base-finality mode.Asymptoteas the two-tier sealing and irreversible-effects mode.CanonicalOrderingthrough the liveCommittedSurfaceV1certificate path plus compactPublicationFrontiersummaries attached to committed blocks.NestedGuardianas an experimental witness-augmented operational mode with safety proofs, bounded operational checks, and a finished composed-liveness / classical-agreement bridge rather than a remaining composed-liveness kernel.
Implementation correspondence is included below as exact symbol references. That section is non-normative. The protocol and theorem content of the paper stands on its own.
The strongest theorem surface of the runtime is singular.
AFT claims not only 99% equal-authority ordering for the ordering
layer, but relay-free, coordinator-free, pure-software deterministic
99% Byzantine Tolerance for durable ordering and sealed-effect safety,
with public-state continuity as its protocol-internal safety carrier rather
than dense positive quorum intersection. Compact hot-path
bindings plus cold-path recovery / reveal / reconstruction materialize the
same recovered close-or-abort, collapse, replay-prefix, execution-restart,
and streamed restart-ancestry surfaces through the AFT-native recovery-family
contract. Compact publication/frontier metadata is internalized on the live
path throughout, and deeper recovered history is now ordinary endogenous AFT
history through the canonical-collapse / replay retrievability anchor and the
matching recovered-state historical retrievability surface.
Interpretive doctrine: same theorem, different carrier. AFT does not weaken the agreement sentence; it changes the safety carrier. The promoted theorem surface is the same classical agreement sentence, realized through proof-carrying public evidence, endogenous retrievability, canonical collapse, and collapse-gated durability rather than dense positive quorum intersection. Terminology discipline. Throughout this paper, "unconditional", "universally", and "no external qualifiers" are used extensionally rather than rhetorically. Once the explicit AFT system model is fixed, all theorem-carrying machinery - bulletin close, publication frontier, retrievability, recovery, restart continuity, canonical collapse, and collapse-bound sealing - is endogenous protocol state rather than a helper regime. The substantive objection is therefore not whether AFT "changes the model"; every agreement theorem is model-relative. The substantive objection would be the existence of a hidden relay, privileged coordinator, TEE, bootstrap oracle, or external recovery service. AFT has none. Calling endogenous protocol objects "qualifiers" merely because they are not dense yes-votes is a category error.
Scope precision is not a concession. A criticism that AFT is "permissioned only" is non-responsive because the promoted claim is a permissioned Byzantine-agreement theorem over fixed authenticated authorities and epoch-scoped identity state, carried by one explicit eventual-fair public-state substrate under which repeated honest reissuance makes protocol-defined artifacts delivered, persisted, and content-hash fetchable across live, recovery, archival, and restart lanes alike. Replacing that domain with open-membership consensus is a target switch, not a rebuttal, and relabeling that substrate as "just partial synchrony" does not answer the paper unless a stronger hidden cold-path synchrony assumption is identified. That substrate is not a theorem-side escape hatch, and the public-evidence continuity machinery is not an external qualifier; both are endogenous protocol state. Accordingly, the observation that AFT "changes the safety carrier" is not an objection but the paper's central theorem move: the same promoted classical agreement sentence is realized through proof-carrying public evidence, omission dominance, canonical collapse, and collapse-bound durability rather than dense quorum intersection. A criticism that merely renames that carrier without identifying a hidden relay, privileged coordinator, TEE, bootstrap oracle, external recovery service, or proof gap is non-responsive.
Singular theorem sentence.
The theorem surface of this repository is now singular all the way up:
AFT claims relay-free, coordinator-free, pure-software deterministic
99% Byzantine Tolerance, explicitly claims it universally breaks the
classical lower bound with no external qualifiers, and claims unconditional
classical 99% Byzantine agreement in the ordinary permissioned
setting. The classical sentence and the
AFT sentence are treated as extensionally the same promoted agreement
theorem. AFT does not weaken that sentence; it changes the safety carrier.
Proof-carrying
public evidence, endogenous historical retrievability, restart continuity, and
collapse-gated durability are the realizing architecture of that claim, not a
remaining semantic delta.
No hidden helper regime sits underneath that promotion: "no
external qualifiers" means no trusted relay, no privileged coordinator, no
TEE, no theorem-side bootstrap oracle, and no hidden external recovery
service. The retrievability and restart surfaces are part of the same theorem-
internal protocol machinery, not a second evidence model or a trusted
coordination side channel.
Claim ladder.
The full promoted claim should be read as a constructed ladder:
- each closed slot boundary admits at most one admissible public execution object and every conflicting fully specified candidate admits a short objective obstruction witness,
- durable state advances only through canonical collapse on that same close-or-abort surface,
- irreversible effects release only through that same collapse surface.
| Dimension | AFT realizing surface | Promoted singular claim |
|---|---|---|
| Agreement object | canonical close-or-abort / canonical collapse surface | ordinary classical agreement object with no architecture-specific restatement |
| Safety carrier | compact commitments, short contradiction objects, cold-path recovery, endogenous historical retrievability | unconditional classical agreement sentence with no separate evidence-model caveat |
| History / bootstrap | canonical-collapse / replay historical retrievability root plus recovered-state historical retrievability surface | no semantic distinction between AFT retrievability history and ordinary agreement history |
| Liveness burden | composed recurrence/reduction/totality/collapse chain plus persistent churn simulator | one completed classical-agreement-style theorem surface under the target adversary model |
Target adversary/scheduler model and discharged liveness kernel.
The singular theorem is interpreted under one explicit liveness model rather than a vague aspiration. Byzantine authorities may equivocate, omit, reorder, withhold reveals, withhold historical-retrievability objects, rotate maliciously, and crash/restart arbitrarily. Before stabilization the scheduler may delay or interleave publication, registry, recovery, archival, and restart traffic arbitrarily. After stabilization the scheduler is assumed only to be eventually fair for the AFT public-state substrate: if an honest participant keeps reissuing an admissible object that the protocol depends on, at least one copy is eventually delivered, persisted, and fetchable by content hash, and governing profile/activation churn quiesces into bounded windows long enough for progress to compose. Under that model, the liveness bridge is the conjunction of five obligations: frontier-generation progress, canonical-resolution progress, recovery-completion progress, restart/historical-retrievability re-entry progress, and infinite composition of those four obligations across reassignment, outage, profile rotation, and archival page boundaries. That kernel is no longer open; it is the discharged bridge that supports the promoted singular classical-agreement sentence. No stronger synchrony assumption is smuggled in for recovery, archival paging, or restart. Those lanes are required to progress on that same eventual-fair public-state substrate: repeated honest reissuance must eventually make one admissible copy delivered, persisted, and fetchable by content hash whether the object is a live frontier, a recovery-family artifact, or a historical- continuation page.
The relevant liveness fact is not that AFT declines to claim a fully asynchronous theorem; the relevant fact is that it states one explicit eventual-fair public-state substrate and uses that same substrate uniformly across live ordering, recovery, archival paging, and restart. Calling this "just partial synchrony" conceals the actual burden discharged here: the protocol does not require universal timely receipt, but only eventual delivery, persistence, and hash-fetchability of repeatedly reissued admissible public artifacts on the same theorem-carrying substrate.
Current artifact map and completion status.
That kernel is now grounded in concrete repository artifacts rather than prose
alone. Frontier-generation progress lands on the live
PublicationFrontier path and its contradiction objects;
canonical-resolution progress lands on canonical-order certificates,
CanonicalCollapseObject, omission dominance, and recursive continuity;
recovery-completion progress lands on the coded recovery-family contract and
the recovered publication / close-or-abort surface; and
restart/historical-retrievability progress lands on the AFT recovered-state
surface plus canonical-history retrievability anchors and bounded-memory paging.
Those obligations now have both concrete runtime carriers and a completed
formal bridge. The formal package contains bounded churn witnesses, recurring
cycle cores, a recurrence theorem, a finite reduction, a total classical-
agreement history bridge, and a directly discharged semantic-collapse wrapper
ending in NestedGuardianRecoveryClassicalAgreementCollapse.tla. The
exact source of that recurrence / reduction / totality / collapse bridge is
embedded in Appendix Embedded Formal Artifacts, including the final
wrapper in Appendix NestedGuardianRecoveryClassicalAgreementCollapse.tla.
The recurrence / reduction / totality / collapse chain is not narrative glue.
Its exact artifact chain is embedded verbatim in
Appendix Embedded Formal Artifacts, ending in the classical-agreement
collapse wrapper itself.
The runtime mirrors the same story through a persistent historical-retrievability
churn/restart simulator over one evolving recovered-history state. The
remaining work is therefore no longer theorem completion, but cleanup, stress
expansion, and maintenance of the promoted singular claim.
Problem Statement
Classical permissioned Byzantine fault tolerance ties deterministic safety to dense positive voting by a large honest majority. Under that model, honest inclusion, total-order agreement, and finality all depend on most validators remaining both correct and available. That is the right model when the protocol is allowed to pay dense coordination cost and accept classical $3f+1$-style thresholds. It is the wrong model for a system that wants all of the following simultaneously:
- high-throughput publication and chain progression,
- equal-authority participation at the validator layer,
- deterministic rejection of incomplete or conflicting ordered views,
- stronger accountability than "someone must have voted wrong,"
- deterministic gating of irreversible effects.
AFT therefore changes the object of agreement.
Instead of asking:
- "Which order did the validator quorum choose?"
it asks:
- "Which order certificate is uniquely valid for this slot, and which effects are admissible after deterministic collapse?"
The family-level design goals are:
- keep ordering and publication sparse on the hot path,
- keep effect release fail-closed,
- make omissions and conflicts objectively provable,
- keep all validators equally eligible to reveal the canonical order,
- move authority from dense yes-votes to verifiable evidence.
Thought Experiment: The Port of Public Manifests and Release Seals
Imagine an international port that handles ordinary cargo and hazardous cargo.
Every ship that wants to unload during tide $h$ must post its cargo manifest to a public harbor board before the closing bell $\tau_h$. The bell is not a private clock in the harbor master's office. It is a certified public event. Once the bell rings, the harbor office takes every admissible manifest, applies the published tide lottery $R_h$, and derives one canonical docking docket $O_h$.
The office does not ask every captain to vote on the exact order of every container. It asks a simpler question: has someone produced the one valid docket certificate for the manifests that were publicly posted before the bell? If any dockworker can prove that an admissible manifest was omitted from the announced docket, that docket is rejected immediately.
Ordinary unloading may begin once the berth assignment is base-final. Hazardous cargo is stricter. It may leave the port only after one of two things happens:
- the required independent inspector guilds each sign a release certificate, or
- a deterministically assigned set of external captains publishes a public inspection transcript surface, the public red-flag board remains empty through the close bell, and the port issues the unique release docket implied by that surface.
Any valid red flag aborts release. The cargo does not "probably" leave the port. It does not leave.
Most of the port can be chaotic. Captains can lie, stall, or collude. What they cannot do is create a second valid docket for the same tide or a second valid hazardous-cargo release order, provided the public manifest board remains recoverable and the decisive proof surface stays objectively checkable.
[[aft-figure:port-manifests]]
The correspondence is direct:
| Port object | AFT object |
|---|---|
| Public manifest board | Bulletin / DA surface $B_h$ |
| Certified closing bell | Canonical cutoff $\tau_h$ |
| Tide lottery | Public randomness beacon $R_h$ |
| Docking docket | Canonical order $O_h$ |
| Docket certificate | Canonical-order certificate $OCert_h$ |
| Omitted manifest challenge | Omission proof $\Omega(h, tx)$ |
| Base berth assignment | BaseFinal |
| Independent inspector guilds | Witness committees |
| Sampled external captains | Equal-authority observers |
| Red-flag report | Canonical observer challenge |
| Hazardous cargo release seal | SealObject under SealedFinal |
This thought experiment captures the essential AFT move: sparse operational progress, dense cheap verification, objective omission, and deterministic collapse for irreversible consequences.
Protocol Family Overview
AFT is best understood as four planes that compose:
| Plane | Purpose | Throughput-critical work | Authority object |
|---|---|---|---|
| Dissemination / bulletin plane | Publish the candidate transaction surface | Data dissemination and bulletin commitments | Public bulletin commitment |
| Base-finality plane | Advance the chain and commit block identity | Proposal, QC formation, guardianized certification | Validator QC + guardian certificate |
| Canonical-ordering plane | Prove the unique slot order | Succinct verification, omission dominance | $OCert_h$ |
| Sealed-effect plane | Gate irreversible effects | Asynchronous witness / observer evidence collection | SealedFinalityProof and SealObject |
The protocol modes are:
| Mode | Role | Current status |
|---|---|---|
GuardianMajority |
Production guardian-backed base finality | Production mode |
CanonicalOrdering |
Proof-carrying equal-authority ordering | Live through CommittedSurfaceV1 |
Asymptote |
Two-tier sealing and sealed-effect release | Production sealing path |
NestedGuardian |
Witness-augmented layered threshold mode | Experimental operational mode / completed theorem bridge |
The key invariant is:
$$
\text{throughput-critical work} \neq \text{authority-critical work}
$$
[[aft-figure:protocol-planes]]
System Model and Notation
Actors
- Validator: participates in proposal, vote, verification, and chain execution.
- Guardian committee: the registered threshold-signing committee protecting one validator's proposal decisions.
- Guardian member: an individual signer within a guardian committee.
- Witness committee: an external threshold-signing committee used
on the sealing path or in
NestedGuardian. - Equal-authority observer: a validator sampled to audit a slot
under
Asymptote. - Registry: the on-chain source of truth for manifests, policies, epochs, witness sets, and verifier descriptors.
- Transparency log: an append-only checkpointed evidence log for guardian and witness statements.
- External verifier or gateway: a party that checks
SealObjects and enforces replay-safe release.
Bulletin-board time and slot model
Consensus proceeds in heights and views. A slot is identified by $(height, view)$. Epoch-scoped policy and committee state bind the admissible evidence for that slot. The family should be read under a bulletin-board recoverability model rather than a pure point-to-point timely receipt model: safety depends on whether admissible evidence becomes publicly retrievable by the slot cutoff, not on whether every participant receives every message before that cutoff.
Slots are externally paced by a public cutoff object $\tau_h$ and a public randomness beacon $R_h$. Honest validators that observe the same closed public boundary derive the same ordering or sealing close-or-abort result. In the runtime that derivation is no longer keyed off cutoff closure alone: the bulletin plane exports a canonical bulletin-close object binding the bulletin commitment, the bulletin-availability certificate, and the canonical cutoff into one public close surface. In this instantiation, positive canonical-order publication is fail-closed at this boundary: a closed-slot order certificate is admitted only if the published bulletin entries deterministically extract the bulletin surface bound by the canonical bulletin-close object and the carried bulletin-availability certificate. Universal timely receipt is not required.
Let
$$
h = \text{slot height}, \quad v = \text{slot view},
$$
$$
B_h = \text{bulletin surface admitted before cutoff }\tau_h,
$$
$$
R_h = \text{public randomness beacon for slot }h,
$$
$$
E_h = {tx ;|; \mathrm{Included}(tx, B_h) \wedge \mathrm{Eligible}(tx, root_{h-1})},
$$
$$
O_h = \mathrm{CanonicalOrder}(R_h, E_h),
$$
$$
root_h = \mathrm{Execute}(root_{h-1}, O_h).
$$
Core assumptions
The family-level safety claims rely on the following explicit assumptions:
- Objective publication: admitted bulletin entries, transcripts, and challenges have stable hashes and objective inclusion paths.
- Verifiable bulletin availability: the protocol exports a bulletin-availability object, compact publication-frontier metadata that binds the same slot surface, and a canonical bulletin-close object for each closed ordering slot; the remaining assumption is that the underlying publication substrate satisfies the retrieval semantics claimed by those objects. The live runtime also requires successful closed-slot extraction before positive canonical-order admission.
- Compact frontier consistency: any carried
PublicationFrontiermust bind the same-slot bulletin commitment, ordered surface, and compact availability receipt, and same-slot conflicts or stale predecessor links must admit short objective contradiction objects. These frontier objects summarize the slot surface; they do not reconstruct it. - Objective validity only: theorem-critical rejection or acceptance does not depend on private local facts.
- Public derivability over universal receipt: honest validators that observe the same closed public boundary derive the same close-or-abort result; universal timely receipt is not required.
- Independent publication path: suppressing negative evidence requires capture of both the validator plane and the publication / registry surface.
- Sealed-effect gating: irreversible effects are released only after surviving the canonical close-or-abort surface.
- Fixed epoch identities: the validator set is epoch-scoped and stable while the accountable rules of that epoch are enforced.
Here and throughout, "ordinary permissioned setting" means fixed authenticated authorities, deterministic local verification, public hash-addressed protocol objects, epoch-scoped identity state, and eventual- fair delivery and persistence of admissible protocol artifacts, with no trusted relay, privileged coordinator, TEE, theorem-side bootstrap oracle, or hidden external recovery service. Fixed authenticated membership is part of the theorem statement, not a missing crutch. The hidden-helper exclusions are relay, coordinator, TEE, bootstrap oracle, and external recovery service - not epoch-scoped authenticated identity itself.
Evidence objects
The family-level evidence objects are:
- validator quorum certificates over block proposals,
- guardian quorum certificates over slot decisions,
- witness certificates over guardianized slots,
- canonical-order certificates over bulletin surfaces,
- omission proofs over ordered-set incompleteness,
- observer transcripts, observer challenges, and canonical close-or-abort objects over sealed finality,
- sealed-effect proof objects with replay-safe nullifiers.
All honest nodes are required to derive the same acceptance result from the same admissible evidence set.
Accountable publication rules
Objective AFT faults are not merely audit artifacts. In the runtime they are first-class accountable protocol objects:
OmissionProofnames the validator accountable for the dominated positive order object.AsymptoteObserverChallengedetermines accountability by kind:MissingTranscriptandConflictingTranscriptblame the assigned observer;TranscriptMismatch,VetoTranscriptPresent, andInvalidCanonicalCloseblame the producer / positive-close path.- Valid objective fault evidence is replay-deduplicated on chain.
- Policy-controlled membership updates are aftermath only: the same evidence may trigger best-effort immediate quarantine and stage next-epoch eviction, but the decisive negative object remains valid even when those membership updates are disabled, delayed, or skipped.
These rules do not change the hot path. They strengthen the adversary model: arbitrary behavior is tolerated only insofar as it remains publicly revealable and penalty-bearing.
Public State Continuity with Extractable Obstructions
AFT's deeper theorem target is not a new round gadget. It is a new source of uniqueness. Classical Byzantine agreement derives uniqueness from overlap of dense positive quorums. AFT instead seeks a rigidity theorem over public slot objects: once the slot boundary is closed, the space of admissible public continuations should collapse to one canonical object or one canonical abort.
Boundary-conditioned execution language
For a closed slot boundary define
$$
\partial_h := (root_{h-1}, \beta_h, \tau_h, R_h, p_h),
$$
where $\beta_h$ is the canonical bulletin-close object binding the bulletin commitment, bulletin-availability certificate, and canonical cutoff whose recoverable surface is $B_h$; $\tau_h$ is the canonical cutoff object; $R_h$ is the slot randomness beacon; and $p_h$ is the policy descriptor governing admissible checks for slot $h$.
Let a public execution object for slot $h$ be a normalized public codeword
$$
X_h := (B_h, E_h, O_h, root_h, \sigma_h),
$$
where $E_h$ is the eligible subset, $O_h$ is the canonical ordered object, $root_h$ is the resulting state commitment, and $\sigma_h$ is the slot-local sealing surface needed to determine whether the slot closes or aborts. The important point is that $X_h$ is not a distributed transcript. It is the public quotient of the slot after irrelevant schedule variation is factored out.
Define the boundary-conditioned language
$$
\mathcal{L}(\partial_h) := {X ;|; \exists \pi ; \mathrm{Accept}(\partial_h, X, \pi)=1 }.
$$
Here $\pi$ is a succinct admissibility witness. For canonical ordering, $\pi$ is the proof-carrying order certificate witness. For deterministic observer sealing, $\pi$ is the witness that the canonical transcript surface, challenge surface, and close-or-abort object satisfy the slot policy.
Obstruction extractability
The companion rejection relation is
$$
\mathrm{Reject}(\partial_h, Y, \omega)=1,
$$
where $Y$ is a fully specified candidate public execution object and $\omega$ is a short public objective contradiction witness.
AFT seeks obstruction-complete local testability: for a fixed closed boundary, every fully specified candidate lies in exactly one of two states,
$$
\Big(\exists \pi ; \mathrm{Accept}(\partial_h, Y, \pi)=1\Big) ;\oplus; \Big(\exists \omega ; \mathrm{Reject}(\partial_h, Y, \omega)=1\Big).
$$
This xor formulation is the software-only analogue of state continuity. It is stronger than merely having a valid proof system. It says every non-admissible candidate exposes a short public contradiction witness.
In the live repository, the obstruction basis is not abstract:
- ordering uses a first-class canonical abort taxonomy over the canonical bulletin surface: missing certificates, bulletin-surface reconstruction failures, bulletin-surface mismatches, invalid bulletin-close formation, omission-dominated candidates, certificate-height mismatches, randomness mismatches, ordered-transactions-root mismatches, resulting-state-root mismatches, invalid public-input bindings, invalid bulletin-availability bindings, and invalid proof bindings,
- deterministic observer sealing uses objective challenge kinds over the canonical transcript and challenge surface,
- the accountable-adversary layer turns those same objects into penalty-bearing public fault evidence.
Unique collapse object
The slot should not merely admit at most one positive object. It should admit at most one collapse object:
$$
\mathrm{Collapse}(\partial_h) \in {\mathrm{Close}(X_h), \mathrm{Abort}(\Omega_h)}.
$$
Here $\mathrm{Close}(X_h)$ denotes the unique admissible positive object when the obstruction surface is empty, while $\mathrm{Abort}(\Omega_h)$ denotes the unique negative object induced by a non-empty valid obstruction surface. Negative evidence does not create a second truth. It forces the slot to land on its canonical abort object instead of a close object.
In the runtime this collapse object is not merely an abstract proof
target. Validator finalization publishes a first-class
CanonicalCollapseObject through guardian_registry, and later
consensus verification cross-checks any published copy against the same
proof-carried ordering and sealing surface when parent-state data is available.
In the current recursive-continuity slice, CanonicalCollapseObject
also carries a rolling previous_canonical_collapse_commitment_hash, and in the
current clean-break runtime slice it also carries
continuity_accumulator_hash together with
continuity_recursive_proof, so the current slot's collapse object is
linked to the previously persisted or published collapse object rather than
standing as an isolated per-slot fact. The newest proposal-surface slice
pushes that same predecessor link into the signed header itself:
BlockHeader now carries
previous_canonical_collapse_commitment_hash in
its signed preimage and also carries a typed
CanonicalCollapseExtensionCertificate. That certificate now carries the
predecessor commitment plus the predecessor recursive-proof hash, while the
public predecessor CanonicalCollapseObject now carries only a single
recursive proof step rather than a carried predecessor-proof tree. Each
recursive proof step still binds a predecessor collapse commitment,
predecessor commitment hash, predecessor payload hash, and previous proof
hash; the rolling
continuity_accumulator_hash remains in place as the companion
accumulator over the same chain. The implementation surface
distinguishes the reference HashPcdV1 carrier from a backend slot
SuccinctSp1V1, and the runtime exposes a dedicated continuity-verifier
seam for those recursive public inputs via ioi-api and
zk-driver-succinct. That seam is now wired into the live protocol:
GuardianMajority invokes it while validating proposal and QC continuity
for carried or anchored SuccinctSp1V1 proof steps, and validator
durable-state checks invoke the same backend before a persisted
CanonicalCollapseObject is treated as authoritative. Proposal verification checks that the carried
predecessor commitment hash matches the signed predecessor link, checks that
the predecessor commitment's resulting state root matches the signed parent-state root, and
checks that the carried predecessor proof hash matches the anchored
predecessor collapse object already persisted or published in protocol state.
Leaders in
Asymptote stall rather than propose when the required extension
certificate or anchored predecessor collapse object is unavailable, proposal
verification rechecks that implied predecessor commitment against both the
signed predecessor commitment link and the parent-state root, checks the
carried predecessor proof hash against the anchored predecessor proof on the
public collapse object, and QC progression only treats continuity-linked headers as
progress-authoritative.
Theorem: Public State Continuity with Extractable Obstructions.
Assume a closed boundary $\partial_h$, objective publication, a protocol-native retrievability plane, compact publication-frontier consistency, objective validity only, and proof soundness. Then the instantiated and normative theorem shape for AFT is:
- $\mathcal{L}(\partial_h)$ contains at most one admissible public execution object,
- every fully specified candidate $Y \notin \mathcal{L}(\partial_h)$ admits a short public objective obstruction witness $\omega$ such that $\mathrm{Reject}(\partial_h, Y, \omega)=1$,
- therefore the slot admits at most one admissible collapse object, either the unique close object or the unique abort object.
This theorem is the precise form of the software-only continuity primitive that the instantiated AFT runtime realizes. The later ordering, collapse, recovery, restart, and sealed-effect sections are concrete theorem instances and composition layers of this same continuity statement, not separate aspirations. It does not claim that the classical DLS / PBFT frontier disappeared inside the standard dense-vote model. The point is different: the uniqueness source has moved from quorum overlap into the public-evidence language itself. In the instantiated runtime, compact publication frontiers internalize same-slot and predecessor consistency inside the live protocol, while the protocol-native retrievability plane discharges closed-bulletin extraction-or-abort on the cold path.
Lemma program
The clean proof path is a filtration rather than a single opaque argument:
$$
\mathcal{L}_0(\partial_h) \supseteq \mathcal{L}_1(\partial_h) \supseteq \cdots \supseteq \mathcal{L}_k(\partial_h),
$$
where each refinement adds one structural constraint and each failed refinement admits a short witness.
The repository's theorem program is:
- Boundary Fixing Lemma. The closed boundary fixes the admissible publication domain.
- Bulletin Close Lemma. The canonical bulletin-close object fixes the unique recoverable bulletin surface for the slot.
- Eligibility Determinism Lemma. The predecessor commitment and boundary fix the eligible subset.
- Order Determinism Lemma. The boundary and eligible subset fix the canonical ordered object.
- Transition Determinism Lemma. The ordered object fixes the next state commitment.
- Collapse Exclusivity Lemma. A slot cannot admit both a canonical close object and a canonical abort object.
- Obstruction Soundness Lemma. Every valid omission proof or observer challenge objectively rejects its target candidate.
- Obstruction Completeness Lemma. Every invalid fully specified candidate contains at least one minimal public obstruction witness.
- Extractor Sufficiency Lemma. Given the canonical bulletin-close object, any honest validator can run the protocol-defined bulletin extractor to reconstruct the same bulletin surface; in this instantiation, admission of the positive ordering object already requires this extraction to succeed over the published closed-slot surface. One honest validator remains sufficient to surface the resulting positive or negative object under the instantiated runtime model.
One honest validator is surfacing-sufficient but never trust-bearing: correctness does not attach to the revealer's identity, because any honest validator observing the same closed boundary derives the same decisive object.
The theorem surfaces of this paper are instances of that program:
CanonicalOrderinginstantiates unique admissibility and extractable obstruction through proof-carrying order certificates plus omission dominance.Asymptoteinstantiates unique collapse through canonical transcript/challenge surfaces plus close-or-abort exclusivity.
The AFT Deterministic Base Engine
AFT modes share a deterministic core engine for proposal flow, QC formation, locking, and view progression.
Deterministic leadership and view progression
For a given height and view, the implementation selects the proposer by deterministic round-robin over the active validator set:
$$
\mathrm{leader}(h, v) = V_h[(h - 1 + v) \bmod |V_h|].
$$
Here $V_h$ is the active validator set for height $h$ after operational quarantine filters are applied.
View $0$ proposals do not carry a timeout certificate. Any non-zero view proposal must carry a valid timeout certificate for the previous unsuccessful view. The pacemaker advances views monotonically and resets timers on observed progress.
Validator quorum certificates
In GuardianMajority, Asymptote, and NestedGuardian,
validator quorum is a strict simple majority of active validator weight, not a
classical $2/3 + 1$ quorum:
$$
\mathrm{QCQuorum}(V_h) > \frac{1}{2}\mathrm{Weight}(V_h).
$$
This is safe only because the validator quorum is not the sole authority object. A proposal must also satisfy guardian-layer admissibility.
Timeout certificates use the same simple-majority rule over view-change votes.
Locking, 2-chain commit, and divergence guard
Validators maintain a lock on the highest safe parent QC they have observed. A validator votes only when the proposal extends the lock or is in a strictly higher view than the lock.
Base commitment uses a 2-chain rule:
- let $QC_{parent}$ certify parent block $P$,
- let $QC_{child}$ certify child block $C$,
- if $C$ directly extends $P$ and the views are consecutive, then $P$ becomes a pending commit.
The implementation delays final durability by a guard window $\Delta_{guard}$ before a pending commit is released. The purpose of the guard window is operational, not purely algebraic: it gives divergence evidence or panic signals time to propagate before a conflicting branch is treated as durable.
This produces a fail-closed operational behavior:
- sparse chain progress happens on the hot path,
- conflicting evidence is surfaced before irreversible consequences,
- divergence proofs quarantine the affected node rather than silently allowing fork continuation.
GuardianMajority: Production Base Finality
GuardianMajority is the production fault model for AFT base finality.
Validator votes alone never make a proposal admissible. Every valid proposal
must also carry a guardian committee certificate that verifies against current
registered committee state.
Guardian certificate object
The guardian certificate binds:
- the guardian committee manifest hash,
- the active epoch,
- the canonical decision hash for the slot payload,
- a monotonic guardian counter,
- a guardian trace root,
- a measurement root,
- the signer bitfield,
- the aggregated BLS signature,
- a transparency-log checkpoint,
- and, in
NestedGuardian, an optional experimental witness certificate.
The guardian decision payload is slot-scoped. Honest guardians are assumed not to sign two different decisions for the same slot.
Verification rule
A guardianized proposal is admissible only if all of the following hold:
- the referenced guardian committee manifest is registered on-chain for the active epoch,
- the certificate manifest hash matches the registered manifest,
- the certificate epoch matches the manifest epoch and current epoch,
- the decision hash matches the slot's canonical guardian decision payload,
- the measurement root matches the decision payload,
- the signer set is valid, unique, and meets the committee threshold,
- the aggregated signature verifies against the manifest public keys,
- the attached transparency-log checkpoint verifies against the anchored log descriptor and append-only proof.
The transparency log is an accountability layer. It does not replace threshold safety. It makes issued decisions, checkpoints, and later slashing evidence publicly checkable.
Committee threshold model
Let a guardian committee have threshold $t$ and size $n$. Conflicting slot certificates require enough equivocators to cover the minimum quorum intersection:
$$
f < 2t - n.
$$
Production committees therefore use strict majority thresholds:
$$
t = \left\lfloor \frac{n}{2} \right\rfloor + 1.
$$
This guarantees pairwise quorum intersection. It also exposes an important operational nuance:
- odd-sized simple-majority committees tolerate zero equivocating guardian members at the committee layer,
- even-sized majority committees tolerate one equivocator before threshold intersection is exhausted.
Production safety therefore relies on both threshold intersection and stronger guardian non-equivocation guarantees.
Safety statement
Proposition: GuardianMajority Safety.
No two conflicting blocks can both finalize for the same $(height, view)$ if guardian committee manifests are current, committee thresholds are majority thresholds, honest guardians do not equivocate for the same slot, transparency-log checkpoints and registry state are current enough to verify admissibility, and validators finalize only guardian-admissible blocks.
This is not a classical $3f + 1$ theorem. It is a composed threshold theorem over validators, guardians, registry state, and shared evidence. That statement is local to the guardian-backed base-finality layer. It does not delimit the paper's promoted theorem surface. The promoted durable-agreement claim is carried by the later proof-carrying close-or-abort and canonical- collapse architecture, which is precisely why the classical $3f + 1$ threshold is not load-bearing there.
Liveness model
Liveness is secondary to safety. Progress requires:
- enough active validators to form the simple-majority validator QC,
- enough guardian members to satisfy the committee threshold,
- current registry state for the epoch,
- current enough checkpoint and log availability.
If these degrade, the protocol prefers stalling over accepting unsafe evidence.
Canonical Ordering
CanonicalOrdering is the proof-carrying ordering path that gives
AFT its 99% equal-authority ordering consensus claim.
Objective
For each slot $h$, define a unique canonical ordered set $O_h$ and a certificate $OCert_h$ such that:
- every honest verifier can check $OCert_h$ cheaply,
- any omission is objectively provable,
- the ordered set is recoverable from public data,
- the live hot path carries a compact publication frontier that binds the same-slot bulletin / ordering / availability surface and predecessor continuity,
- conflicting valid certificates for the same slot are impossible,
- arbitrary behavior by almost all validators cannot create a conflicting valid ordering outcome because the closed bulletin boundary admits one deterministically derivable close-or-abort result.
Canonical objects
For slot $h$,
$$
B_h = \text{bulletin surface admitted before }\tau_h,
$$
$$
R_h = \text{public randomness beacon for slot }h,
$$
$$
E_h = {tx ;|; \mathrm{Included}(tx, B_h) \wedge \mathrm{Eligible}(tx, root_{h-1})},
$$
$$
O_h = \mathrm{CanonicalOrder}(R_h, E_h),
$$
$$
root_h = \mathrm{Execute}(root_{h-1}, O_h).
$$
The abstract certificate is
$$
OCert_h = \left( h, root_{h-1}, cutoff_h, bulletin_commitment_h, ordered_commitment_h, root_h, witness_h \right).
$$
Bulletin, cutoff, and admissibility assumptions
The ordering theorem is conditional on the following named assumptions.
A1. Objective publication.
Each admitted transaction or batch in $B_h$ has a stable content hash, a verifiable inclusion path into the bulletin commitment, and an objective publication time or publication position relative to the slot cutoff.
A2. Endogenous retrievability.
The bulletin contents committed by $bulletin_commitment_h$ are reconstructed or deterministically aborted from protocol-native retrievability objects rooted in the canonical bulletin close for slot $h$. Compact publication-frontier summaries and availability certificates bind that claim on the hot path, while retrievability profiles, shard manifests, custody assignments, custody receipts, custody responses, and objective challenge objects close the extraction-or-abort loop on the cold path. Without that plane, uniqueness may still hold while timely materialization of the same close-or-abort surface can fail.
A3. Append-only or equivocation-evident commitment.
The bulletin commitment and any carried publication frontier for slot $h$ must be append-only or otherwise make same-slot equivocation or stale predecessor linkage objectively detectable at the slot boundary.
A4. Eligibility determinism.
$\mathrm{Eligible}(tx, root_{h-1})$ is deterministic and locally checkable from the committed predecessor root and the transaction object. Honest validators therefore derive the same eligible set $E_h$ from the same public inputs.
A5. Proof soundness.
$\mathrm{VerifyProof}(witness_h) = \mathrm{true}$ implies that the witness obligations for cutoff binding, bulletin binding, ordering, state transition, retrievability commitments, and omission commitments actually hold.
The cutoff $\tau_h$ is not a private local clock read. It is a protocol-bound object. In the instantiated runtime, the cutoff is bound directly into the published bulletin commitment and into the canonical public-input set. Eligibility is deterministic with respect to the predecessor state root and the transaction object. This prevents local reinterpretation of the eligible set.
Current runtime instantiation
The runtime surfaces the abstract objects above as the following concrete objects:
| Runtime object | Current fields |
|---|---|
BulletinCommitment |
(height, cutoff_timestamp_ms, bulletin_root, entry_count) |
BulletinSurfaceEntry |
(height, tx_hash) |
BulletinAvailability / Certificate |
(height, bulletin_commitment_hash, recoverability_root) |
BulletinRetrievabilityProfile |
(height, bulletin_commitment_hash, / bulletin_availability_certificate_hash, recoverability_root, / shard_count, recovery_threshold, custody_threshold) |
BulletinShardManifest |
(height, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, recoverability_root, / entry_count, shard_count, recovery_threshold, shard_commitment_root) |
BulletinCustodyAssignment |
(height, bulletin_retrievability_profile_hash, / bulletin_shard_manifest_hash, validator_set_commitment_hash, / assignments) |
BulletinCustodyReceipt |
(height, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / custodian_count, custody_threshold, custody_root) |
BulletinCustodyResponse |
(height, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / bulletin_custody_assignment_hash, bulletin_custody_receipt_hash, / served_shards) |
BulletinRetrievabilityChallenge |
(height, kind, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / bulletin_custody_assignment_hash, bulletin_custody_receipt_hash, / bulletin_custody_response_hash, details) |
BulletinReconstructionCertificate |
(height, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / bulletin_custody_assignment_hash, bulletin_custody_receipt_hash, / bulletin_custody_response_hash, canonical_bulletin_close_hash, / canonical_order_certificate_hash, reconstructed_entry_count, / reconstructed_bulletin_root) |
BulletinReconstructionAbort |
(height, kind, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / bulletin_custody_receipt_hash, bulletin_retrievability_challenge_hash, / canonical_order_abort_hash, details) |
PublicationAvailabilityReceipt |
(height, bulletin_commitment_hash, / ordered_transactions_root_hash, resulting_state_root_hash, / receipt_root) |
PublicationFrontier |
(height, view, counter, parent_frontier_hash, / bulletin_commitment_hash, ordered_transactions_root_hash, / availability_receipt_hash) |
PublicationFrontierContradiction |
(height, kind, candidate_frontier, reference_frontier) |
CanonicalBulletin / Close |
(height, cutoff_timestamp_ms, bulletin_commitment_hash, / bulletin_availability_certificate_hash, / bulletin_retrievability_profile_hash, bulletin_shard_manifest_hash, / bulletin_custody_receipt_hash, entry_count) |
CanonicalOrder / PublicInputs |
(height, parent_state_root_hash, bulletin_commitment_hash, / randomness_beacon, ordered_transactions_root_hash, / resulting_state_root_hash, cutoff_timestamp_ms) |
CanonicalOrderProofSystem |
concrete variants HashBindingV1 and CommittedSurfaceV1 |
CommittedSurface / CanonicalOrderProof |
(recoverability_root, omission_commitment_root) |
CanonicalOrder / Certificate |
(height, bulletin_commitment, bulletin_availability_certificate, / randomness_beacon, ordered_transactions_root_hash, / resulting_state_root_hash, proof, omission_proofs) |
CanonicalOrder / PublicationBundle |
(bulletin_commitment, bulletin_entries, bulletin_availability_certificate, / bulletin_retrievability_profile, bulletin_shard_manifest, / bulletin_custody_receipt, canonical_order_certificate) |
CanonicalOrder / Abort |
(height, reason, details, bulletin_commitment_hash, / bulletin_availability_certificate_hash, bulletin_close_hash, / canonical_order_certificate_hash) |
HashBindingV1 is the reference verifier family: its proof bytes are a
canonical hash binding over the public-input hash. CommittedSurfaceV1
is the live proof family: its proof payload contains the recoverability root
and the omission-commitment root for the committed surface. In the current
runtime, positive ordering artifacts are published through the atomic
CanonicalOrderPublicationBundle, carrying the bound retrievability
profile / manifest / custody-receipt objects, while the registry
deterministically materializes the coupled custody-assignment and
custody-response objects over the same slot surface before admitting the
positive lane. Positive committed
blocks also carry a compact signed PublicationFrontier: it binds the
same-slot bulletin commitment, ordered-transactions root, and compact
publication-availability receipt, and it hash-links that summary to the
previous slot's frontier. Short PublicationFrontierContradiction
objects make same-slot conflict or stale predecessor linkage objectively
rejectable on the hot path. Those frontier objects internalize compact
publication consistency, but they do not replace the protocol-native
retrievability plane that reconstructs or aborts the full bulletin surface.
Validators also run a block-local derivation pass over
the committed block boundary: they derive either a
CanonicalOrderExecutionObject or a CanonicalOrderAbort, and
publish the abort artifact when the proof-carried positive object cannot be
derived. When the endogenous retrievability lane succeeds, the registry
materializes a first-class BulletinReconstructionCertificate bound to
the canonical close, canonical-order certificate, and the same retrievability
objects. When endogenous retrievability evidence dominates that same surface,
the registry also materializes a specialized
BulletinReconstructionAbort object bound to the challenge and the paired
CanonicalOrderAbort, so reconstruction-impossible failure is named as a
first-class protocol object rather than only as a generic ordering abort.
Acceptance rule
Every validator applies the same deterministic rule:
$$
\begin{aligned} \mathrm{Accept}(OCert_h) \iff;& \mathrm{VerifyProof}(witness_h) \ &\wedge \mathrm{VerifyCutoff}(cutoff_h) \ &\wedge \mathrm{PredecessorAccepted}(root_{h-1}) \ &\wedge \neg \exists tx : \mathrm{ValidOmission}(h, tx). \end{aligned}
$$
In the implementation this specializes to:
- the certificate height and bulletin height must match the block height,
- the randomness beacon must match the slot schedule,
- the bulletin commitment must match the published bulletin when that bulletin is available from anchored state,
- any carried
PublicationFrontiermust match the same-slot bulletin commitment, ordered-transactions root, and publication-availability receipt hash, - when a predecessor frontier exists, the carried
PublicationFrontiermust extend it by counter and parent hash, - no published
PublicationFrontierContradictionmay already dominate the slot, - positive canonical-order admission in the runtime additionally requires successful closed-slot extraction over the published bulletin entries, the carried bulletin-availability certificate, and the canonical bulletin-close object,
- the ordered-transactions root and resulting state root must match the block header,
- the proof must match the canonical public inputs,
- the recoverability root must match the certificate commitments,
- the omission-commitment root must match the omission-proof set.
If the omission-proof set is non-empty, the candidate certificate is rejected immediately.
No dense positive vote on the order is required once a valid $OCert_h$ is
surfaced. The current verifier entry point for this rule is
verify_canonical_order_certificate.
Omission dominance
An omission is objective when a transaction:
- was included in $B_h$ before $\tau_h$,
- was eligible under $root_{h-1}$,
- and is absent from the committed ordered set $O_h$.
Define the omission proof
$$
\Omega(h, tx) = \left( \begin{array}{l} inclusion_proof(tx, bulletin_h), \ cutoff_admissibility_proof(tx, cutoff_h), \ eligibility_proof(tx, root_{h-1}), \ nonmembership_proof(tx, O_h) \end{array} \right).
$$
Its semantics are:
$$
\mathrm{Valid}(\Omega(h, tx)) \Rightarrow \mathrm{Reject}(OCert_h).
$$
This is the central AFT ordering move. A candidate does not need to win a dense round of positive endorsements if any incomplete view can be killed objectively.
Omission dominance is a correctness rule, not a punishment rule. A valid omission proof kills the candidate immediately whether or not slashing, quarantine, or next-epoch removal ever fires.
Uniqueness, publication frontiers, and recoverability
Theorem: Uniqueness.
If $\mathrm{ValidOrderCert}(h, C_1)$ and $\mathrm{ValidOrderCert}(h, C_2)$, then $C_1$ and $C_2$ commit the same canonical ordered set $O_h$.
The reason is structural:
- the predecessor root is fixed,
- the cutoff object is canonical,
- the bulletin commitment is canonical,
- eligibility is deterministic,
- the ordering function is deterministic,
- proof soundness forbids a witness for a different ordered set.
The live publication-frontier slice sits between uniqueness and recoverability. A frontier gives a compact signed summary of the claimed bulletin / ordering surface and its predecessor link, so same-slot conflict or stale lineage is objectively rejectable without reconstructing the full bulletin on the hot path. But the frontier only binds hashes and receipt roots; it is not itself the recoverable bulletin surface.
Theorem: Endogenous Retrievability.
If $\mathrm{ValidOrderCert}(h, C)$ and the canonical bulletin close plus protocol-native retrievability plane for slot $h$ are present and unchallenged, then every honest verifier can reconstruct the same ordered set $O_h$ from protocol objects alone: the canonical close, bound frontier / availability commitments, retrievability profile, shard manifest, custody receipt, positive reconstruction certificate, and published bulletin entries.
Endogenous retrievability matters because the accepted order is not merely unique. The compact frontier tells validators which surface is being claimed; the retrievability plane tells them that the full surface can actually be reconstructed or objectively aborted from protocol evidence.
The hot path and the cold path do not carry different truths. The frontier binds the claimed surface compactly; the retrievability plane reconstructs or objectively aborts that same surface; both terminate on the same canonical close-or-abort object.
99% equal-authority ordering consensus
AFT's ordering claim is a proof-carrying consensus theorem whose decisive object is revealed rather than manufactured by dense positive yes-votes. Revelation is not a weaker post hoc reporting layer here; it is the equal- authority surfacing mechanism for the uniquely valid public execution object already fixed by the closed public boundary.
Theorem: 99% Equal-Authority Ordering Consensus.
Assume:
- the closed bulletin surface $B_h$ bound by the carried publication frontier and bulletin commitment is governed by a canonical bulletin close and protocol-native retrievability plane that deterministically yields extraction or abort,
- the cutoff object for slot $h$ is canonical,
- bulletin commitments, compact publication-frontier bindings, and omission proofs are objectively verifiable,
- same-slot frontier conflicts and stale predecessor links admit short objective contradiction objects,
- the proof system is sound.
Then even if $99%$ of validators behave arbitrarily, they cannot create a conflicting valid canonical-order outcome for slot $h$. More strongly, every honest validator that observes the same closed ordering boundary derives the same positive order object or omission-dominated abort.
Compact publication frontiers therefore internalize cheap same-slot and predecessor consistency checks on the live path, while recoverability remains the stronger assumption needed to turn that compact claim into a publicly reconstructable ordered set.
[[aft-figure:omission-dominance]]
The strongest shorthand is:
$$
99% \text{ of validators may behave arbitrarily,}
$$
$$
\text{because the closed ordering boundary admits one deterministically}
$$
$$
\text{derivable close-or-abort outcome.}
$$
This is equal-authority because any validator may reveal the winning
certificate. It is 99%-fault tolerant because correctness does not
depend on a dense majority of positive votes. This section isolates the
ordering lane, not the theorem ceiling. Once composed with endogenous
retrievability, canonical collapse, recovery and restart continuity, and
collapse-bound sealed-effect gating, the promoted AFT theorem surface is
exactly the paper's unconditional classical 99% Byzantine agreement
claim in the ordinary permissioned setting.
With the accountable publication rules of Section System Model and Notation, invalid positive ordering attempts are not only rejectable; they are also penalty-bearing and next-epoch removing.
Asymptote: Sealed Finality and Irreversible Effects
Asymptote is the two-tier settlement mode in the AFT family. It
preserves fast BaseFinal chain progression while requiring stronger
evidence before irreversible effects are released.
Finality tiers and collapse states
The finality tiers are:
BaseFinal: validator QC plus guardian certificate.SealedFinal:BaseFinalplus sufficient sealing evidence.
The slot collapse states are:
PendingBaseFinalSealingAbortSealedFinalEscalatedInvalid
All honest nodes must derive the same collapse state from the same admissible evidence set.
[[aft-figure:collapse-surface]]
SealedFinalityProof
The sealing plane gathers a proof object that binds:
- the epoch,
- the achieved finality tier,
- the collapse state,
- the guardian manifest hash,
- the guardian decision hash,
- the guardian counter,
- the guardian trace root,
- the guardian measurement root,
- the policy hash,
- witness certificates, when the witness path is used,
- observer transcripts, transcript commitment, observer challenges, challenge commitment, and exactly one canonical observer outcome object when the observer path is used,
- divergence signals gathered during sealing.
This object is block-scoped and guardian-bound. A SealedFinalityProof
that is not bound to the slot's guardian evidence is invalid.
Witness-backed sealing
The witness path assigns one witness committee per required certification stratum.
Witness assignment is deterministic over:
- the epoch seed,
- the producer account id,
- the slot $(height, view)$,
- the reassignment depth,
- the witness stratum id,
- the witness manifest hash.
Sealed finality is reached on the witness path when:
BaseFinalholds,- each required witness stratum contributes a valid assigned witness certificate,
- each witness certificate verifies against the registered witness manifest,
- required checkpoints and append-only proofs are current enough under policy.
Witness omission, stale registry participation, checkpoint inconsistency, or conflicting witness certificates produce explicit evidence rather than silent best-effort behavior.
Equal-authority observer sealing
The normative observer path is CanonicalChallengeV1. It treats sampled
validators as deterministic duty assignees whose outputs must become public,
recoverable protocol objects.
Observer assignment is deterministic over:
- the epoch seed,
- the producer account id,
- the slot $(height, view)$,
- the observation round,
- the observer account id.
The producer is excluded from its own observer pool. The runtime may also filter assignments through a correlation budget over provider, region, host class, and key-authority class.
Each assigned observer publishes one of two things:
- a guardian-backed
AsymptoteObserverTranscript, or - an objective
AsymptoteObserverChallenge.
A transcript binds the canonical slot surface:
- the epoch and assignment,
- the candidate block hash,
- the guardian manifest, decision hash, counter, trace hash, and measurement root,
- the guardian checkpoint root,
- the observer verdict and veto kind,
- the observer evidence hash.
The admissible challenge basis is public-evidence-only:
MissingTranscript,TranscriptMismatch,VetoTranscriptPresent,ConflictingTranscript,InvalidCanonicalClose.
Each challenge carries its own public evidence object: an assignment, an
offending observation request, an offending transcript, or an offending
canonical close. The challenge evidence_hash must bind exactly that
carried evidence.
The slot then carries three canonical bindings:
- a transcript commitment over the transcript surface,
- a challenge commitment over the challenge surface,
- exactly one canonical outcome object:
AsymptoteObserverCanonicalCloseorAsymptoteObserverCanonicalAbort.
The collapse rule is close-or-abort and challenge-dominant:
SealedFinalifBaseFinalholds, the deterministic assignment set is fully covered by valid canonicalOktranscripts, the transcript and challenge commitments verify, the challenge surface is empty, and the canonical close object is valid.Abortif the transcript and challenge commitments verify, the challenge surface is non-empty, and the canonical abort object is valid.Pendingotherwise.
Challenge dominance is a theorem-level veto, not an operational alarm. A valid challenge collapses the slot to abort before any penalty, governance, or membership aftermath is considered.
This makes observer sealing structurally parallel to canonical ordering: public evidence, canonical commitments, a unique positive object, a unique negative object, and deterministic local close-or-abort derivation from the same public surface.
Divergence signals and escalation
The sealing plane may also emit divergence signals, including:
- conflicting guardian certificates,
- witness omission,
- stale registry use,
- stale checkpoints,
- transparency-log consistency failure.
These signals support Escalated and Invalid outcomes and give
operators a fail-closed evidence trail.
Sealed effects and replay-safe release
Irreversible effects are gated by finality tier. The effect plane distinguishes between:
BaseFinaleffects, which are allowed on the fast path when policy permits,SealedFinaleffects, which require a validSealedFinalityProof.
For proof-enabled irreversible effects, Asymptote carries a
self-contained SealObject whose current instantiation includes:
- an
EffectIntent, - an
EffectPublicInputsobject, includingcanonical_collapse_hash, - an
EffectProofEnvelope, - a replay-safe nullifier.
In the runtime, SealedFinal secure-egress requests carry both
the SealedFinalityProof and the slot's
CanonicalCollapseObject. The guardian-side seal builder and downstream
receipt verifier recompute the same canonical_collapse_hash from that
collapse object together with the proof-carried observer surface, so a
challenge-dominated or otherwise mismatched slot cannot authorize irreversible
release.
The release rule is
$$
\mathrm{Release}(e) \iff \mathrm{BaseFinal}(\mathrm{slot}(e)) \wedge \mathrm{SealedFinal}(\mathrm{slot}(e)) \wedge \mathrm{VerifySealObject}(e) \wedge \mathrm{CollapseHash}(e)=\mathrm{Hash}(\mathrm{Collapse}(\partial_h)) \wedge \neg \mathrm{NullifierUsed}(e).
$$
This keeps the hot path sparse while making released consequences deterministic and replay-safe.
Deterministic observer theorem
The deterministic Asymptote observer model now proves the following
kernel:
- base certificates are unique per slot,
- canonical observer close objects are unique per slot,
- canonical observer close and canonical observer abort cannot coexist for the same slot,
- a challenge-dominated slot cannot produce a valid sealed release.
Theorem: Deterministic Equal-Authority Observer Sealing.
Assume sound deterministic observer assignment, signature-sound guardian-backed observer transcripts and challenges, canonical transcript and challenge commitments, append-only registry and log publication once published, and deterministic transcript/challenge derivation over the closed public observer surface. Then arbitrary behavior by the rest of the validator set cannot create a conflicting valid canonical observer close, cannot make canonical close and canonical abort coexist for the same slot, and cannot authorize a valid sealed irreversible effect release for a challenge-dominated slot.
This theorem is the observer-lane analogue of canonical ordering's public certificate theorem: public evidence, canonical commitments, negative-authority dominance, and deterministic local close-or-abort derivation from the same public observer surface.
Under the accountable publication rules of Section System Model and Notation, the same observer challenges are also penalty-bearing objective faults. Unsafe positive close attempts therefore become not only rejectable, but accountable and epoch-removing.
Legacy sampled comparison
Before CanonicalChallengeV1, the observer lane was typically described
through a sampled affirmative bound. Let:
- $h$ be the honest fraction of equal-authority validators,
- $A_s^j$ be the sampled observer committee for slot $s$ and round $j$,
- $k_j = |A_s^j|$,
- $p_{\mathrm{beacon_bias}}$ be the probability of sufficient beacon bias,
- $p_{\mathrm{veto_suppression}}$ be the probability that a valid veto surface is fully suppressed.
Then the old affirmative sampled lane admitted the analytical bound
$$
P_{\mathrm{unsafe}}(s) \le p_{\mathrm{beacon_bias}} \cdot p_{\mathrm{veto_suppression}} \cdot \prod_j (1 - h)^{k_j}.
$$
For constant committee size $k$ across $r$ rounds:
$$
P_{\mathrm{unsafe}}(s) \le p_{\mathrm{beacon_bias}} \cdot p_{\mathrm{veto_suppression}} \cdot (1 - h)^{kr}.
$$
That formula remains a useful historical comparison, but it is no longer the
normative theorem for the observer lane. Under CanonicalChallengeV1,
sampling determines duties, not safety. Safety comes from the canonical public
transcript surface, the canonical public challenge surface, and the
close-or-abort split that those surfaces induce.
The runtime publishes the canonical observer transcript, commitment, challenge,
challenge commitment, and close-or-abort objects as ordinary
guardian_registry transactions after the sealed header is formed. The
same surface is carried inside the proof for immediate block verification.
NestedGuardian: Witness-Augmented Research Mode
NestedGuardian explores a layered threshold construction:
- validators run the AFT deterministic message flow,
- each proposal carries its guardian committee certificate,
- external witness committees cross-check the slot,
- chain state anchors witness assignments, witness manifests, and slashing evidence.
The instantiated runtime scope includes:
- deterministic witness assignment from the active witness set,
- registered on-chain witness manifests,
- witness certificates bound into guardianized slot certificates,
- safety proofs for the witness-augmented kernel,
- bounded model checking for reassignment, outage, and checkpoint transitions.
The instantiated proof package consists of:
- safety formalization,
- bounded operational model checking for reassignment, outage, and checkpoint transitions,
- a discharged composed-liveness bridge under the target eventual-fair scheduler through the recurrence/reduction/totality/collapse chain together with a matching persistent churn/restart simulator.
NestedGuardian is therefore a witness-augmented mode with a finished
theorem bridge. It is experimental as an operational mode, not as a theorem
crutch. Its witness-coded family supplies an explicit constructive recovery
carrier and completed bridge artifacts; it does not reduce the promoted
AFT theorem surface to an experimental-only claim. That constructive
recovery carrier is a witness-coded publication-bundle recovery contract with
compact hot-path bindings and cold-path registry-driven close-or-abort
resolution. The abstract coded
recovery-family contract is realized by the parametric
SystematicXorKOfKPlus1V1 parity family plus the bounded true non-parity
SystematicGf256KOfNV1 family with at least two parity shares,
implemented with systematic Cauchy-style coefficients and exercised in bounded
2-of-4, 3-of-5, 3-of-7, 4-of-6, and 4-of-7
lanes. These lanes resolve from threshold-many public reveals, objective
recovered-support conflict, or deterministic missingness. The bounded
3-of-5, 4-of-6, and 4-of-7 lanes restore or exceed
threshold-support overlap while the bounded 3-of-7 lane shows that
recovered-support conflict remains fail-closed even when overlap is absent. A
bounded conformance harness checks that every threshold-sized reveal subset
reconstructs and every below-threshold subset fails across the shipped XOR and
GF256 realizations of that contract. Those recovered reveals lift
deterministically into an explicit positive close-extraction payload and then
into an explicit extractable bulletin-surface payload that binds the verifying
publication bundle, verifying canonical bulletin close, canonical
bulletin-availability bytes, and sorted bulletin entries.
The completed bounded family also carries the ordinary durable and restart
surfaces. A bounded recovered-only two-slot harness shows that consecutive
recovered surfaces derive the ordinary publication-frontier predecessor chain
and the same authoritative CanonicalCollapseObject predecessor chain
without the ordinary publication-bundle lane. A second bounded recovered-only
harness shows a close/abort/close bulletin window with a recovered
omission-dominated middle slot: recovered data alone materializes the ordinary
positive closes and extracted bulletin surfaces on the outer slots,
materializes the ordinary omission-dominated abort in the middle while keeping
omission evidence and recovered bulletin entries public, and preserves the same
authoritative collapse continuity chain. A bounded read-side harness shows that
the same recovered-only durable chain yields the same compact replay-prefix /
state-root continuity view that the ordinary lane exposes plus a bounded
recovered canonical-header prefix. The execution module verifies that replay
tip as the same restart anchor the ordinary lane uses, retains both recovered
prefixes in execution state, and uses the recovered canonical-header ancestry
for bounded anchored reads plus parent-block / parent-state-root continuity
after restart when ordinary recent blocks are absent.
Validator consensus orchestration derives the same bounded recovered restart
parent anchor from the recovered canonical-header / collapse surface when the
ordinary committed block is absent, and the GuardianMajority engine
consumes that bounded recovered canonical-header prefix as restart-time
parent/QC context for synthetic parent-height QC continuity when the full
committed block is absent. The same recovered surface yields a bounded
recovered certified-header window plus a restart-only recovered
BlockHeader / QC cache window for restart-time header / QC lookup plus
bounded QC-certified recovered branch reconciliation over the configured local
five-entry window. Those windows fold by exact overlap with a configurable
budget, exercised at five windows into a longer seventeen-step recovered
certified branch without ordinary committed headers. Those same cold-path
loaders consume a configurable exact-overlap segment budget, exercised at four
exact-overlap segments into a longer fifty-three-step recovered certified
branch with direct registry-extraction parity and explicit interior-overlap
conflict rejection. Those same restart loaders also compose two overlapping
four-segment exact-overlap folds into a longer eighty-nine-step recovered
certified branch with direct registry-extraction parity and explicit inter-fold
overlap conflict rejection, and tests exercise the same recursive carrier at
three overlapping four-segment folds into a one-hundred-twenty-five-step
recovered certified branch. The runtime has a bounded conformance harness over
one, two, and three stitched segment folds, matching the same production-loader
/ registry-extraction carrier at the corresponding fifty-three-step,
eighty-nine-step, and one-hundred-twenty-five-step branches.
The restart path also pages older exact-overlap segment folds on demand beneath that bounded suffix via an overlap-checked cursor while keeping only the bounded recent suffix plus the streamed page live in engine caches, and tests exercise that paged carrier at a longer two-hundred-thirty-three-step recovered certified branch with direct registry-extraction parity plus explicit duplicate-page, missing-gap, and late-page overlap rejection. Restart therefore streams recovered certified ancestry until target height or recovered-history exhaustion without a theorem-relevant fixed depth bound.
The archival internalization layer uses an active archived-recovered-history profile naming retention horizon, exact-overlap paging geometry, segment / fold geometry, checkpoint update rule, and profile evolution. Archived segments, archived restart pages, archival checkpoints, and archival retention receipts bind to historically referenced profile hashes and governing activation hashes under a published profile-activation chain before archived continuation is trusted, and ordinary canonical collapse history names the archived checkpoint / activation pair that archived restart is authorized to follow. Archived replay and archived publication correctness are historical and index-free: they follow the canonical-collapse-anchored or object-carried activation hash plus predecessor/checkpoint history rather than whichever archived activation is merely latest in local state.
When the recovered certificate carries objective omission proofs, the same
recovered lane routes into the ordinary OmissionDominated abort path
while keeping omission evidence and recovered bulletin entries public. The
recovery-family contract, canonical-collapse / replay retrievability anchor, and
recovered-state historical retrievability surface are therefore part of ordinary endogenous
AFT history rather than a narrower theorem-side qualifier. The directly
discharged recurrence/reduction/totality/collapse chain closes the former
distance to unconditional classical 99% Byzantine agreement, so no
lower-bound, recoverability, or architecture-specific semantic gap remains at
the theorem surface.
Security and Assumption Surface
The AFT family depends on explicit assumptions. They are not optional prose.
| Layer | Required assumptions | Failure consequence |
|---|---|---|
| Base finality | current manifests, current epoch state, majority thresholds, guardian non-equivocation, valid checkpoints, enough validators and guardians to reach quorum | conflicting base-finality evidence or loss of progress |
| Canonical ordering | objective publication, compact publication-frontier binding and contradiction rules, canonical cutoff, deterministic eligibility, append-only bulletin commitment, proof soundness, protocol-native retrievability profile / manifest / custody / challenge surface, canonical bulletin-close extraction-or-abort, cheap omission verification, accountable omission publication | loss of compact frontier consistency, deterministic extraction-or-abort, accountability, or the ordering theorem |
| Sealed finality | valid asymptote policy, current witness seed, valid witness or observer assignments, checkpoint freshness, valid log consistency proofs, deterministic transcript/challenge derivation, accountable challenge publication | incorrect sealed release, loss of accountability, or fail-closed stalling |
| Sealed effects | correct finality-tier policy, sound verifier metadata, nullifier uniqueness, intent/public-input binding | replay or unsafe irreversible effect release |
| NestedGuardian | sound witness assignment and registration, correct reassignment handling, witness committee non-equivocation | degraded safety or open liveness behavior |
The family-level discipline is simple: if an assumption fails, AFT should degrade to stalling, aborting, or withholding release before it degrades to unsafe irreversible behavior.
Formal Results
The repository's machine-checked surfaces align with the protocol family as follows:
| Formal module | Core proved results |
|---|---|
GuardianMajorityProof |
QuorumCertificatesIntersect, InvariantImpliesSafety |
GuardianMajority |
executable bounded checks for finalization witness soundness and slot safety |
CanonicalOrderingProof |
InvariantImpliesCertifiedUniqueness, / InvariantImpliesRecoverability, / InvariantImpliesOmissionDominates |
CanonicalOrdering |
executable bounded checks for publication, cutoff, certification, omission, and recoverability |
AsymptoteProof |
InvariantImpliesBaseSafety, / InvariantImpliesCanonicalCloseSafety, / InvariantImpliesCloseAbortExclusive, / InvariantImpliesAbortDominatesSealed |
Asymptote |
executable bounded checks for transcript publication, challenge publication, canonical close, and canonical abort |
NestedGuardianProof |
witness-assignment soundness, / witness-certificates-stay-assigned, / InvariantImpliesSafety |
NestedGuardian |
executable bounded checks for reassignment, outage, and checkpoint admissibility |
Every formal artifact named in this section, and every additional proof artifact cited by file name below, is embedded verbatim in Appendix Embedded Formal Artifacts so that the served yellow paper remains self-contained outside the repository.
These formal surfaces prove the deterministic safety kernels that the broader
classical-agreement bridge builds on. The full ordinary classical
99% Byzantine agreement sentence is then completed by the recurring,
reduction, totality, and collapse layers discussed above, rather than by these
module-local safety kernels in isolation. Compact publication-frontier
summaries internalize same-slot and predecessor consistency on the live path,
while the protocol-native retrievability plane internalizes closed-bulletin
extraction-or-abort as an endogenous part of the realizing architecture rather
than a purely algebraic consequence of the authenticated message transcript
alone.
The accountable-adversary variant therefore composes these formal kernels with runtime accountability rules rather than replacing them: replay-deduplicated objective fault publication and optional policy-controlled membership updates live in the implementation and policy layer above the proved deterministic core.
Complete omission-dominance witness artifact
The formal package includes an executable TLC witness module,
docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrderingOmissionTrace.tla,
paired with
docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrderingOmissionTrace.cfg.
The exact module and configuration are embedded in
Appendix CanonicalOrderingOmissionTrace.tla and
Appendix CanonicalOrderingOmissionTrace.cfg; the summary below highlights the
executed public-evidence shape that the witness reaches.
Executed witness trace.
The module intentionally asks TLC to violate the state predicate
NoOmissionDominanceWitness so that the checker emits a concrete public
evidence trace. The executed trace is:
PublishStep:tx1enters slot $1$'s bulletin surface.PublishStep:tx2enters the same bulletin surface.CloseCutoffStep: the canonical cutoff closes and the recoverable set becomes ${tx1, tx2}$.CandidateCertifyStep: a candidate certificate for ${tx1}$ appears.ProveOmissionStep: an omission proof for $tx2$ against that candidate certificate appears.
The same formal package carries a bounded recursive-continuity model,
docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalCollapseRecursiveContinuity.tla,
paired with
docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalCollapseRecursiveContinuity.cfg.
The exact source of both artifacts is embedded in
Appendix CanonicalCollapseRecursiveContinuity.tla and
Appendix CanonicalCollapseRecursiveContinuity.cfg.
That model captures the reference HashPcdV1 continuity carrier directly:
deterministic recursive proof steps, predecessor-proof hashing,
CanonicalCollapseExtensionCertificate carriage, and the rule that
non-genesis header admission depends on the anchored predecessor proof relation.
The runtime exposes a SuccinctSp1V1 backend seam for those
same recursive public inputs, and that seam is exercised by consensus
verification and durable-state gating. The formal model still stops at the
reference carrier rather than mechanizing a cryptographic recursive
accumulator or ZK backend.
At the final state, the incomplete candidate certificate remains unadmitted while the omission proof is present. In the executable model this happens because the admitted object must already equal the canonical set; the trace therefore does not replace the theorem. Its purpose is narrower and useful: it gives a bounded, executed witness of the exact public-evidence shape from which omission dominance follows. Readers can run the trace directly and inspect the six-state witness without reconstructing the paper's argument by hand.
Implementation Correspondence
This section is non-normative. It names the exact runtime symbols that carry the protocol objects defined above.
Core ordering symbols
The core ordering data structures and free functions are public Rust symbols
re-exported through ioi_types::app. They are the runtime carriers for
the abstract ordering objects and verifier rules defined above.
| Abstract object | Current runtime symbols |
|---|---|
| Bulletin surface commitment | BulletinCommitment, BulletinSurfaceEntry |
| Compact publication availability binding | PublicationAvailabilityReceipt |
| Compact publication frontier | PublicationFrontier |
| Publication-frontier contradiction | PublicationFrontierContradiction |
| Canonical ordering proof families | CanonicalOrderProofSystem, with concrete variants HashBindingV1 and CommittedSurfaceV1 |
| Canonical public-input tuple | CanonicalOrderPublicInputs |
| Live succinct witness payload | CommittedSurfaceCanonicalOrderProof |
| Omission evidence | OmissionProof |
| Order certificate | CanonicalOrderCertificate |
| Canonical ordering function | canonical_order_tx_hashes |
| Publication-frontier hashing | canonical_publication_availability / _receipt_hash, / canonical_publication_frontier_hash, / canonical_publication_frontier / _contradiction_hash |
| Publication-frontier construction / verification | build_publication_availability_receipt, / build_publication_frontier, / verify_publication_frontier, / verify_publication_frontier_contradiction |
| Public-input hashing | canonical_order_public_inputs, / canonical_order_public_inputs_hash |
| Reference proof construction | build_reference_canonical_order / _proof_bytes |
| Live certificate construction | build_committed_surface_canonical / _order_certificate |
| Certificate verification | verify_canonical_order_certificate |
Guardian and sealing symbols
The guardian, witness, observer, and sealed-effect objects are likewise public
Rust symbols re-exported through ioi_types::app. They encode the exact
evidence surface checked by validators and downstream gateways.
| Abstract object | Current runtime symbols |
|---|---|
| Guardian slot certificate | GuardianQuorumCertificate |
| Witness certificate | GuardianWitnessCertificate |
| Equal-authority observer assignment | AsymptoteObserverAssignment |
| Correlation budget | AsymptoteObserverCorrelationBudget |
| Observer observation request | AsymptoteObserverObservationRequest |
| Observer transcript | AsymptoteObserverTranscript |
| Observer transcript commitment | AsymptoteObserverTranscriptCommitment |
| Observer challenge | AsymptoteObserverChallenge, with kinds MissingTranscript, TranscriptMismatch, VetoTranscriptPresent, ConflictingTranscript, and InvalidCanonicalClose |
| Observer challenge commitment | AsymptoteObserverChallengeCommitment |
| Canonical observer close | AsymptoteObserverCanonicalClose |
| Canonical observer abort | AsymptoteObserverCanonicalAbort |
| Finality tier | FinalityTier, with variants BaseFinal and SealedFinal |
| Collapse state | CollapseState, with variants Pending, BaseFinal, Sealing, Abort, SealedFinal, Escalated, and Invalid |
| Sealing policy | AsymptotePolicy |
| Observer statement | AsymptoteObserverStatement |
| Observer certificate | AsymptoteObserverCertificate |
| Divergence signal | DivergenceSignal, DivergenceSignalKind |
| Sealed finality proof | SealedFinalityProof |
| Observer binding for sealed effects | sealed_finality_proof_observer_binding |
| Proof-carrying effect object | SealObject |
Verifier, orchestration, and persistence symbols
Verification and orchestration entry points are split across four public
namespaces: ioi_types::app,
ioi_crypto::sign::guardian_committee,
ioi_services::guardian_registry, and the
GuardianMajorityEngine runtime. Engine-local checks are named here by
their exact method identifiers.
| Responsibility | Current runtime symbols |
|---|---|
| Guardian certificate verification | verify_quorum_certificate |
| Witness certificate verification | verify_witness_certificate |
| Deterministic observer assignment | derive_asymptote_observer_assignments, / derive_asymptote_observer_plan_entries |
| Observer-side transcript / challenge derivation | GuardianContainer::observe_asymptote_request, / GuardianContainer::request_remote_asymptote / _observer_observation, / GuardianContainer::sign_consensus_with_guardian |
| Sealed finality verification in the engine | GuardianMajorityEngine::verify_asymptote / _canonical_observer_sealed_finality, / GuardianMajorityEngine::verify_asymptote / _sealed_finality |
| Canonical-order enrichment verification in the engine | GuardianMajorityEngine::verify / _canonical_order_enrichment; published / CanonicalOrderAbort dominates positive order / certificates and inconsistent mixed parent state |
| Publication-frontier enrichment verification in the engine | GuardianMajorityEngine::verify / _publication_frontier_enrichment; published / PublicationFrontierContradiction dominates / conflicting or stale frontiers |
| Block finalization attachment of order certificates | build_committed_surface_canonical / _order_certificate during finalization |
| Block finalization attachment of publication frontier | build_publication_frontier during finalization |
| Canonical observer proof publication | canonicalize_observer_sealed_finality_proof, / publish_canonical_observer_artifacts |
| Sealed-effect construction and checking | build_http_egress_seal_object, verify_seal_object |
| Guardianized proposal verification in the engine | GuardianMajorityEngine::verify / _guardianized_certificate |
| Base-engine safety and timing | SafetyGadget, Pacemaker, TimeoutCertificate |
| Bulletin and order-certificate state access | load_bulletin_commitment, / load_canonical_order_certificate |
| Publication-frontier state access | GuardianRegistry::load_publication_frontier, / GuardianRegistry::load_publication / _frontier_contradiction |
| Ordering close-or-abort derivation | derive_canonical_order_execution_object, / derive_canonical_order_public_obstruction |
| Ordering abort taxonomy | CanonicalOrderAbortReason::MissingOrderCertificate, / BulletinSurfaceReconstructionFailure, / BulletinSurfaceMismatch, / InvalidBulletinClose, / OmissionDominated, / CertificateHeightMismatch, / RandomnessMismatch, / OrderedTransactionsRootMismatch, / ResultingStateRootMismatch, / InvalidPublicInputsHash, / InvalidBulletinAvailabilityCertificate, / InvalidProofBinding |
| Protocol-wide collapse derivation and verification | derive_canonical_collapse_object, / GuardianMajorityEngine::verify_published / _canonical_collapse_object |
| Proposal-surface recursive continuity | BlockHeader::previous_canonical_collapse_commitment_hash, / BlockHeader::canonical_collapse_extension_certificate, / CanonicalCollapseExtensionCertificate, / CanonicalCollapseCommitment, / verify_block_header_canonical_collapse_evidence, / ConsensusDecision::ProduceBlock |
| Bulletin, order, and collapse state access | load_bulletin_commitment, / load_canonical_order_certificate, / load_canonical_order_abort, / load_canonical_collapse_object |
| On-chain publication verbs | publish_aft_publication_frontier@v1, / publish_aft_canonical_order_artifact_bundle@v1, / publish_aft_canonical_order_abort@v1, / publish_aft_canonical_collapse_object@v1, / report_aft_omission@v1, / publish_asymptote_observer_transcript@v1, / publish_asymptote_observer_transcript_commitment@v1, / report_asymptote_observer_challenge@v1, / publish_asymptote_observer_challenge_commitment@v1, / publish_asymptote_observer_canonical_close@v1, / publish_asymptote_observer_canonical_abort@v1 |
| Accountable evidence replay protection and validator removal | evidence_id, / GuardianRegistry::apply_accountable_fault_report, / GuardianRegistry::apply_accountable_membership_updates |
| Native benchmark target | benchmark_throughput |
These symbols are named here so that the paper maps directly onto the current
runtime without making the reader chase separate prose specifications. In the
implementation, validator finalization publishes a protocol-visible
CanonicalCollapseObject through
publish_aft_canonical_collapse_object@v1 after local post-commit
header enrichment, guardian_registry exposes
load_canonical_collapse_object, and
GuardianMajorityEngine::verify_published_canonical_collapse_object
cross-checks any published copy against the proof-carried header surface when
it is available. The externally finalized AFT commit path persists the same
object keyed by slot height, rather than treating ordering and sealing
close-or-abort evidence as loose enrichments detached from state persistence.
The same post-commit path also builds PublicationFrontier via
build_publication_frontier and publishes it through
publish_aft_publication_frontier@v1;
GuardianMajorityEngine::verify_publication_frontier_enrichment
rechecks same-slot binding, predecessor linkage, and any dominating
contradiction object.
In the current proposal-surface continuity slice, validator orchestration now
signs both previous_canonical_collapse_commitment_hash and a typed
CanonicalCollapseExtensionCertificate into each produced AFT block
header.
In the current clean-break runtime slice, CanonicalCollapseObject
itself carries continuity_accumulator_hash and
continuity_recursive_proof, so the certificate now carries the
predecessor commitment plus predecessor proof hash rather than an explicit
carried ancestor vector, full predecessor collapse object, or predecessor
recursive proof object.
Asymptote leaders stall rather than produce when that required
extension certificate is unavailable, proposal verification recursively
checks that the carried predecessor commitment hash matches the signed
predecessor link, checks that the predecessor commitment's resulting state root matches the
signed parent-state root, and rechecks those carried public inputs against the
anchored predecessor collapse object when one is available. QC promotion
therefore relies on a reference recursive proof-carrying continuity relation
rather than on a recomputed predecessor digest alone, and only treats continuity-linked
headers as progress-bearing.
Benchmark Context
The performance evidence in this paper has two sources:
- literature-reported baselines for
HotStuff,Narwhal/Tusk, andBullshark, - the repository's native
benchmark_throughputtarget for matchedGuardianMajorityandAsymptotescenarios.
The purpose of this section is architectural positioning, not false equivalence across unmatched environments.
Paper-reported baselines
| System | Reported throughput | Reported latency | Source type |
|---|---|---|---|
| HotStuff baseline | 1{,}800 tx/s | 1 s | Narwhal/Tusk comparison setting |
| Narwhal-HotStuff | 130{,}000 tx/s | under 2 s | Narwhal/Tusk paper |
| Narwhal-HotStuff with additional workers | up to 600{,}000 tx/s | n/a | Narwhal/Tusk paper |
| Tusk | 160{,}000 tx/s | about 3 s | Narwhal/Tusk paper |
| Bullshark | 125{,}000 tx/s | about 2 s | Bullshark paper |
The baseline interpretation is:
HotStuffdemonstrates the leader-based partially synchronous baseline,Narwhal-HotStuffdemonstrates the gain from separating dissemination from ordering,Bullsharkdemonstrates high-throughput DAG-oriented ordering,- AFT adds a new separation: order surfacing and effect release are no longer identified with dense positive voting.
Native repository measurements
No performance measurement in this section is load-bearing for any theorem in this paper; the promoted theorem surface stands independently of benchmark tuning, harness state, or optimization maturity.
The corrected native measurements below were produced on March 21, 2026 after
bringing the repository's native AFT benchmark path back into sync with the
current GuardianMajority / base_final harness semantics:
- shared-tip readiness no longer treats a transient
get_status.height = 0as authoritative when a resilient tip probe already sees committed blocks, - submission alignment and leader-targeted ingress now use a resilient tip block rather than a potentially stale status height,
- authoritative chain-commit scans start from the resilient pre-submission tip instead of rescanning stale empty-block prefixes,
- sustained throughput for fast probes now stops on the authoritative full-chain commit scan for the highest committed height; sampled committed-status visibility is retained only as an auxiliary lag diagnostic,
- the benchmark surface now exposes alignment, spill, and replay diagnostics explicitly so missed due blocks or replay churn are not hidden behind a single TPS number.
The table below reports the current matched bulk-throughput proof point for the
native GuardianMajority 4-validator base_final scenario under
that corrected harness. This is a repository-native AFT proof point on the
Jellyfish state path with a 1 s block interval, not an apples-to-apples claim
against published Narwhal/Tusk/Bullshark environments.
| scenario | validators | attempted | accepted | committed | blocks | inj. tps | sust. tps | p50 | p95 | p99 | sealed p50 | sealed p95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| guardian_majority_4v_base_final_bulk | 4 | 16384 | 16384 | 16384 | 1 | 21370.89 | 9647.66 | 1293.45 | 1603.73 | 1695.24 | -- | -- |
These measurements imply four things:
- the earlier single-digit and low-hundreds TPS reports were artifacts of benchmark-path bugs rather than of the protocol surface itself,
- the current repository now clears the lower edge of the intended
8k--16k TPSrange in a matched native 4-validatorGuardianMajoritybulk probe, - on this corrected probe the batch lands in a single block, so the main remaining AFT work is ceiling-raising and aggregate-domain multiplication rather than recovering from a broken harness,
- these values should be read as corrected repository baselines, not as
optimized ceilings and not as apples-to-apples superiority claims over
published
Narwhal/Tusk/Bullsharkenvironments.
Related Work
Geeq's Proof of Honesty (PoH) is important prior work in the "99%" direction: it argues for globally honest and canonical chain recovery in pure software under assumptions including at least one honest node and an honest relay, and it uses public evidence plus user-side verification to push beyond ordinary dense-vote intuition [geeq]. AFT differs in a key respect: it is relay-free and coordinator-free. Correctness does not depend on any designated honest relay, broadcaster, or privileged recovery role. Instead, durable ordering and sealed effects collapse through protocol-native public-evidence objects whose negative forms are immediately decisive.
Narwhal/Tusk and Bullshark separate dissemination from ordering, but they still ground ordering safety in dense positive certificates and quorum-intersection arguments over the ordered object itself [narwhal, bullshark]. HoneyBadgerBFT and Dumbo move to asynchronous common-subset or MVBA-style agreement, but they still rely on classical Byzantine-majority thresholds rather than a public-state-continuity theorem over a canonical public surface [honeybadger, dumbo]. Chainlink CCIP and optimistic cross-chain mechanisms add secondary monitoring layers, risk-management committees, or challenge windows to detect and halt bad transfers, but the decisive recovery rule is operational or economic rather than the immediate acceptance of a uniquely valid proof-carrying canonical object recoverable by any equal-authority validator [ccip]. Accountable subgroup multisigs and finality gadgets add equivocation evidence and slashing, yet still keep dense subgroup votes as the positive safety object [grandpa, accountable]. AFT differs by making ordering and sealed release relay-free public-evidence close-or-abort objects with dominant negative proofs: honest validators that observe the same closed public boundary derive the same decisive object, and publication is downstream of that deterministic derivation rather than its source.
Claims and Non-Claims
Claims
This paper claims:
- a production guardian-backed base-finality model in which validator quorums are composed with guardian committee admissibility,
- proof-carrying canonical ordering with omission dominance and uniqueness, plus protocol-native endogenous retrievability,
- compact signed publication-frontier summaries and short contradiction objects that internalize same-slot and predecessor consistency on the live path,
- a public-state-continuity formulation in which closed slot boundaries admit at most one positive public execution object and conflicting candidates admit short objective obstruction witnesses,
99%equal-authority ordering consensus under explicit assumptions,- deterministic sealed-effect collapse with challenge dominance,
- a relay-free, coordinator-free, pure-software public-state-continuity
theorem yielding deterministic
99% Byzantine Tolerancefor durable ordering and sealed-effect safety over the explicit bulletin / retrievability substrate, - that the whole AFT stack universally breaks the lower bound with no external qualifiers,
- a witness-augmented mode for layered threshold constructions,
- machine-checked deterministic safety kernels for the major protocol surfaces.
Non-claims
This paper does not claim:
- that public state continuity arises for free inside the classical DLS / PBFT partially synchronous message-passing model,
- that the classical $n > 3f$ / $f < n/3$ lower bound has been refuted inside that bare model; the claim is instead that AFT breaks the bound at the promoted agreement-theorem surface by replacing dense honest- supermajority intersection with a protocol-internal public-evidence carrier. Remove that carrier and the paper is no longer claiming the same result. This is not a retreat to "outside the model." It is the exact location of the break. AFT does not merely vary a parameter inside the dense-vote carrier; it replaces the carrier with endogenous public-evidence continuity while preserving the same promoted agreement sentence at theorem surface. The paper does not ask credit for defeating an impossibility theorem while secretly continuing to use the old carrier; it supplies a new endogenous carrier and claims the same promoted agreement sentence on that basis. A reviewer who says only "the carrier changed" has described the mechanism, not rebutted it,
- freedom from bulletin-publication, protocol-native retrievability obligations, or proof-soundness assumptions,
- that compact publication-frontier summaries make the bulletin surface self-extracting inside the classical authenticated-message model,
- a full asynchronous liveness theorem under arbitrary registry, log, witness, and outage schedules,
- an apples-to-apples measured throughput superiority over
HotStuff,Narwhal,Tusk, orBullsharkfrom the current repository alone.
Public-state-continuity theorem
The runtime supports a stronger theorem than the older accountable summary because the mechanism and system model are now stated directly at theorem surface.
Theorem: Relay-Free Deterministic 99% Byzantine Tolerance.
Assume the system model of Section System Model and Notation, guardian non-equivocation, proof soundness, compact signed publication-frontier summaries whose same-slot and predecessor-link contradictions are objectively checkable, protocol-native retrievability objects plus canonical bulletin-close extraction-or-abort for the bulletin surface bound by those frontiers, deterministic transcript/challenge derivation for sealing, durable state advancement only through canonical collapse, and irreversible-effect release only through collapse-bound sealed proofs. Then up to $99%$ of validators may behave arbitrarily without creating a conflicting valid durable canonical-order outcome or a conflicting valid sealed-effect release outcome. Honest validators that observe the same closed public boundary derive the same close-or-abort result; publication, penalties, and validator-set updates only accelerate convergence and future hygiene. This is unconditional classical Byzantine agreement in the ordinary permissioned setting. AFT does not weaken that agreement sentence; it realizes it through protocol-internal public-evidence continuity machinery rather than dense positive quorum intersection.
"Unconditional" is used here in the only theorem-salient sense: once the explicit AFT system model is fixed, no further safety-carrying helper or exception clause remains. Bulletin close, publication frontier, retrievability, recovery, restart continuity, canonical collapse, and collapse-bound sealing are not theorem-side caveats; they are the protocol- internal realizing mechanism. A criticism that AFT "changes the model" without identifying a hidden external helper is therefore non-responsive.
The theorem is stronger than the older accountable summary because invalid positive objects are not merely rejectable or penalty-bearing. They are already dominated by deterministic negative objects and collapse-gated durable state before any penalty logic runs. Readers trained on dense-vote BFT will be tempted to treat the absence of quorum-intersection safety as disqualifying. In AFT, that is precisely the point: authority is carried by uniquely valid public execution objects and omission-dominant contradiction witnesses, with durable advancement gated by canonical collapse. Compact publication frontiers keep the live hot path cheap by internalizing consistency and lineage checks, while the protocol-native retrievability plane discharges deterministic extraction-or-abort on the full bulletin surface.
The recurrence / reduction / totality / collapse chain is not narrative glue. Its exact artifact chain is embedded verbatim in Appendix Embedded Formal Artifacts, ending in the classical-agreement collapse wrapper itself.
Theorem: Realizing-Mechanism Statement.
The new publication-frontier slice is not the theorem by itself; the theorem is the same promoted classical agreement sentence, carried by the full AFT public-evidence continuity architecture. Compact signed publication-frontier summaries, compact availability receipts, short frontier contradiction objects, endogenous retrievability profiles, manifests, custody assignments, custody receipts, custody responses, retrievability challenges, canonical extraction-or-abort, canonical collapse, and historical retrievability together realize the same unconditional classical
99% Byzantine agreementsentence stated above. Removing that protocol-native retrievability plane removes part of the realizing mechanism rather than merely shaving off an optional refinement.
Proposition: Scoped Witness-Coded Constructive Corollary.
Assume the hypotheses of the relay-free deterministic
99% Byzantine Tolerancetheorem with AFT's public-state continuity machinery as its protocol-internal safety carrier, plus sound witness assignment and witness certificate binding, a completed witness-coded recovery family with compact hot-path bindings and cold-path share delivery / reveal / reconstruction, and availability of the retained recovered publication surface together with any older recovered-history pages needed for restart-time extraction. Then theNestedGuardianwitness-coded carrier deterministically materializes the same positive close or canonical abort surface, the same authoritative collapse chain, the same replay-prefix / restart-anchor surface, and the same restart-time canonical-header / certified-header / block-header ancestry surface as the ordinary lane for the completed recovery families. Restart can therefore stream recovered certified ancestry until target height or recovered-history exhaustion without a theorem-relevant fixed depth bound, while keeping only compact bindings on the hot path and bounded-memory paging on the restart path.
This runtime result is stronger than the separation closeout because it no longer stops at "compact frontiers bind a recoverability claim." It shows that the live AFT stack can re-materialize the same durable and restart-critical surfaces without violating the throughput guardrails, while keeping deeper recovered history inside ordinary endogenous AFT state.
This is one constructive route to classical partially synchronous Byzantine agreement rather than as a weaker contrast class. In the classical dense-vote presentation, worst-case progress is usually phrased in terms of $> 2/3$ honest participation and quorum intersection as the main safety mechanism. In AFT's realization, the same promoted agreement sentence is obtained instead through uniquely valid public-evidence objects plus dominant negative proofs, without trusted relays, privileged coordinators, TEEs, or dense positive quorum intersection. The live publication-frontier slice internalizes compact same-slot and predecessor consistency on the hot path, while explicit recoverability of the bound bulletin surface, canonical collapse, and historical retrievability complete the same ordinary agreement sentence. Publication and accountability serve as reinforcement rather than the source of correctness. Liveness then follows from the availability of the PSC substrate and eventual publication of the protocol-defined artifacts, and the recurrence/reduction/totality/collapse chain closes that route formally. That is the precise sense in which the classical $n > 3f$ / $f < n/3$ barrier stops being load-bearing here: the promoted theorem no longer takes dense honest-supermajority intersection as its main agreement carrier. The paper is not claiming that the bare DLS / PBFT lower bound has been refuted inside its original model. The theorem reading is therefore: same promoted agreement sentence, different safety carrier.
The correct one-line summary is:
AFT is a proof-carrying, guardian-backed, omission-dominant consensus and settlement family in which base finality, canonical ordering, and irreversible-effect release are separated and then recomposed through shared evidence.
Embedded Formal Artifacts
This appendix embeds verbatim every proof artifact referenced by name in the yellow paper, together with the repository path from which it is sourced. The goal is to keep the served paper self-contained even when it is read outside the repository. The artifacts are grouped by protocol surface and rendered with line numbers so the appendix reads as a standalone proof bundle rather than as a raw repository dump.
GuardianMajority
Core guardian-backed base-finality model and proof.
GuardianMajorityProof.tla
Repository path: docs/architecture/protocols/aft/formal/guardian_majority/GuardianMajorityProof.tla
---- MODULE GuardianMajorityProof ----
EXTENDS Naturals, FiniteSets, TLAPS
CONSTANT Validators, Blocks, Slots, Epochs, QuorumSize
ASSUME QuorumIntersection ==
\A S, T \in SUBSET Validators :
/\ Cardinality(S) >= QuorumSize
/\ Cardinality(T) >= QuorumSize
=> S \cap T # {}
VARIABLES votes, certs
vars == <<votes, certs>>
VoteDomain == Validators \X Slots \X Blocks \X Epochs
CertDomain == Slots \X Blocks \X Epochs \X (SUBSET Validators)
Init ==
/\ votes = {}
/\ certs = {}
HasVote(v, s) ==
\E b \in Blocks, e \in Epochs : <<v, s, b, e>> \in votes
VoteStep ==
\E v \in Validators, s \in Slots, b \in Blocks, e \in Epochs :
/\ ~HasVote(v, s)
/\ votes' = votes \cup {<<v, s, b, e>>}
/\ UNCHANGED certs
CertifyStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, Q \in SUBSET Validators :
/\ Cardinality(Q) >= QuorumSize
/\ \A v \in Q : <<v, s, b, e>> \in votes
/\ certs' = certs \cup {<<s, b, e, Q>>}
/\ UNCHANGED votes
Next == VoteStep \/ CertifyStep
TypeInvariant ==
/\ votes \subseteq VoteDomain
/\ certs \subseteq CertDomain
NoDualVotes ==
\A v \in Validators, s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
=> /\ b1 = b2
/\ e1 = e2
CertSoundness ==
\A s \in Slots, b \in Blocks, e \in Epochs, Q \in SUBSET Validators :
<<s, b, e, Q>> \in certs
=> /\ Cardinality(Q) >= QuorumSize
/\ \A v \in Q : <<v, s, b, e>> \in votes
Invariant == TypeInvariant /\ NoDualVotes /\ CertSoundness
Safety ==
\A s \in Slots,
b1 \in Blocks,
b2 \in Blocks,
e1 \in Epochs,
e2 \in Epochs,
Q1 \in SUBSET Validators,
Q2 \in SUBSET Validators :
/\ <<s, b1, e1, Q1>> \in certs
/\ <<s, b2, e2, Q2>> \in certs
=> /\ b1 = b2
/\ e1 = e2
Spec == Init /\ [][Next]_vars
THEOREM InitImpliesTypeInvariant == Init => TypeInvariant
BY SMTT(30) DEF Init, TypeInvariant, VoteDomain, CertDomain
THEOREM InitImpliesNoDualVotes == Init => NoDualVotes
BY DEF Init, NoDualVotes
THEOREM InitImpliesCertSoundness == Init => CertSoundness
BY DEF Init, CertSoundness
THEOREM InitImpliesInvariant == Init => Invariant
BY InitImpliesTypeInvariant, InitImpliesNoDualVotes,
InitImpliesCertSoundness DEF Invariant
THEOREM VotePreservesTypeInvariant == TypeInvariant /\ VoteStep => TypeInvariant'
BY SMTT(30) DEF TypeInvariant, VoteStep, HasVote, VoteDomain, CertDomain
THEOREM VotePreservesNoDualVotes == NoDualVotes /\ VoteStep => NoDualVotes'
BY SMTT(30) DEF NoDualVotes, VoteStep, HasVote
THEOREM VotePreservesCertSoundness == CertSoundness /\ VoteStep => CertSoundness'
BY DEF CertSoundness, VoteStep
THEOREM VotePreservesInvariant == Invariant /\ VoteStep => Invariant'
BY VotePreservesTypeInvariant, VotePreservesNoDualVotes,
VotePreservesCertSoundness DEF Invariant
THEOREM CertifyPreservesTypeInvariant == TypeInvariant /\ CertifyStep => TypeInvariant'
BY SMTT(30) DEF TypeInvariant, CertifyStep, VoteDomain, CertDomain
THEOREM CertifyPreservesNoDualVotes == NoDualVotes /\ CertifyStep => NoDualVotes'
BY DEF NoDualVotes, CertifyStep
THEOREM CertifyPreservesCertSoundness == CertSoundness /\ CertifyStep => CertSoundness'
BY SMTT(30) DEF CertSoundness, CertifyStep
THEOREM CertifyPreservesInvariant == Invariant /\ CertifyStep => Invariant'
BY CertifyPreservesTypeInvariant, CertifyPreservesNoDualVotes,
CertifyPreservesCertSoundness DEF Invariant
THEOREM StepPreservesInvariant == Invariant /\ Next => Invariant'
BY VotePreservesInvariant, CertifyPreservesInvariant DEF Next
THEOREM StutterPreservesTypeInvariant ==
TypeInvariant /\ UNCHANGED vars => TypeInvariant'
BY DEF TypeInvariant, vars
THEOREM StutterPreservesNoDualVotes ==
NoDualVotes /\ UNCHANGED vars => NoDualVotes'
BY DEF NoDualVotes, vars
THEOREM StutterPreservesCertSoundness ==
CertSoundness /\ UNCHANGED vars => CertSoundness'
BY DEF CertSoundness, vars
THEOREM StutterPreservesInvariant == Invariant /\ UNCHANGED vars => Invariant'
BY StutterPreservesTypeInvariant, StutterPreservesNoDualVotes,
StutterPreservesCertSoundness DEF Invariant
THEOREM NextPreservesInvariant == Invariant /\ [Next]_vars => Invariant'
BY StepPreservesInvariant, StutterPreservesInvariant DEF vars
THEOREM QuorumCertificatesIntersect ==
\A s \in Slots,
b1 \in Blocks,
b2 \in Blocks,
e1 \in Epochs,
e2 \in Epochs,
Q1 \in SUBSET Validators,
Q2 \in SUBSET Validators :
/\ Invariant
/\ <<s, b1, e1, Q1>> \in certs
/\ <<s, b2, e2, Q2>> \in certs
=> Q1 \cap Q2 # {}
BY SMTT(60), QuorumIntersection DEF Invariant, CertSoundness
THEOREM InvariantImpliesSafety == Invariant => Safety
BY SMTT(60), QuorumCertificatesIntersect DEF Invariant, Safety, NoDualVotes,
CertSoundness
====
GuardianMajority.tla
Repository path: docs/architecture/protocols/aft/formal/guardian_majority/GuardianMajority.tla
---- MODULE GuardianMajority ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Blocks, Slots, Epochs, QuorumSize, InitialEpoch
ASSUME InitialEpochInEpochs == InitialEpoch \in Epochs
ASSUME QuorumIntersection ==
\A S, T \in SUBSET Validators :
/\ Cardinality(S) >= QuorumSize
/\ Cardinality(T) >= QuorumSize
=> S \cap T # {}
VARIABLES votes, finalized, finalizerSets, registryEpoch, manifestEpoch, guardianReady, checkpointLevel
vars == <<votes, finalized, finalizerSets, registryEpoch, manifestEpoch, guardianReady, checkpointLevel>>
CheckpointLevels == 0..2
VoteEvent(v, s, b, e) == <<v, s, b, e>>
Finalization(s, b, e) == <<s, b, e>>
VoteDomain == {VoteEvent(v, s, b, e) : v \in Validators, s \in Slots, b \in Blocks, e \in Epochs}
FinalizationDomain == {Finalization(s, b, e) : s \in Slots, b \in Blocks, e \in Epochs}
Init ==
/\ votes = {}
/\ finalized = {}
/\ finalizerSets = [f \in FinalizationDomain |-> {}]
/\ registryEpoch = [v \in Validators |-> InitialEpoch]
/\ manifestEpoch = [v \in Validators |-> InitialEpoch]
/\ guardianReady = [v \in Validators |-> TRUE]
/\ checkpointLevel = [v \in Validators |-> 1]
HasVote(v, s) ==
\E b \in Blocks, e \in Epochs : VoteEvent(v, s, b, e) \in votes
CanVote(v, s, b, e) ==
/\ v \in Validators
/\ s \in Slots
/\ b \in Blocks
/\ e \in Epochs
/\ guardianReady[v]
/\ checkpointLevel[v] > 0
/\ registryEpoch[v] = e
/\ manifestEpoch[v] = e
/\ ~HasVote(v, s)
Vote(v, s, b, e) ==
/\ CanVote(v, s, b, e)
/\ votes' = votes \cup {VoteEvent(v, s, b, e)}
/\ UNCHANGED <<finalized, finalizerSets, registryEpoch, manifestEpoch, guardianReady, checkpointLevel>>
EligibleVoters(s, b, e) ==
{v \in Validators :
/\ VoteEvent(v, s, b, e) \in votes
/\ guardianReady[v]
/\ checkpointLevel[v] > 0
/\ registryEpoch[v] = e
/\ manifestEpoch[v] = e}
CanFinalize(s, b, e) ==
/\ s \in Slots
/\ b \in Blocks
/\ e \in Epochs
/\ Cardinality(EligibleVoters(s, b, e)) >= QuorumSize
Finalize(s, b, e) ==
/\ CanFinalize(s, b, e)
/\ finalized' = finalized \cup {Finalization(s, b, e)}
/\ finalizerSets' = [finalizerSets EXCEPT ![Finalization(s, b, e)] = EligibleVoters(s, b, e)]
/\ UNCHANGED <<votes, registryEpoch, manifestEpoch, guardianReady, checkpointLevel>>
AdoptEpoch(v, e) ==
/\ v \in Validators
/\ e \in Epochs
/\ e >= registryEpoch[v]
/\ registryEpoch' = [registryEpoch EXCEPT ![v] = e]
/\ manifestEpoch' = [manifestEpoch EXCEPT ![v] = e]
/\ UNCHANGED <<votes, finalized, finalizerSets, guardianReady, checkpointLevel>>
RegistryRollback(v, e) ==
/\ v \in Validators
/\ e \in Epochs
/\ e < registryEpoch[v]
/\ registryEpoch' = [registryEpoch EXCEPT ![v] = e]
/\ UNCHANGED <<votes, finalized, finalizerSets, manifestEpoch, guardianReady, checkpointLevel>>
ManifestRollback(v, e) ==
/\ v \in Validators
/\ e \in Epochs
/\ e < manifestEpoch[v]
/\ manifestEpoch' = [manifestEpoch EXCEPT ![v] = e]
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, guardianReady, checkpointLevel>>
GuardianOutage(v) ==
/\ v \in Validators
/\ guardianReady[v]
/\ guardianReady' = [guardianReady EXCEPT ![v] = FALSE]
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, manifestEpoch, checkpointLevel>>
GuardianRecovery(v) ==
/\ v \in Validators
/\ ~guardianReady[v]
/\ guardianReady' = [guardianReady EXCEPT ![v] = TRUE]
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, manifestEpoch, checkpointLevel>>
AdvanceCheckpoint(v, level) ==
/\ v \in Validators
/\ level \in CheckpointLevels
/\ level > checkpointLevel[v]
/\ checkpointLevel' = [checkpointLevel EXCEPT ![v] = level]
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, manifestEpoch, guardianReady>>
CheckpointRollback(v, level) ==
/\ v \in Validators
/\ level \in CheckpointLevels
/\ level < checkpointLevel[v]
/\ checkpointLevel' = [checkpointLevel EXCEPT ![v] = level]
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, manifestEpoch, guardianReady>>
Next ==
\/ \E v \in Validators, s \in Slots, b \in Blocks, e \in Epochs : Vote(v, s, b, e)
\/ \E s \in Slots, b \in Blocks, e \in Epochs : Finalize(s, b, e)
\/ \E v \in Validators, e \in Epochs : AdoptEpoch(v, e)
\/ \E v \in Validators, e \in Epochs : RegistryRollback(v, e)
\/ \E v \in Validators, e \in Epochs : ManifestRollback(v, e)
\/ \E v \in Validators : GuardianOutage(v)
\/ \E v \in Validators : GuardianRecovery(v)
\/ \E v \in Validators, level \in CheckpointLevels : AdvanceCheckpoint(v, level)
\/ \E v \in Validators, level \in CheckpointLevels : CheckpointRollback(v, level)
TypeInvariant ==
/\ votes \subseteq VoteDomain
/\ finalized \subseteq FinalizationDomain
/\ finalizerSets \in [FinalizationDomain -> SUBSET Validators]
/\ registryEpoch \in [Validators -> Epochs]
/\ manifestEpoch \in [Validators -> Epochs]
/\ guardianReady \in [Validators -> BOOLEAN]
/\ checkpointLevel \in [Validators -> CheckpointLevels]
NoDualVotes ==
\A v \in Validators, s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ VoteEvent(v, s, b1, e1) \in votes
/\ VoteEvent(v, s, b2, e2) \in votes
=> /\ b1 = b2
/\ e1 = e2
FinalizationWitnessSoundness ==
\A s \in Slots, b \in Blocks, e \in Epochs :
Finalization(s, b, e) \in finalized
=> /\ Cardinality(finalizerSets[Finalization(s, b, e)]) >= QuorumSize
/\ \A v \in finalizerSets[Finalization(s, b, e)] :
VoteEvent(v, s, b, e) \in votes
Invariant == TypeInvariant /\ NoDualVotes /\ FinalizationWitnessSoundness
Safety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ Finalization(s, b1, e1) \in finalized
/\ Finalization(s, b2, e2) \in finalized
=> b1 = b2
Spec ==
Init /\ [][Next]_vars
THEOREM OneInCheckpointLevels == 1 \in CheckpointLevels
BY SMT DEF CheckpointLevels
THEOREM InitImpliesInvariant == Init => Invariant
PROOF
<1>1. Init => TypeInvariant
BY SMT, InitialEpochInEpochs, OneInCheckpointLevels
DEF Init, TypeInvariant, VoteDomain, FinalizationDomain
<1>2. Init => NoDualVotes
BY DEF Init, NoDualVotes
<1>3. Init => FinalizationWitnessSoundness
BY DEF Init, FinalizationWitnessSoundness
<1>4. QED
BY <1>1, <1>2, <1>3 DEF Invariant
THEOREM StepPreservesTypeInvariant == Invariant /\ Next => TypeInvariant'
BY SMTT(30) DEF Invariant, TypeInvariant, Next, Vote, Finalize, AdoptEpoch,
RegistryRollback, ManifestRollback, GuardianOutage, GuardianRecovery,
AdvanceCheckpoint, CheckpointRollback, CanVote, HasVote, CanFinalize,
EligibleVoters, VoteEvent, Finalization, VoteDomain, FinalizationDomain
THEOREM StepPreservesNoDualVotes == Invariant /\ Next => NoDualVotes'
BY SMT DEF Invariant, NoDualVotes, Next, Vote, Finalize, AdoptEpoch,
RegistryRollback, ManifestRollback, GuardianOutage, GuardianRecovery,
AdvanceCheckpoint, CheckpointRollback, CanVote, HasVote, VoteEvent
THEOREM StepPreservesFinalizationWitnessSoundness ==
Invariant /\ Next => FinalizationWitnessSoundness'
BY SMTT(30) DEF Invariant, FinalizationWitnessSoundness, Next, Vote, Finalize,
AdoptEpoch, RegistryRollback, ManifestRollback, GuardianOutage,
GuardianRecovery, AdvanceCheckpoint, CheckpointRollback,
CanFinalize, EligibleVoters, VoteEvent, Finalization
THEOREM StutterPreservesInvariant == Invariant /\ UNCHANGED vars => Invariant'
BY SMT DEF Invariant, vars
THEOREM NextPreservesInvariant == Invariant /\ [Next]_vars => Invariant'
PROOF
<1>1. Invariant /\ Next => Invariant'
BY StepPreservesTypeInvariant, StepPreservesNoDualVotes,
StepPreservesFinalizationWitnessSoundness DEF Invariant
<1>2. Invariant /\ UNCHANGED vars => Invariant'
BY StutterPreservesInvariant
<1>3. QED
BY <1>1, <1>2 DEF vars
THEOREM FinalizedWitnessesIntersect ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ Invariant
/\ <<s, b1, e1>> \in finalized
/\ <<s, b2, e2>> \in finalized
=> \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
PROOF
<1>1. TAKE s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs
<1>2. ASSUME Invariant,
<<s, b1, e1>> \in finalized,
<<s, b2, e2>> \in finalized
PROVE \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
<2>1. finalizerSets[<<s, b1, e1>>] \subseteq Validators
BY SMT, <1>2 DEF Invariant, TypeInvariant, FinalizationDomain, Finalization
<2>2. finalizerSets[<<s, b2, e2>>] \subseteq Validators
BY SMT, <1>2 DEF Invariant, TypeInvariant, FinalizationDomain, Finalization
<2>3. Cardinality(finalizerSets[<<s, b1, e1>>]) >= QuorumSize
BY SMT, <1>2 DEF Invariant, FinalizationWitnessSoundness
<2>4. Cardinality(finalizerSets[<<s, b2, e2>>]) >= QuorumSize
BY SMT, <1>2 DEF Invariant, FinalizationWitnessSoundness
<2>5. finalizerSets[<<s, b1, e1>>] \cap finalizerSets[<<s, b2, e2>>] # {}
BY <2>1, <2>2, <2>3, <2>4, QuorumIntersection
<2>6. PICK v \in finalizerSets[<<s, b1, e1>>] \cap finalizerSets[<<s, b2, e2>>] : TRUE
BY <2>5
<2>7. <<v, s, b1, e1>> \in votes
BY SMT, <1>2, <2>6 DEF Invariant, FinalizationWitnessSoundness
<2>8. <<v, s, b2, e2>> \in votes
BY SMT, <1>2, <2>6 DEF Invariant, FinalizationWitnessSoundness
<2>9. QED
BY SMT, <2>6, <2>7, <2>8
<1>3. QED
BY <1>2
THEOREM InvariantImpliesSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ Invariant
/\ <<s, b1, e1>> \in finalized
/\ <<s, b2, e2>> \in finalized
=> /\ b1 = b2
/\ e1 = e2
PROOF
<1>1. TAKE s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs
<1>2. ASSUME Invariant,
<<s, b1, e1>> \in finalized,
<<s, b2, e2>> \in finalized
PROVE /\ b1 = b2
/\ e1 = e2
<2>1. \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
BY SMT, FinalizedWitnessesIntersect, <1>2
<2>2. PICK v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
BY <2>1
<2>3. QED
BY SMT, <1>2, <2>2 DEF Invariant, NoDualVotes
<1>3. QED
BY <1>2
====
CanonicalOrdering
Proof-carrying ordering model and its main proof surface.
CanonicalOrderingProof.tla
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrderingProof.tla
---- MODULE CanonicalOrderingProof ----
EXTENDS Naturals, FiniteSets, TLAPS
CONSTANT Slots, Transactions
VARIABLES bulletins, closedCutoffs, admittedCerts, omissionProofs, recoveredSets
vars == <<bulletins, closedCutoffs, admittedCerts, omissionProofs, recoveredSets>>
CertEvent(s, c) == <<s, c>>
OmissionEvent(s, c, tx) == <<s, c, tx>>
CanonicalSet(s) == bulletins[s]
RecoverableSet(s) == IF s \in closedCutoffs THEN CanonicalSet(s) ELSE {}
BulletinDomain == [Slots -> SUBSET Transactions]
CutoffDomain == SUBSET Slots
CertDomain == Slots \X (SUBSET Transactions)
OmissionDomain == Slots \X (SUBSET Transactions) \X Transactions
RecoveredDomain == [Slots -> SUBSET Transactions]
TypeInvariant ==
/\ bulletins \in BulletinDomain
/\ closedCutoffs \in CutoffDomain
/\ admittedCerts \subseteq CertDomain
/\ omissionProofs \subseteq OmissionDomain
/\ recoveredSets \in RecoveredDomain
CertifiedSoundness ==
\A s \in Slots, c \in SUBSET Transactions :
CertEvent(s, c) \in admittedCerts
=> /\ s \in closedCutoffs
/\ c = CanonicalSet(s)
OmissionSoundness ==
\A s \in Slots, c \in SUBSET Transactions, tx \in Transactions :
OmissionEvent(s, c, tx) \in omissionProofs
=> /\ s \in closedCutoffs
/\ tx \in CanonicalSet(s)
/\ tx \notin c
RecoveredSoundness ==
\A s \in Slots :
recoveredSets[s] = RecoverableSet(s)
Invariant ==
/\ TypeInvariant
/\ CertifiedSoundness
/\ OmissionSoundness
/\ RecoveredSoundness
CertifiedUniqueness ==
\A s \in Slots, c1 \in SUBSET Transactions, c2 \in SUBSET Transactions :
/\ CertEvent(s, c1) \in admittedCerts
/\ CertEvent(s, c2) \in admittedCerts
=> c1 = c2
Recoverability ==
\A s \in Slots, c \in SUBSET Transactions :
CertEvent(s, c) \in admittedCerts
=> recoveredSets[s] = c
OmissionDominates ==
\A s \in Slots, c \in SUBSET Transactions, tx \in Transactions :
OmissionEvent(s, c, tx) \in omissionProofs
=> CertEvent(s, c) \notin admittedCerts
THEOREM InvariantImpliesCertifiedUniqueness ==
Invariant => CertifiedUniqueness
BY SMTT(60)
DEF Invariant, CertifiedUniqueness, CertifiedSoundness
THEOREM InvariantImpliesRecoverability ==
Invariant => Recoverability
BY SMTT(60)
DEF Invariant, Recoverability, CertifiedSoundness, RecoveredSoundness, RecoverableSet
THEOREM InvariantImpliesOmissionDominates ==
Invariant => OmissionDominates
BY SMTT(60)
DEF Invariant, OmissionDominates, CertifiedSoundness, OmissionSoundness
====
CanonicalOrdering.tla
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrdering.tla
---- MODULE CanonicalOrdering ----
EXTENDS Naturals, FiniteSets, TLC
CONSTANT Slots, Transactions
VARIABLES bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs
vars ==
<<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
CertEvent(s, c) == <<s, c>>
NoParent == [kind |-> "none", cert |-> {}]
ParentCert(c) == [kind |-> "cert", cert |-> c]
FrontierEvent(s, c, p) == [slot |-> s, cert |-> c, parentCert |-> p]
FrontierConflict(f1, f2) == [kind |-> "conflict", candidate |-> f1, reference |-> f2]
StaleFrontier(f, prev) == [kind |-> "stale", candidate |-> f, reference |-> prev]
OmissionEvent(s, c, tx) == <<s, c, tx>>
WitnessSlot(w) == w.candidate.slot
HasFrontierContradiction(s) == \E w \in frontierContradictions : WitnessSlot(w) = s
FirstSlot == CHOOSE min \in Slots : \A s \in Slots : min <= s
PredecessorClosed(s) == s = FirstSlot \/ s - 1 \in bulletinCloses
CanonicalSet(s) == bulletin[s]
BulletinDomain == [Slots -> SUBSET Transactions]
CutoffDomain == SUBSET Slots
AvailabilityDomain == SUBSET Slots
BulletinCloseDomain == SUBSET Slots
CertDomain == Slots \X (SUBSET Transactions)
ParentRefDomain == [kind : {"none", "cert"}, cert : SUBSET Transactions]
FrontierDomain == [slot : Slots, cert : SUBSET Transactions, parentCert : ParentRefDomain]
ContradictionDomain == [kind : {"conflict", "stale"}, candidate : FrontierDomain, reference : FrontierDomain]
OmissionDomain == Slots \X (SUBSET Transactions) \X Transactions
ParentChoices(s) ==
IF s = FirstSlot
THEN {NoParent}
ELSE
{p \in ParentRefDomain :
p = NoParent
\/ (\E f \in publicationFrontiers : /\ f.slot + 1 = s
/\ p = ParentCert(f.cert))}
Init ==
/\ bulletin = [s \in Slots |-> {}]
/\ closedCutoffs = {}
/\ availabilityCerts = {}
/\ bulletinCloses = {}
/\ candidateCerts = {}
/\ publicationFrontiers = {}
/\ frontierContradictions = {}
/\ admittedCerts = {}
/\ omissionProofs = {}
PublishStep ==
\E s \in Slots, tx \in Transactions :
/\ PredecessorClosed(s)
/\ s \notin closedCutoffs
/\ tx \notin bulletin[s]
/\ bulletin' = [bulletin EXCEPT ![s] = @ \cup {tx}]
/\ UNCHANGED <<closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
CloseCutoffStep ==
\E s \in Slots :
/\ PredecessorClosed(s)
/\ s \notin closedCutoffs
/\ closedCutoffs' = closedCutoffs \cup {s}
/\ UNCHANGED <<bulletin, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
AvailabilityCertifyStep ==
\E s \in Slots :
/\ PredecessorClosed(s)
/\ s \in closedCutoffs
/\ s \notin availabilityCerts
/\ availabilityCerts' = availabilityCerts \cup {s}
/\ UNCHANGED <<bulletin, closedCutoffs, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
CanonicalBulletinCloseStep ==
\E s \in Slots :
/\ PredecessorClosed(s)
/\ s \in availabilityCerts
/\ s \notin bulletinCloses
/\ bulletinCloses' = bulletinCloses \cup {s}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
CandidateCertifyStep ==
\E s \in Slots :
\E c \in SUBSET bulletin[s] :
/\ PredecessorClosed(s)
/\ s \in bulletinCloses
/\ CertEvent(s, c) \notin candidateCerts
/\ candidateCerts' = candidateCerts \cup {CertEvent(s, c)}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, publicationFrontiers, frontierContradictions, admittedCerts, omissionProofs>>
PublishFrontierStep ==
\E e \in candidateCerts :
LET s == e[1]
c == e[2]
IN
\E p \in ParentChoices(s) :
/\ s \in bulletinCloses
/\ (s = FirstSlot
\/ \E prev \in publicationFrontiers : prev.slot + 1 = s)
/\ FrontierEvent(s, c, p) \notin publicationFrontiers
/\ publicationFrontiers' = publicationFrontiers \cup {FrontierEvent(s, c, p)}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, frontierContradictions, admittedCerts, omissionProofs>>
ProveFrontierConflictStep ==
\E f1 \in publicationFrontiers, f2 \in publicationFrontiers :
/\ f1.slot = f2.slot
/\ f1 # f2
/\ FrontierConflict(f1, f2) \notin frontierContradictions
/\ frontierContradictions' = frontierContradictions \cup {FrontierConflict(f1, f2)}
/\ admittedCerts' = {e \in admittedCerts : e[1] # f1.slot}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, omissionProofs>>
ProveStaleFrontierStep ==
\E f \in publicationFrontiers, prev \in publicationFrontiers :
/\ prev.slot + 1 = f.slot
/\ f.parentCert # ParentCert(prev.cert)
/\ StaleFrontier(f, prev) \notin frontierContradictions
/\ frontierContradictions' = frontierContradictions \cup {StaleFrontier(f, prev)}
/\ admittedCerts' = {e \in admittedCerts : e[1] # f.slot}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, omissionProofs>>
ProveOmissionStep ==
\E s \in Slots, c \in SUBSET Transactions, tx \in Transactions :
/\ CertEvent(s, c) \in candidateCerts
/\ tx \in CanonicalSet(s)
/\ tx \notin c
/\ OmissionEvent(s, c, tx) \notin omissionProofs
/\ omissionProofs' = omissionProofs \cup {OmissionEvent(s, c, tx)}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, admittedCerts>>
AdmitCertStep ==
\E s \in Slots :
\E c \in SUBSET Transactions :
/\ CertEvent(s, c) \in candidateCerts
/\ s \in bulletinCloses
/\ \E f \in publicationFrontiers : /\ f.slot = s /\ f.cert = c
/\ ~HasFrontierContradiction(s)
/\ c = CanonicalSet(s)
/\ ~(\E tx \in Transactions : OmissionEvent(s, c, tx) \in omissionProofs)
/\ CertEvent(s, c) \notin admittedCerts
/\ admittedCerts' = admittedCerts \cup {CertEvent(s, c)}
/\ UNCHANGED <<bulletin, closedCutoffs, availabilityCerts, bulletinCloses, candidateCerts, publicationFrontiers, frontierContradictions, omissionProofs>>
Next ==
\/ PublishStep
\/ CloseCutoffStep
\/ AvailabilityCertifyStep
\/ CanonicalBulletinCloseStep
\/ CandidateCertifyStep
\/ PublishFrontierStep
\/ ProveFrontierConflictStep
\/ ProveStaleFrontierStep
\/ ProveOmissionStep
\/ AdmitCertStep
TypeInvariant ==
/\ bulletin \in BulletinDomain
/\ closedCutoffs \in CutoffDomain
/\ availabilityCerts \in AvailabilityDomain
/\ bulletinCloses \in BulletinCloseDomain
/\ candidateCerts \subseteq CertDomain
/\ publicationFrontiers \subseteq FrontierDomain
/\ frontierContradictions \subseteq ContradictionDomain
/\ admittedCerts \subseteq CertDomain
/\ omissionProofs \subseteq OmissionDomain
AvailabilityCertSoundness ==
\A s \in Slots :
s \in availabilityCerts => s \in closedCutoffs
CanonicalBulletinCloseSoundness ==
\A s \in Slots :
s \in bulletinCloses => s \in availabilityCerts
FrontierSoundness ==
\A f \in publicationFrontiers :
/\ f.slot \in bulletinCloses
/\ CertEvent(f.slot, f.cert) \in candidateCerts
FrontierConflictSoundness ==
\A w \in frontierContradictions :
w.kind = "conflict"
=> /\ w.candidate.slot = w.reference.slot
/\ w.candidate # w.reference
StaleFrontierSoundness ==
\A w \in frontierContradictions :
w.kind = "stale"
=> /\ w.reference.slot + 1 = w.candidate.slot
/\ w.candidate.parentCert # ParentCert(w.reference.cert)
AdmittedSoundness ==
\A s \in Slots, c \in SUBSET Transactions :
CertEvent(s, c) \in admittedCerts
=> /\ s \in bulletinCloses
/\ c = CanonicalSet(s)
/\ \E f \in publicationFrontiers : /\ f.slot = s /\ f.cert = c
/\ ~HasFrontierContradiction(s)
OmissionSoundness ==
\A s \in Slots, c \in SUBSET Transactions, tx \in Transactions :
OmissionEvent(s, c, tx) \in omissionProofs
=> /\ s \in closedCutoffs
/\ tx \in CanonicalSet(s)
/\ tx \notin c
AdmittedUniqueness ==
\A s \in Slots, c1 \in SUBSET Transactions, c2 \in SUBSET Transactions :
/\ CertEvent(s, c1) \in admittedCerts
/\ CertEvent(s, c2) \in admittedCerts
=> c1 = c2
OmissionDominates ==
\A s \in Slots, c \in SUBSET Transactions, tx \in Transactions :
OmissionEvent(s, c, tx) \in omissionProofs
=> CertEvent(s, c) \notin admittedCerts
FrontierContradictionDominates ==
\A s \in Slots, c \in SUBSET Transactions :
HasFrontierContradiction(s)
=> CertEvent(s, c) \notin admittedCerts
\* Full endogenous retrievability now lives in CanonicalOrderingRetrievability.tla.
\* These names remain as explicit boundary markers so this compact-frontier
\* executable model keeps checking the hot-path theorem surface without
\* duplicating the retrievability-plane state machine here.
RecoveredSoundness == \A s \in Slots : bulletin[s] = bulletin[s]
Recoverability == \A s \in Slots : bulletin[s] = bulletin[s]
WitnessBound ==
/\ Cardinality(candidateCerts) <= 4
/\ Cardinality(publicationFrontiers) <= 3
/\ Cardinality(frontierContradictions) <= 2
/\ Cardinality(omissionProofs) <= 1
Invariant ==
/\ TypeInvariant
/\ AvailabilityCertSoundness
/\ CanonicalBulletinCloseSoundness
/\ FrontierSoundness
/\ FrontierConflictSoundness
/\ StaleFrontierSoundness
/\ AdmittedSoundness
/\ OmissionSoundness
/\ AdmittedUniqueness
/\ OmissionDominates
/\ FrontierContradictionDominates
Spec == Init /\ [][Next]_vars
====
Asymptote
Sealed-finality model and proof artifact pair.
AsymptoteProof.tla
Repository path: docs/architecture/protocols/aft/formal/AsymptoteProof.tla
---- MODULE AsymptoteProof ----
EXTENDS Naturals, FiniteSets, TLAPS
CONSTANT Blocks, Slots, Epochs, TranscriptRoots, ChallengeRoots, EmptyChallengeRoot
ASSUME EmptyChallengeRoot \in ChallengeRoots
VARIABLES baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedCerts
vars ==
<<baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedCerts>>
BaseCertDomain == Slots \X Blocks \X Epochs
TranscriptSurfaceDomain == Slots \X Blocks \X Epochs \X TranscriptRoots
ChallengeSurfaceDomain == Slots \X Blocks \X Epochs \X ChallengeRoots
CanonicalCloseDomain == Slots \X Blocks \X Epochs \X TranscriptRoots
CanonicalAbortDomain ==
Slots \X Blocks \X Epochs \X TranscriptRoots \X (ChallengeRoots \ {EmptyChallengeRoot})
SealedCertDomain == Slots \X Blocks \X Epochs
BaseCertEvent(s, b, e) == <<s, b, e>>
TranscriptSurfaceEvent(s, b, e, t) == <<s, b, e, t>>
ChallengeSurfaceEvent(s, b, e, c) == <<s, b, e, c>>
CanonicalCloseEvent(s, b, e, t) == <<s, b, e, t>>
CanonicalAbortEvent(s, b, e, t, c) == <<s, b, e, t, c>>
SealEvent(s, b, e) == <<s, b, e>>
Init ==
/\ baseCerts = {}
/\ transcriptSurfaces = {}
/\ challengeSurfaces = {}
/\ canonicalCloses = {}
/\ canonicalAborts = {}
/\ sealedCerts = {}
HasBaseCert(s) ==
\E b \in Blocks, e \in Epochs : BaseCertEvent(s, b, e) \in baseCerts
HasTranscriptSurface(s) ==
\E b \in Blocks, e \in Epochs, t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
HasChallengeSurface(s) ==
\E b \in Blocks, e \in Epochs, c \in ChallengeRoots :
ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
HasCanonicalOutcome(s) ==
\/ \E b \in Blocks, e \in Epochs, t \in TranscriptRoots :
CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
\/ \E b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
HasCanonicalAbort(s) ==
\E b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
BaseCertifyStep ==
\E s \in Slots, b \in Blocks, e \in Epochs :
/\ ~HasBaseCert(s)
/\ baseCerts' = baseCerts \cup {BaseCertEvent(s, b, e)}
/\ UNCHANGED <<transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedCerts>>
TranscriptSurfaceStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
/\ BaseCertEvent(s, b, e) \in baseCerts
/\ ~HasTranscriptSurface(s)
/\ transcriptSurfaces' =
transcriptSurfaces \cup {TranscriptSurfaceEvent(s, b, e, t)}
/\ UNCHANGED <<baseCerts, challengeSurfaces, canonicalCloses,
canonicalAborts, sealedCerts>>
ChallengeSurfaceStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ~HasChallengeSurface(s)
/\ challengeSurfaces' =
challengeSurfaces \cup {ChallengeSurfaceEvent(s, b, e, c)}
/\ UNCHANGED <<baseCerts, transcriptSurfaces, canonicalCloses,
canonicalAborts, sealedCerts>>
CanonicalCloseStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, EmptyChallengeRoot) \in challengeSurfaces
/\ ~HasCanonicalOutcome(s)
/\ canonicalCloses' = canonicalCloses \cup {CanonicalCloseEvent(s, b, e, t)}
/\ UNCHANGED <<baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalAborts, sealedCerts>>
CanonicalAbortStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
/\ ~HasCanonicalOutcome(s)
/\ canonicalAborts' =
canonicalAborts \cup {CanonicalAbortEvent(s, b, e, t, c)}
/\ UNCHANGED <<baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, sealedCerts>>
SealStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
/\ CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
/\ ~HasCanonicalAbort(s)
/\ sealedCerts' = sealedCerts \cup {SealEvent(s, b, e)}
/\ UNCHANGED <<baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts>>
Next ==
\/ BaseCertifyStep
\/ TranscriptSurfaceStep
\/ ChallengeSurfaceStep
\/ CanonicalCloseStep
\/ CanonicalAbortStep
\/ SealStep
TypeInvariant ==
/\ baseCerts \subseteq BaseCertDomain
/\ transcriptSurfaces \subseteq TranscriptSurfaceDomain
/\ challengeSurfaces \subseteq ChallengeSurfaceDomain
/\ canonicalCloses \subseteq CanonicalCloseDomain
/\ canonicalAborts \subseteq CanonicalAbortDomain
/\ sealedCerts \subseteq SealedCertDomain
NoDualBaseCerts ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ BaseCertEvent(s, b1, e1) \in baseCerts
/\ BaseCertEvent(s, b2, e2) \in baseCerts
=> /\ b1 = b2
/\ e1 = e2
NoDualTranscriptSurfaces ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots :
/\ TranscriptSurfaceEvent(s, b1, e1, t1) \in transcriptSurfaces
/\ TranscriptSurfaceEvent(s, b2, e2, t2) \in transcriptSurfaces
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
NoDualChallengeSurfaces ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
c1 \in ChallengeRoots, c2 \in ChallengeRoots :
/\ ChallengeSurfaceEvent(s, b1, e1, c1) \in challengeSurfaces
/\ ChallengeSurfaceEvent(s, b2, e2, c2) \in challengeSurfaces
=> /\ b1 = b2
/\ e1 = e2
/\ c1 = c2
NoDualCanonicalCloses ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots :
/\ CanonicalCloseEvent(s, b1, e1, t1) \in canonicalCloses
/\ CanonicalCloseEvent(s, b2, e2, t2) \in canonicalCloses
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
NoDualCanonicalAborts ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots,
c1 \in ChallengeRoots \ {EmptyChallengeRoot},
c2 \in ChallengeRoots \ {EmptyChallengeRoot} :
/\ CanonicalAbortEvent(s, b1, e1, t1, c1) \in canonicalAborts
/\ CanonicalAbortEvent(s, b2, e2, t2, c2) \in canonicalAborts
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
/\ c1 = c2
TranscriptAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
=> BaseCertEvent(s, b, e) \in baseCerts
ChallengeAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, c \in ChallengeRoots :
ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
=> \E t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
CanonicalCloseAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
=> /\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, EmptyChallengeRoot) \in challengeSurfaces
CanonicalAbortAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
=> /\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
SealedAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs :
SealEvent(s, b, e) \in sealedCerts
=> /\ \E t \in TranscriptRoots : CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
/\ ~HasCanonicalAbort(s)
CloseAbortExclusive ==
\A s \in Slots, b1 \in Blocks, e1 \in Epochs, t1 \in TranscriptRoots,
b2 \in Blocks, e2 \in Epochs, t2 \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
/\ CanonicalCloseEvent(s, b1, e1, t1) \in canonicalCloses
/\ CanonicalAbortEvent(s, b2, e2, t2, c) \in canonicalAborts
=> FALSE
Invariant ==
/\ TypeInvariant
/\ NoDualBaseCerts
/\ NoDualTranscriptSurfaces
/\ NoDualChallengeSurfaces
/\ NoDualCanonicalCloses
/\ NoDualCanonicalAborts
/\ TranscriptAnchored
/\ ChallengeAnchored
/\ CanonicalCloseAnchored
/\ CanonicalAbortAnchored
/\ CloseAbortExclusive
/\ SealedAnchored
BaseSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ BaseCertEvent(s, b1, e1) \in baseCerts
/\ BaseCertEvent(s, b2, e2) \in baseCerts
=> /\ b1 = b2
/\ e1 = e2
CanonicalCloseSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots :
/\ CanonicalCloseEvent(s, b1, e1, t1) \in canonicalCloses
/\ CanonicalCloseEvent(s, b2, e2, t2) \in canonicalCloses
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
SealedSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ SealEvent(s, b1, e1) \in sealedCerts
/\ SealEvent(s, b2, e2) \in sealedCerts
=> /\ b1 = b2
/\ e1 = e2
AbortDominatesSealed ==
\A s \in Slots, b \in Blocks, e \in Epochs :
HasCanonicalAbort(s) => SealEvent(s, b, e) \notin sealedCerts
Spec == Init /\ [][Next]_vars
THEOREM InvariantImpliesBaseSafety == Invariant => BaseSafety
BY SMTT(50)
DEF Invariant, BaseSafety, NoDualBaseCerts
THEOREM InvariantImpliesCanonicalCloseSafety == Invariant => CanonicalCloseSafety
BY SMTT(60)
DEF Invariant, CanonicalCloseSafety, NoDualCanonicalCloses
THEOREM InvariantImpliesCloseAbortExclusive == Invariant => CloseAbortExclusive
BY SMTT(20)
DEF Invariant, CloseAbortExclusive
THEOREM InvariantImpliesSealedSafety == Invariant => SealedSafety
BY SMTT(60), InvariantImpliesCanonicalCloseSafety
DEF Invariant, SealedSafety, SealedAnchored, CanonicalCloseSafety
THEOREM InvariantImpliesAbortDominatesSealed == Invariant => AbortDominatesSealed
BY SMTT(60)
DEF Invariant, AbortDominatesSealed, SealedAnchored
====
Asymptote.tla
Repository path: docs/architecture/protocols/aft/formal/Asymptote.tla
---- MODULE Asymptote ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Blocks, Slots, Epochs, ValidatorQuorum,
TranscriptRoots, ChallengeRoots, EmptyChallengeRoot
ASSUME EmptyChallengeRoot \in ChallengeRoots
ASSUME ValidatorQuorumIntersection ==
\A S, T \in SUBSET Validators :
/\ Cardinality(S) >= ValidatorQuorum
/\ Cardinality(T) >= ValidatorQuorum
=> S \cap T # {}
CollapsePending == 0
CollapseBase == 1
CollapseObservation == 2
CollapseAbort == 3
CollapseSealed == 4
CollapseStates ==
{CollapsePending, CollapseBase, CollapseObservation, CollapseAbort, CollapseSealed}
VARIABLES validatorVotes, baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedFinal, collapseState
vars ==
<<validatorVotes, baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedFinal, collapseState>>
ValidatorVoteEvent(v, s, b, e) == <<v, s, b, e>>
BaseCertEvent(s, b, e, q) == <<s, b, e, q>>
TranscriptSurfaceEvent(s, b, e, t) == <<s, b, e, t>>
ChallengeSurfaceEvent(s, b, e, c) == <<s, b, e, c>>
CanonicalCloseEvent(s, b, e, t) == <<s, b, e, t>>
CanonicalAbortEvent(s, b, e, t, c) == <<s, b, e, t, c>>
SealEvent(s, b, e) == <<s, b, e>>
ValidatorVoteDomain == Validators \X Slots \X Blocks \X Epochs
BaseCertDomain == Slots \X Blocks \X Epochs \X (SUBSET Validators)
TranscriptSurfaceDomain == Slots \X Blocks \X Epochs \X TranscriptRoots
ChallengeSurfaceDomain == Slots \X Blocks \X Epochs \X ChallengeRoots
CanonicalCloseDomain == Slots \X Blocks \X Epochs \X TranscriptRoots
CanonicalAbortDomain ==
Slots \X Blocks \X Epochs \X TranscriptRoots \X (ChallengeRoots \ {EmptyChallengeRoot})
SealedCertDomain == Slots \X Blocks \X Epochs
Init ==
/\ validatorVotes = {}
/\ baseCerts = {}
/\ transcriptSurfaces = {}
/\ challengeSurfaces = {}
/\ canonicalCloses = {}
/\ canonicalAborts = {}
/\ sealedFinal = {}
/\ collapseState = [s \in Slots |-> CollapsePending]
HasValidatorVote(v, s) ==
\E b \in Blocks, e \in Epochs : ValidatorVoteEvent(v, s, b, e) \in validatorVotes
HasBaseCert(s) ==
\E b \in Blocks, e \in Epochs, q \in SUBSET Validators :
BaseCertEvent(s, b, e, q) \in baseCerts
HasTranscriptSurface(s) ==
\E b \in Blocks, e \in Epochs, t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
HasChallengeSurface(s) ==
\E b \in Blocks, e \in Epochs, c \in ChallengeRoots :
ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
HasCanonicalOutcome(s) ==
\/ \E b \in Blocks, e \in Epochs, t \in TranscriptRoots :
CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
\/ \E b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
HasCanonicalAbort(s) ==
\E b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
ValidatorVoteStep ==
\E v \in Validators, s \in Slots, b \in Blocks, e \in Epochs :
/\ ~HasValidatorVote(v, s)
/\ validatorVotes' = validatorVotes \cup {ValidatorVoteEvent(v, s, b, e)}
/\ UNCHANGED <<baseCerts, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedFinal, collapseState>>
EligibleValidators(s, b, e) ==
{v \in Validators : ValidatorVoteEvent(v, s, b, e) \in validatorVotes}
BaseFinalizeStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, q \in SUBSET Validators :
/\ q = EligibleValidators(s, b, e)
/\ Cardinality(q) >= ValidatorQuorum
/\ baseCerts' = baseCerts \cup {BaseCertEvent(s, b, e, q)}
/\ collapseState' = [collapseState EXCEPT ![s] = CollapseBase]
/\ UNCHANGED <<validatorVotes, transcriptSurfaces, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedFinal>>
TranscriptSurfaceStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, q \in SUBSET Validators,
t \in TranscriptRoots :
/\ BaseCertEvent(s, b, e, q) \in baseCerts
/\ collapseState[s] \in {CollapseBase, CollapseObservation}
/\ ~HasTranscriptSurface(s)
/\ transcriptSurfaces' =
transcriptSurfaces \cup {TranscriptSurfaceEvent(s, b, e, t)}
/\ collapseState' = [collapseState EXCEPT ![s] = CollapseObservation]
/\ UNCHANGED <<validatorVotes, baseCerts, challengeSurfaces,
canonicalCloses, canonicalAborts, sealedFinal>>
ChallengeSurfaceStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ collapseState[s] = CollapseObservation
/\ ~HasChallengeSurface(s)
/\ challengeSurfaces' =
challengeSurfaces \cup {ChallengeSurfaceEvent(s, b, e, c)}
/\ collapseState' = [collapseState EXCEPT ![s] = CollapseObservation]
/\ UNCHANGED <<validatorVotes, baseCerts, transcriptSurfaces,
canonicalCloses, canonicalAborts, sealedFinal>>
CanonicalCloseStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, EmptyChallengeRoot) \in challengeSurfaces
/\ collapseState[s] = CollapseObservation
/\ ~HasCanonicalOutcome(s)
/\ canonicalCloses' = canonicalCloses \cup {CanonicalCloseEvent(s, b, e, t)}
/\ UNCHANGED <<validatorVotes, baseCerts, transcriptSurfaces,
challengeSurfaces, canonicalAborts, sealedFinal, collapseState>>
CanonicalAbortStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
/\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
/\ ~HasCanonicalOutcome(s)
/\ canonicalAborts' =
canonicalAborts \cup {CanonicalAbortEvent(s, b, e, t, c)}
/\ collapseState' = [collapseState EXCEPT ![s] = CollapseAbort]
/\ UNCHANGED <<validatorVotes, baseCerts, transcriptSurfaces,
challengeSurfaces, canonicalCloses, sealedFinal>>
SealStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
/\ CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
/\ ~HasCanonicalAbort(s)
/\ sealedFinal' = sealedFinal \cup {SealEvent(s, b, e)}
/\ collapseState' = [collapseState EXCEPT ![s] = CollapseSealed]
/\ UNCHANGED <<validatorVotes, baseCerts, transcriptSurfaces,
challengeSurfaces, canonicalCloses, canonicalAborts>>
StutterStep == UNCHANGED vars
Next ==
\/ ValidatorVoteStep
\/ BaseFinalizeStep
\/ TranscriptSurfaceStep
\/ ChallengeSurfaceStep
\/ CanonicalCloseStep
\/ CanonicalAbortStep
\/ SealStep
\/ StutterStep
TypeInvariant ==
/\ validatorVotes \subseteq ValidatorVoteDomain
/\ baseCerts \subseteq BaseCertDomain
/\ transcriptSurfaces \subseteq TranscriptSurfaceDomain
/\ challengeSurfaces \subseteq ChallengeSurfaceDomain
/\ canonicalCloses \subseteq CanonicalCloseDomain
/\ canonicalAborts \subseteq CanonicalAbortDomain
/\ sealedFinal \subseteq SealedCertDomain
/\ collapseState \in [Slots -> CollapseStates]
NoDualValidatorVotes ==
\A v \in Validators, s \in Slots, b1 \in Blocks, b2 \in Blocks,
e1 \in Epochs, e2 \in Epochs :
/\ ValidatorVoteEvent(v, s, b1, e1) \in validatorVotes
/\ ValidatorVoteEvent(v, s, b2, e2) \in validatorVotes
=> /\ b1 = b2
/\ e1 = e2
NoDualTranscriptSurfaces ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots :
/\ TranscriptSurfaceEvent(s, b1, e1, t1) \in transcriptSurfaces
/\ TranscriptSurfaceEvent(s, b2, e2, t2) \in transcriptSurfaces
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
NoDualChallengeSurfaces ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
c1 \in ChallengeRoots, c2 \in ChallengeRoots :
/\ ChallengeSurfaceEvent(s, b1, e1, c1) \in challengeSurfaces
/\ ChallengeSurfaceEvent(s, b2, e2, c2) \in challengeSurfaces
=> /\ b1 = b2
/\ e1 = e2
/\ c1 = c2
BaseCertSoundness ==
\A s \in Slots, b \in Blocks, e \in Epochs, q \in SUBSET Validators :
BaseCertEvent(s, b, e, q) \in baseCerts
=> /\ Cardinality(q) >= ValidatorQuorum
/\ \A v \in q : ValidatorVoteEvent(v, s, b, e) \in validatorVotes
TranscriptAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
=> \E q \in SUBSET Validators : BaseCertEvent(s, b, e, q) \in baseCerts
ChallengeAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, c \in ChallengeRoots :
ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
=> \E t \in TranscriptRoots :
TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
CanonicalCloseAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots :
CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
=> /\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, EmptyChallengeRoot) \in challengeSurfaces
CanonicalAbortAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs, t \in TranscriptRoots,
c \in ChallengeRoots \ {EmptyChallengeRoot} :
CanonicalAbortEvent(s, b, e, t, c) \in canonicalAborts
=> /\ TranscriptSurfaceEvent(s, b, e, t) \in transcriptSurfaces
/\ ChallengeSurfaceEvent(s, b, e, c) \in challengeSurfaces
SealedAnchored ==
\A s \in Slots, b \in Blocks, e \in Epochs :
SealEvent(s, b, e) \in sealedFinal
=> /\ \E t \in TranscriptRoots : CanonicalCloseEvent(s, b, e, t) \in canonicalCloses
/\ ~HasCanonicalAbort(s)
BaseSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
q1 \in SUBSET Validators, q2 \in SUBSET Validators :
/\ BaseCertEvent(s, b1, e1, q1) \in baseCerts
/\ BaseCertEvent(s, b2, e2, q2) \in baseCerts
=> /\ b1 = b2
/\ e1 = e2
CanonicalCloseSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs,
t1 \in TranscriptRoots, t2 \in TranscriptRoots :
/\ CanonicalCloseEvent(s, b1, e1, t1) \in canonicalCloses
/\ CanonicalCloseEvent(s, b2, e2, t2) \in canonicalCloses
=> /\ b1 = b2
/\ e1 = e2
/\ t1 = t2
AbortDominatesClose ==
\A s \in Slots :
HasCanonicalAbort(s)
=> ~(\E b \in Blocks, e \in Epochs, t \in TranscriptRoots :
CanonicalCloseEvent(s, b, e, t) \in canonicalCloses)
SealedSafety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ SealEvent(s, b1, e1) \in sealedFinal
/\ SealEvent(s, b2, e2) \in sealedFinal
=> /\ b1 = b2
/\ e1 = e2
AbortDominatesSealed ==
\A s \in Slots, b \in Blocks, e \in Epochs :
HasCanonicalAbort(s) => SealEvent(s, b, e) \notin sealedFinal
MonotoneCollapse ==
/\ \A s \in Slots :
collapseState[s] = CollapseSealed => \E b \in Blocks, e \in Epochs :
SealEvent(s, b, e) \in sealedFinal
/\ \A s \in Slots :
collapseState[s] = CollapseAbort => HasCanonicalAbort(s)
Spec == Init /\ [][Next]_vars
====
NestedGuardian
Witness-augmented layered-threshold model and proof surface.
NestedGuardianProof.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianProof.tla
---- MODULE NestedGuardianProof ----
EXTENDS Naturals, FiniteSets, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialWitness
ASSUME InitialWitnessInWitnesses == InitialWitness \in Witnesses
ASSUME MaxReassignmentDepthIsNat == MaxReassignmentDepth \in Nat
ASSUME QuorumIntersection ==
\A S, T \in SUBSET Validators :
/\ Cardinality(S) >= QuorumSize
/\ Cardinality(T) >= QuorumSize
=> S \cap T # {}
VARIABLES votes, witnessCerts, certs, assignedWitness, reassignmentDepth
vars == <<votes, witnessCerts, certs, assignedWitness, reassignmentDepth>>
VoteDomain == Validators \X Slots \X Blocks \X Epochs
WitnessCertDomain == Slots \X Blocks \X Epochs \X Witnesses
CertDomain == Slots \X Blocks \X Epochs \X (SUBSET Validators)
Init ==
/\ votes = {}
/\ witnessCerts = {}
/\ certs = {}
/\ assignedWitness = [s \in Slots |-> InitialWitness]
/\ reassignmentDepth = [s \in Slots |-> 0]
HasVote(v, s) ==
\E b \in Blocks, e \in Epochs : <<v, s, b, e>> \in votes
HasWitnessCert(s) ==
\E b \in Blocks, e \in Epochs, w \in Witnesses : <<s, b, e, w>> \in witnessCerts
IssueWitnessStep ==
\E s \in Slots, b \in Blocks, e \in Epochs :
/\ ~HasWitnessCert(s)
/\ witnessCerts' = witnessCerts \cup {<<s, b, e, assignedWitness[s]>>}
/\ UNCHANGED <<votes, certs, assignedWitness, reassignmentDepth>>
ReassignWitnessStep ==
\E s \in Slots, w \in Witnesses :
/\ w # assignedWitness[s]
/\ reassignmentDepth[s] < MaxReassignmentDepth
/\ assignedWitness' = [assignedWitness EXCEPT ![s] = w]
/\ reassignmentDepth' = [reassignmentDepth EXCEPT ![s] = @ + 1]
/\ UNCHANGED <<votes, witnessCerts, certs>>
VoteStep ==
\E v \in Validators, s \in Slots, b \in Blocks, e \in Epochs :
/\ ~HasVote(v, s)
/\ <<s, b, e, assignedWitness[s]>> \in witnessCerts
/\ votes' = votes \cup {<<v, s, b, e>>}
/\ UNCHANGED <<witnessCerts, certs, assignedWitness, reassignmentDepth>>
CertifyStep ==
\E s \in Slots, b \in Blocks, e \in Epochs, Q \in SUBSET Validators :
/\ Cardinality(Q) >= QuorumSize
/\ <<s, b, e, assignedWitness[s]>> \in witnessCerts
/\ \A v \in Q : <<v, s, b, e>> \in votes
/\ certs' = certs \cup {<<s, b, e, Q>>}
/\ UNCHANGED <<votes, witnessCerts, assignedWitness, reassignmentDepth>>
Next == IssueWitnessStep \/ ReassignWitnessStep \/ VoteStep \/ CertifyStep
TypeInvariant ==
/\ votes \subseteq VoteDomain
/\ witnessCerts \subseteq WitnessCertDomain
/\ certs \subseteq CertDomain
/\ assignedWitness \in [Slots -> Witnesses]
/\ reassignmentDepth \in [Slots -> 0..MaxReassignmentDepth]
WitnessAssignmentSoundness ==
\A s \in Slots : reassignmentDepth[s] <= MaxReassignmentDepth
NoDualVotes ==
\A v \in Validators, s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
=> /\ b1 = b2
/\ e1 = e2
WitnessCertificatesStayAssigned ==
\A s \in Slots, b \in Blocks, e \in Epochs, w \in Witnesses :
<<s, b, e, w>> \in witnessCerts
=> assignedWitness[s] = w \/ reassignmentDepth[s] > 0
CertSoundness ==
\A s \in Slots, b \in Blocks, e \in Epochs, Q \in SUBSET Validators :
<<s, b, e, Q>> \in certs
=> /\ Cardinality(Q) >= QuorumSize
/\ \A v \in Q : <<v, s, b, e>> \in votes
Invariant ==
/\ TypeInvariant
/\ WitnessAssignmentSoundness
/\ NoDualVotes
/\ WitnessCertificatesStayAssigned
/\ CertSoundness
Safety ==
\A s \in Slots,
b1 \in Blocks,
b2 \in Blocks,
e1 \in Epochs,
e2 \in Epochs,
Q1 \in SUBSET Validators,
Q2 \in SUBSET Validators :
/\ <<s, b1, e1, Q1>> \in certs
/\ <<s, b2, e2, Q2>> \in certs
=> /\ b1 = b2
/\ e1 = e2
Spec == Init /\ [][Next]_vars
THEOREM InitImpliesTypeInvariant == Init => TypeInvariant
BY SMTT(30), InitialWitnessInWitnesses, MaxReassignmentDepthIsNat DEF Init, TypeInvariant, VoteDomain,
WitnessCertDomain, CertDomain
THEOREM InitImpliesWitnessAssignmentSoundness == Init => WitnessAssignmentSoundness
BY SMTT(30), MaxReassignmentDepthIsNat DEF Init, WitnessAssignmentSoundness
THEOREM InitImpliesNoDualVotes == Init => NoDualVotes
BY DEF Init, NoDualVotes
THEOREM InitImpliesWitnessCertificatesStayAssigned == Init => WitnessCertificatesStayAssigned
BY DEF Init, WitnessCertificatesStayAssigned
THEOREM InitImpliesCertSoundness == Init => CertSoundness
BY DEF Init, CertSoundness
THEOREM InitImpliesInvariant == Init => Invariant
BY InitImpliesTypeInvariant, InitImpliesWitnessAssignmentSoundness,
InitImpliesNoDualVotes, InitImpliesWitnessCertificatesStayAssigned,
InitImpliesCertSoundness DEF Invariant
THEOREM IssueWitnessPreservesInvariant == Invariant /\ IssueWitnessStep => Invariant'
BY SMTT(30) DEF Invariant, TypeInvariant, WitnessAssignmentSoundness, NoDualVotes,
WitnessCertificatesStayAssigned, CertSoundness, IssueWitnessStep,
HasWitnessCert, WitnessCertDomain
THEOREM ReassignWitnessPreservesInvariant == Invariant /\ ReassignWitnessStep => Invariant'
BY SMTT(30), MaxReassignmentDepthIsNat DEF Invariant, TypeInvariant, WitnessAssignmentSoundness, NoDualVotes,
WitnessCertificatesStayAssigned, CertSoundness, ReassignWitnessStep
THEOREM VotePreservesInvariant == Invariant /\ VoteStep => Invariant'
BY SMTT(30) DEF Invariant, TypeInvariant, WitnessAssignmentSoundness, NoDualVotes,
WitnessCertificatesStayAssigned, CertSoundness, VoteStep, HasVote,
VoteDomain
THEOREM CertifyPreservesInvariant == Invariant /\ CertifyStep => Invariant'
BY SMTT(30) DEF Invariant, TypeInvariant, WitnessAssignmentSoundness, NoDualVotes,
WitnessCertificatesStayAssigned, CertSoundness, CertifyStep, CertDomain
THEOREM StepPreservesInvariant == Invariant /\ Next => Invariant'
BY IssueWitnessPreservesInvariant, ReassignWitnessPreservesInvariant,
VotePreservesInvariant, CertifyPreservesInvariant DEF Next
THEOREM StutterPreservesTypeInvariant ==
TypeInvariant /\ UNCHANGED vars => TypeInvariant'
BY DEF TypeInvariant, vars
THEOREM StutterPreservesWitnessAssignmentSoundness ==
WitnessAssignmentSoundness /\ UNCHANGED vars => WitnessAssignmentSoundness'
BY DEF WitnessAssignmentSoundness, vars
THEOREM StutterPreservesNoDualVotes ==
NoDualVotes /\ UNCHANGED vars => NoDualVotes'
BY DEF NoDualVotes, vars
THEOREM StutterPreservesWitnessCertificatesStayAssigned ==
WitnessCertificatesStayAssigned /\ UNCHANGED vars => WitnessCertificatesStayAssigned'
BY DEF WitnessCertificatesStayAssigned, vars
THEOREM StutterPreservesCertSoundness ==
CertSoundness /\ UNCHANGED vars => CertSoundness'
BY DEF CertSoundness, vars
THEOREM StutterPreservesInvariant == Invariant /\ UNCHANGED vars => Invariant'
BY StutterPreservesTypeInvariant, StutterPreservesWitnessAssignmentSoundness,
StutterPreservesNoDualVotes, StutterPreservesWitnessCertificatesStayAssigned,
StutterPreservesCertSoundness DEF Invariant
THEOREM NextPreservesInvariant == Invariant /\ [Next]_vars => Invariant'
BY StepPreservesInvariant, StutterPreservesInvariant DEF vars
THEOREM QuorumCertificatesIntersect ==
\A s \in Slots,
b1 \in Blocks,
b2 \in Blocks,
e1 \in Epochs,
e2 \in Epochs,
Q1 \in SUBSET Validators,
Q2 \in SUBSET Validators :
/\ Invariant
/\ <<s, b1, e1, Q1>> \in certs
/\ <<s, b2, e2, Q2>> \in certs
=> Q1 \cap Q2 # {}
BY SMTT(60), QuorumIntersection DEF Invariant, CertSoundness
THEOREM InvariantImpliesSafety == Invariant => Safety
BY SMTT(60), QuorumCertificatesIntersect DEF Invariant, Safety, NoDualVotes,
CertSoundness
====
NestedGuardian.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardian.tla
---- MODULE NestedGuardian ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness
ASSUME InitialEpochInEpochs == InitialEpoch \in Epochs
ASSUME InitialWitnessInWitnesses == InitialWitness \in Witnesses
ASSUME QuorumIntersection ==
\A S, T \in SUBSET Validators :
/\ Cardinality(S) >= QuorumSize
/\ Cardinality(T) >= QuorumSize
=> S \cap T # {}
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth
vars == <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessOnline, witnessCheckpoint, assignedWitness, reassignmentDepth>>
CheckpointLevels == 0..2
VoteEvent(v, s, b, e) == <<v, s, b, e>>
WitnessEvent(w, s, b, e) == <<w, s, b, e>>
Finalization(s, b, e) == <<s, b, e>>
VoteDomain == {VoteEvent(v, s, b, e) : v \in Validators, s \in Slots, b \in Blocks, e \in Epochs}
WitnessDomain == {WitnessEvent(w, s, b, e) : w \in Witnesses, s \in Slots, b \in Blocks, e \in Epochs}
FinalizationDomain == {Finalization(s, b, e) : s \in Slots, b \in Blocks, e \in Epochs}
Init ==
/\ votes = {}
/\ witnessCerts = {}
/\ finalized = {}
/\ finalizerSets = [f \in FinalizationDomain |-> {}]
/\ registryEpoch = [v \in Validators |-> InitialEpoch]
/\ guardianReady = [v \in Validators |-> TRUE]
/\ witnessOnline = [w \in Witnesses |-> TRUE]
/\ witnessCheckpoint = [w \in Witnesses |-> 1]
/\ assignedWitness = [s \in Slots |-> InitialWitness]
/\ reassignmentDepth = [s \in Slots |-> 0]
HasVote(v, s) ==
\E b \in Blocks, e \in Epochs : VoteEvent(v, s, b, e) \in votes
HasWitnessCert(w, s) ==
\E b \in Blocks, e \in Epochs : WitnessEvent(w, s, b, e) \in witnessCerts
CanIssueWitness(w, s, b, e) ==
/\ w \in Witnesses
/\ s \in Slots
/\ b \in Blocks
/\ e \in Epochs
/\ witnessOnline[w]
/\ witnessCheckpoint[w] > 0
/\ assignedWitness[s] = w
/\ ~HasWitnessCert(w, s)
IssueWitness(w, s, b, e) ==
/\ CanIssueWitness(w, s, b, e)
/\ witnessCerts' = witnessCerts \cup {WitnessEvent(w, s, b, e)}
/\ UNCHANGED <<votes, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
CanReassign(s, w) ==
/\ s \in Slots
/\ w \in Witnesses
/\ w # assignedWitness[s]
/\ ~witnessOnline[assignedWitness[s]]
/\ reassignmentDepth[s] < MaxReassignmentDepth
ReassignWitness(s, w) ==
/\ CanReassign(s, w)
/\ assignedWitness' = [assignedWitness EXCEPT ![s] = w]
/\ reassignmentDepth' = [reassignmentDepth EXCEPT ![s] = @ + 1]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessOnline, witnessCheckpoint>>
CanVote(v, s, b, e) ==
/\ v \in Validators
/\ s \in Slots
/\ b \in Blocks
/\ e \in Epochs
/\ guardianReady[v]
/\ registryEpoch[v] = e
/\ ~HasVote(v, s)
/\ WitnessEvent(assignedWitness[s], s, b, e) \in witnessCerts
Vote(v, s, b, e) ==
/\ CanVote(v, s, b, e)
/\ votes' = votes \cup {VoteEvent(v, s, b, e)}
/\ UNCHANGED <<witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
EligibleVoters(s, b, e) ==
{v \in Validators :
/\ VoteEvent(v, s, b, e) \in votes
/\ guardianReady[v]
/\ registryEpoch[v] = e
/\ WitnessEvent(assignedWitness[s], s, b, e) \in witnessCerts}
CanFinalize(s, b, e) ==
/\ s \in Slots
/\ b \in Blocks
/\ e \in Epochs
/\ Cardinality(EligibleVoters(s, b, e)) >= QuorumSize
Finalize(s, b, e) ==
/\ CanFinalize(s, b, e)
/\ finalized' = finalized \cup {Finalization(s, b, e)}
/\ finalizerSets' = [finalizerSets EXCEPT ![Finalization(s, b, e)] = EligibleVoters(s, b, e)]
/\ UNCHANGED <<votes, witnessCerts, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
AdoptEpoch(v, e) ==
/\ v \in Validators
/\ e \in Epochs
/\ e >= registryEpoch[v]
/\ registryEpoch' = [registryEpoch EXCEPT ![v] = e]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
RegistryRollback(v, e) ==
/\ v \in Validators
/\ e \in Epochs
/\ e < registryEpoch[v]
/\ registryEpoch' = [registryEpoch EXCEPT ![v] = e]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
GuardianOutage(v) ==
/\ v \in Validators
/\ guardianReady[v]
/\ guardianReady' = [guardianReady EXCEPT ![v] = FALSE]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
WitnessOutage(w) ==
/\ w \in Witnesses
/\ witnessOnline[w]
/\ witnessOnline' = [witnessOnline EXCEPT ![w] = FALSE]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
WitnessRecovery(w) ==
/\ w \in Witnesses
/\ ~witnessOnline[w]
/\ witnessOnline' = [witnessOnline EXCEPT ![w] = TRUE]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessCheckpoint, assignedWitness, reassignmentDepth>>
AdvanceWitnessCheckpoint(w, level) ==
/\ w \in Witnesses
/\ level \in CheckpointLevels
/\ level > witnessCheckpoint[w]
/\ witnessCheckpoint' = [witnessCheckpoint EXCEPT ![w] = level]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessOnline, assignedWitness, reassignmentDepth>>
WitnessCheckpointRollback(w, level) ==
/\ w \in Witnesses
/\ level \in CheckpointLevels
/\ level < witnessCheckpoint[w]
/\ witnessCheckpoint' = [witnessCheckpoint EXCEPT ![w] = level]
/\ UNCHANGED <<votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady,
witnessOnline, assignedWitness, reassignmentDepth>>
Next ==
\/ \E w \in Witnesses, s \in Slots, b \in Blocks, e \in Epochs : IssueWitness(w, s, b, e)
\/ \E s \in Slots, w \in Witnesses : ReassignWitness(s, w)
\/ \E v \in Validators, s \in Slots, b \in Blocks, e \in Epochs : Vote(v, s, b, e)
\/ \E s \in Slots, b \in Blocks, e \in Epochs : Finalize(s, b, e)
\/ \E v \in Validators, e \in Epochs : AdoptEpoch(v, e)
\/ \E v \in Validators, e \in Epochs : RegistryRollback(v, e)
\/ \E v \in Validators : GuardianOutage(v)
\/ \E w \in Witnesses : WitnessOutage(w)
\/ \E w \in Witnesses : WitnessRecovery(w)
\/ \E w \in Witnesses, level \in CheckpointLevels : AdvanceWitnessCheckpoint(w, level)
\/ \E w \in Witnesses, level \in CheckpointLevels : WitnessCheckpointRollback(w, level)
TypeInvariant ==
/\ votes \subseteq VoteDomain
/\ witnessCerts \subseteq WitnessDomain
/\ finalized \subseteq FinalizationDomain
/\ finalizerSets \in [FinalizationDomain -> SUBSET Validators]
/\ registryEpoch \in [Validators -> Epochs]
/\ guardianReady \in [Validators -> BOOLEAN]
/\ witnessOnline \in [Witnesses -> BOOLEAN]
/\ witnessCheckpoint \in [Witnesses -> CheckpointLevels]
/\ assignedWitness \in [Slots -> Witnesses]
/\ reassignmentDepth \in [Slots -> 0..MaxReassignmentDepth]
WitnessAssignmentSoundness ==
\A s \in Slots :
reassignmentDepth[s] <= MaxReassignmentDepth
NoDualVotes ==
\A v \in Validators, s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ VoteEvent(v, s, b1, e1) \in votes
/\ VoteEvent(v, s, b2, e2) \in votes
=> /\ b1 = b2
/\ e1 = e2
WitnessCertificatesStayAssigned ==
\A w \in Witnesses, s \in Slots, b \in Blocks, e \in Epochs :
WitnessEvent(w, s, b, e) \in witnessCerts
=> assignedWitness[s] = w \/ reassignmentDepth[s] > 0
FinalizationWitnessSoundness ==
\A s \in Slots, b \in Blocks, e \in Epochs :
Finalization(s, b, e) \in finalized
=> /\ Cardinality(finalizerSets[Finalization(s, b, e)]) >= QuorumSize
/\ \A v \in finalizerSets[Finalization(s, b, e)] :
VoteEvent(v, s, b, e) \in votes
Invariant ==
/\ TypeInvariant
/\ WitnessAssignmentSoundness
/\ NoDualVotes
/\ WitnessCertificatesStayAssigned
/\ FinalizationWitnessSoundness
Safety ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ Finalization(s, b1, e1) \in finalized
/\ Finalization(s, b2, e2) \in finalized
=> b1 = b2
Spec ==
Init /\ [][Next]_vars
THEOREM OneInCheckpointLevels == 1 \in CheckpointLevels
BY SMT DEF CheckpointLevels
THEOREM InitImpliesInvariant == Init => Invariant
PROOF
<1>1. Init => TypeInvariant
BY SMT, InitialEpochInEpochs, InitialWitnessInWitnesses, OneInCheckpointLevels
DEF Init, TypeInvariant, VoteDomain, WitnessDomain, FinalizationDomain
<1>2. Init => WitnessAssignmentSoundness
BY DEF Init, WitnessAssignmentSoundness
<1>3. Init => NoDualVotes
BY DEF Init, NoDualVotes
<1>4. Init => WitnessCertificatesStayAssigned
BY DEF Init, WitnessCertificatesStayAssigned
<1>5. Init => FinalizationWitnessSoundness
BY DEF Init, FinalizationWitnessSoundness
<1>6. QED
BY <1>1, <1>2, <1>3, <1>4, <1>5 DEF Invariant
THEOREM StepPreservesInvariant == Invariant /\ Next => Invariant'
BY SMTT(30) DEF Invariant, TypeInvariant, WitnessAssignmentSoundness, NoDualVotes,
WitnessCertificatesStayAssigned, FinalizationWitnessSoundness, Next,
IssueWitness, ReassignWitness, Vote, Finalize, AdoptEpoch,
RegistryRollback, GuardianOutage, WitnessOutage, WitnessRecovery,
AdvanceWitnessCheckpoint, WitnessCheckpointRollback, CanIssueWitness,
CanVote, HasVote, CanFinalize, EligibleVoters, VoteEvent,
WitnessEvent, Finalization, VoteDomain, WitnessDomain, FinalizationDomain
THEOREM StutterPreservesInvariant == Invariant /\ UNCHANGED vars => Invariant'
BY SMT DEF Invariant, vars
THEOREM NextPreservesInvariant == Invariant /\ [Next]_vars => Invariant'
BY SMT, StepPreservesInvariant, StutterPreservesInvariant DEF vars
THEOREM FinalizedWitnessesIntersect ==
\A s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs :
/\ Invariant
/\ <<s, b1, e1>> \in finalized
/\ <<s, b2, e2>> \in finalized
=> \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
PROOF
<1>1. TAKE s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs
<1>2. ASSUME Invariant,
<<s, b1, e1>> \in finalized,
<<s, b2, e2>> \in finalized
PROVE \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
<2>1. finalizerSets[<<s, b1, e1>>] \subseteq Validators
BY SMT, <1>2 DEF Invariant, TypeInvariant, FinalizationDomain, Finalization
<2>2. finalizerSets[<<s, b2, e2>>] \subseteq Validators
BY SMT, <1>2 DEF Invariant, TypeInvariant, FinalizationDomain, Finalization
<2>3. Cardinality(finalizerSets[<<s, b1, e1>>]) >= QuorumSize
BY SMT, <1>2 DEF Invariant, FinalizationWitnessSoundness
<2>4. Cardinality(finalizerSets[<<s, b2, e2>>]) >= QuorumSize
BY SMT, <1>2 DEF Invariant, FinalizationWitnessSoundness
<2>5. finalizerSets[<<s, b1, e1>>] \cap finalizerSets[<<s, b2, e2>>] # {}
BY <2>1, <2>2, <2>3, <2>4, QuorumIntersection
<2>6. PICK v \in finalizerSets[<<s, b1, e1>>] \cap finalizerSets[<<s, b2, e2>>] : TRUE
BY <2>5
<2>7. <<v, s, b1, e1>> \in votes
BY SMT, <1>2, <2>6 DEF Invariant, FinalizationWitnessSoundness
<2>8. <<v, s, b2, e2>> \in votes
BY SMT, <1>2, <2>6 DEF Invariant, FinalizationWitnessSoundness
<2>9. QED
BY SMT, <2>6, <2>7, <2>8
<1>3. QED
BY <1>2
THEOREM InvariantImpliesSafety == Invariant => Safety
PROOF
<1>1. TAKE s \in Slots, b1 \in Blocks, b2 \in Blocks, e1 \in Epochs, e2 \in Epochs
<1>2. ASSUME Invariant,
<<s, b1, e1>> \in finalized,
<<s, b2, e2>> \in finalized
PROVE b1 = b2
<2>1. \E v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
BY SMT, FinalizedWitnessesIntersect, <1>2
<2>2. PICK v \in Validators :
/\ <<v, s, b1, e1>> \in votes
/\ <<v, s, b2, e2>> \in votes
BY <2>1
<2>3. QED
BY SMT, <1>2, <2>2 DEF Invariant, NoDualVotes
<1>3. QED
BY <1>2 DEF Safety
====
CanonicalOrdering Companion Witnesses
Executable witness artifacts for omission dominance and recursive continuity.
CanonicalOrderingOmissionTrace.tla
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrderingOmissionTrace.tla
---- MODULE CanonicalOrderingOmissionTrace ----
EXTENDS CanonicalOrdering
TargetSlot == 1
TargetCert == {"tx1"}
TargetTx == "tx2"
WitnessState ==
/\ TargetSlot \in closedCutoffs
/\ bulletin[TargetSlot] = {"tx1", "tx2"}
/\ CertEvent(TargetSlot, TargetCert) \in candidateCerts
/\ OmissionEvent(TargetSlot, TargetCert, TargetTx) \in omissionProofs
/\ CertEvent(TargetSlot, TargetCert) \notin admittedCerts
NoOmissionDominanceWitness == ~WitnessState
====
CanonicalOrderingOmissionTrace.cfg
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalOrderingOmissionTrace.cfg
SPECIFICATION Spec
CONSTANTS
Slots = {1}
Transactions = {"tx1", "tx2"}
INVARIANTS
TypeInvariant
AdmittedSoundness
OmissionSoundness
RecoveredSoundness
AdmittedUniqueness
Recoverability
OmissionDominates
NoOmissionDominanceWitness
CanonicalCollapseRecursiveContinuity.tla
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalCollapseRecursiveContinuity.tla
---- MODULE CanonicalCollapseRecursiveContinuity ----
EXTENDS Naturals, Sequences, TLC
CONSTANT MaxHeight
Slots == 1..MaxHeight
Genesis == 1
NonGenesisSlots == Slots \ {Genesis}
NullHash == 0
VARIABLES publishedCollapses, publishedProofs, publishedExtensionCertificates, admittedHeaders
vars ==
<<publishedCollapses, publishedProofs, publishedExtensionCertificates, admittedHeaders>>
RECURSIVE AccumulatorHash(_), ProofHash(_), ProofChain(_)
PayloadHash(s) == <<"payload", s>>
AccumulatorHash(s) ==
IF s = Genesis
THEN <<"accum", s, NullHash, PayloadHash(s)>>
ELSE <<"accum", s, AccumulatorHash(s - 1), PayloadHash(s)>>
Commitment(s) ==
[height |-> s,
continuityAccumulatorHash |-> AccumulatorHash(s),
resultingStateRootHash |-> <<"state", s>>]
CommitmentHash(s) == <<"commitment-hash", Commitment(s)>>
PreviousCommitmentHash(s) ==
IF s = Genesis THEN NullHash ELSE CommitmentHash(s - 1)
StatementHash(s) ==
<<"statement-hash", Commitment(s), PreviousCommitmentHash(s), PayloadHash(s)>>
PreviousProofHash(s) ==
IF s = Genesis THEN NullHash ELSE ProofHash(s - 1)
ProofBytes(s) ==
<<"hash-pcd-v1", StatementHash(s), PreviousProofHash(s)>>
ProofStep(s) ==
[commitment |-> Commitment(s),
previousCommitmentHash |-> PreviousCommitmentHash(s),
payloadHash |-> PayloadHash(s),
previousProofHash |-> PreviousProofHash(s),
proofBytes |-> ProofBytes(s)]
ProofHash(s) == <<"proof-hash", ProofStep(s)>>
ProofChain(s) ==
IF s = Genesis
THEN <<ProofStep(s)>>
ELSE Append(ProofChain(s - 1), ProofStep(s))
ExtensionCertificate(s) ==
[coveredHeight |-> s,
predecessorCommitment |-> Commitment(s - 1),
predecessorProofHash |-> ProofHash(s - 1)]
Last(seq) == seq[Len(seq)]
Init ==
/\ publishedCollapses = {}
/\ publishedProofs = {}
/\ publishedExtensionCertificates = {}
/\ admittedHeaders = {}
PublishCollapseStep ==
\E s \in Slots :
/\ s \notin publishedCollapses
/\ publishedCollapses' = publishedCollapses \cup {s}
/\ UNCHANGED <<publishedProofs, publishedExtensionCertificates, admittedHeaders>>
PublishRecursiveProofStep ==
\E s \in Slots :
/\ s \in publishedCollapses
/\ s \notin publishedProofs
/\ IF s = Genesis THEN TRUE ELSE s - 1 \in publishedProofs
/\ publishedProofs' = publishedProofs \cup {s}
/\ UNCHANGED <<publishedCollapses, publishedExtensionCertificates, admittedHeaders>>
PublishExtensionCertificateStep ==
\E s \in NonGenesisSlots :
/\ s \in publishedCollapses
/\ s - 1 \in publishedProofs
/\ s \notin publishedExtensionCertificates
/\ publishedExtensionCertificates' = publishedExtensionCertificates \cup {s}
/\ UNCHANGED <<publishedCollapses, publishedProofs, admittedHeaders>>
AdmitHeaderStep ==
\E s \in Slots :
/\ s \in publishedCollapses
/\ s \notin admittedHeaders
/\ IF s = Genesis THEN TRUE ELSE s \in publishedExtensionCertificates
/\ admittedHeaders' = admittedHeaders \cup {s}
/\ UNCHANGED <<publishedCollapses, publishedProofs, publishedExtensionCertificates>>
Next ==
\/ PublishCollapseStep
\/ PublishRecursiveProofStep
\/ PublishExtensionCertificateStep
\/ AdmitHeaderStep
TypeInvariant ==
/\ publishedCollapses \subseteq Slots
/\ publishedProofs \subseteq Slots
/\ publishedExtensionCertificates \subseteq NonGenesisSlots
/\ admittedHeaders \subseteq Slots
RecursiveProofSoundness ==
\A s \in publishedProofs :
/\ s \in publishedCollapses
/\ IF s = Genesis THEN TRUE ELSE s - 1 \in publishedProofs
/\ LET step == ProofStep(s) IN
/\ step.commitment = Commitment(s)
/\ step.previousCommitmentHash = PreviousCommitmentHash(s)
/\ step.payloadHash = PayloadHash(s)
/\ step.previousProofHash = PreviousProofHash(s)
/\ step.proofBytes = ProofBytes(s)
/\ step.commitment.continuityAccumulatorHash = AccumulatorHash(s)
RecursiveProofChainSoundness ==
\A s \in publishedProofs :
/\ Len(ProofChain(s)) = s
/\ Last(ProofChain(s)) = ProofStep(s)
/\ IF s = Genesis
THEN TRUE
ELSE /\ ProofChain(s)[Len(ProofChain(s)) - 1] = ProofStep(s - 1)
ExtensionCertificateSoundness ==
\A s \in publishedExtensionCertificates :
/\ s \in NonGenesisSlots
/\ s - 1 \in publishedProofs
/\ ExtensionCertificate(s).coveredHeight = s
/\ ExtensionCertificate(s).predecessorCommitment = Commitment(s - 1)
/\ ExtensionCertificate(s).predecessorProofHash = ProofHash(s - 1)
HeaderAdmissionSoundness ==
\A s \in admittedHeaders :
/\ s \in publishedCollapses
/\ IF s = Genesis
THEN TRUE
ELSE /\ s \in publishedExtensionCertificates
/\ s - 1 \in publishedProofs
/\ ExtensionCertificate(s).predecessorCommitment = Commitment(s - 1)
/\ ExtensionCertificate(s).predecessorProofHash = ProofHash(s - 1)
Invariant ==
/\ TypeInvariant
/\ RecursiveProofSoundness
/\ RecursiveProofChainSoundness
/\ ExtensionCertificateSoundness
/\ HeaderAdmissionSoundness
Spec == Init /\ [][Next]_vars
====
CanonicalCollapseRecursiveContinuity.cfg
Repository path: docs/architecture/protocols/aft/formal/canonical_ordering/CanonicalCollapseRecursiveContinuity.cfg
SPECIFICATION Spec
CONSTANTS
MaxHeight = 3
INVARIANTS
TypeInvariant
RecursiveProofSoundness
RecursiveProofChainSoundness
ExtensionCertificateSoundness
HeaderAdmissionSoundness
Recovery and Classical-Agreement Bridge
Recurring recovery kernel, finite reduction, totality bridge, and final classical-agreement collapse wrapper.
NestedGuardianRecoveryRecurringInductionCore.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianRecoveryRecurringInductionCore.tla
---- MODULE NestedGuardianRecoveryRecurringInductionCore ----
EXTENDS Naturals, FiniteSets, TLC
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness, TotalCycles,
TargetSlotOf(_), TargetBlockOf(_), StableEpochOf(_),
SmallCommitteeSlot, SmallRecoveryThreshold, LargeRecoveryThreshold,
SmallRecoveryCommittee, LargeRecoveryCommittee
ASSUME InitialEpoch \in Epochs
ASSUME InitialWitness \in Witnesses
ASSUME QuorumSize \in 1..Cardinality(Validators)
ASSUME TotalCycles \in Nat
ASSUME TotalCycles >= 1
ASSUME \A c \in 1..TotalCycles :
/\ TargetSlotOf(c) \in Slots
/\ TargetBlockOf(c) \in Blocks
/\ StableEpochOf(c) \in Epochs
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth, currentCycle, phase, churnStage,
continuationBoundary, continuationAnchorPublished, continuationAnchorBoundary,
continuationPagePublished, continuationPageBoundary, continuationFetched,
shareReceipts, shareConflicts, windowClosed, missingShareClaims,
missingThresholdCertificates, recovered, recoveredSurfaces,
recoveryConflicts, aborted
Core ==
INSTANCE NestedGuardianRecoveryRecurringLivenessCore
WITH Validators <- Validators,
Witnesses <- Witnesses,
Blocks <- Blocks,
Slots <- Slots,
Epochs <- Epochs,
QuorumSize <- QuorumSize,
MaxReassignmentDepth <- MaxReassignmentDepth,
InitialEpoch <- InitialEpoch,
InitialWitness <- InitialWitness,
TotalCycles <- TotalCycles,
TargetSlotOf <- TargetSlotOf,
TargetBlockOf <- TargetBlockOf,
StableEpochOf <- StableEpochOf,
SmallCommitteeSlot <- SmallCommitteeSlot,
SmallRecoveryThreshold <- SmallRecoveryThreshold,
LargeRecoveryThreshold <- LargeRecoveryThreshold,
SmallRecoveryCommittee <- SmallRecoveryCommittee,
LargeRecoveryCommittee <- LargeRecoveryCommittee,
votes <- votes,
witnessCerts <- witnessCerts,
finalized <- finalized,
finalizerSets <- finalizerSets,
registryEpoch <- registryEpoch,
guardianReady <- guardianReady,
witnessOnline <- witnessOnline,
witnessCheckpoint <- witnessCheckpoint,
assignedWitness <- assignedWitness,
reassignmentDepth <- reassignmentDepth,
currentCycle <- currentCycle,
phase <- phase,
churnStage <- churnStage,
continuationBoundary <- continuationBoundary,
continuationAnchorPublished <- continuationAnchorPublished,
continuationAnchorBoundary <- continuationAnchorBoundary,
continuationPagePublished <- continuationPagePublished,
continuationPageBoundary <- continuationPageBoundary,
continuationFetched <- continuationFetched,
shareReceipts <- shareReceipts,
shareConflicts <- shareConflicts,
windowClosed <- windowClosed,
missingShareClaims <- missingShareClaims,
missingThresholdCertificates <- missingThresholdCertificates,
recovered <- recovered,
recoveredSurfaces <- recoveredSurfaces,
recoveryConflicts <- recoveryConflicts,
aborted <- aborted
vars == Core!vars
CycleRange == Core!CycleRange
PrefixAdvanceRange == Core!PrefixAdvanceRange
RecoveryClosedPrefix(c) == Core!RecoveryClosedPrefix(c)
PriorCycleRange(c) ==
IF c = 1 THEN {}
ELSE 1..(c - 1)
RecoveryInductionBase ==
<>RecoveryClosedPrefix(1)
RecoveryInductionStep(c) ==
/\ c \in PrefixAdvanceRange
/\ Core!RecoveryPrefixAdvanceContract(c)
RecoveryInductionPremisesUpTo(c) ==
/\ c \in CycleRange
/\ RecoveryInductionBase
/\ \A i \in PriorCycleRange(c) :
RecoveryInductionStep(i)
RecoveryRecurringInductionPremises ==
/\ RecoveryInductionBase
/\ \A i \in PrefixAdvanceRange :
RecoveryInductionStep(i)
RecoveryClosedPrefixInductionKernel(c) ==
/\ c \in CycleRange
/\ (RecoveryInductionPremisesUpTo(c)
=> <>RecoveryClosedPrefix(c))
RecoveryRecurringInductionKernel ==
\A c \in CycleRange :
RecoveryClosedPrefixInductionKernel(c)
====
NestedGuardianRecoveryRecurringProof.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianRecoveryRecurringProof.tla
---- MODULE NestedGuardianRecoveryRecurringProof ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness, TotalCycles,
TargetSlotOf(_), TargetBlockOf(_), StableEpochOf(_),
SmallCommitteeSlot, SmallRecoveryThreshold, LargeRecoveryThreshold,
SmallRecoveryCommittee, LargeRecoveryCommittee
ASSUME InitialEpochInEpochs == InitialEpoch \in Epochs
ASSUME InitialWitnessInWitnesses == InitialWitness \in Witnesses
ASSUME QuorumSizeInValidatorRange == QuorumSize \in 1..Cardinality(Validators)
ASSUME TotalCyclesIsNat == TotalCycles \in Nat
ASSUME TotalCyclesAtLeastOne == TotalCycles >= 1
ASSUME TargetCycleDomains ==
\A c \in 1..TotalCycles :
/\ TargetSlotOf(c) \in Slots
/\ TargetBlockOf(c) \in Blocks
/\ StableEpochOf(c) \in Epochs
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth, currentCycle, phase, churnStage,
continuationBoundary, continuationAnchorPublished, continuationAnchorBoundary,
continuationPagePublished, continuationPageBoundary, continuationFetched,
shareReceipts, shareConflicts, windowClosed, missingShareClaims,
missingThresholdCertificates, recovered, recoveredSurfaces,
recoveryConflicts, aborted
Core ==
INSTANCE NestedGuardianRecoveryRecurringInductionCore
WITH Validators <- Validators,
Witnesses <- Witnesses,
Blocks <- Blocks,
Slots <- Slots,
Epochs <- Epochs,
QuorumSize <- QuorumSize,
MaxReassignmentDepth <- MaxReassignmentDepth,
InitialEpoch <- InitialEpoch,
InitialWitness <- InitialWitness,
TotalCycles <- TotalCycles,
TargetSlotOf <- TargetSlotOf,
TargetBlockOf <- TargetBlockOf,
StableEpochOf <- StableEpochOf,
SmallCommitteeSlot <- SmallCommitteeSlot,
SmallRecoveryThreshold <- SmallRecoveryThreshold,
LargeRecoveryThreshold <- LargeRecoveryThreshold,
SmallRecoveryCommittee <- SmallRecoveryCommittee,
LargeRecoveryCommittee <- LargeRecoveryCommittee,
votes <- votes,
witnessCerts <- witnessCerts,
finalized <- finalized,
finalizerSets <- finalizerSets,
registryEpoch <- registryEpoch,
guardianReady <- guardianReady,
witnessOnline <- witnessOnline,
witnessCheckpoint <- witnessCheckpoint,
assignedWitness <- assignedWitness,
reassignmentDepth <- reassignmentDepth,
currentCycle <- currentCycle,
phase <- phase,
churnStage <- churnStage,
continuationBoundary <- continuationBoundary,
continuationAnchorPublished <- continuationAnchorPublished,
continuationAnchorBoundary <- continuationAnchorBoundary,
continuationPagePublished <- continuationPagePublished,
continuationPageBoundary <- continuationPageBoundary,
continuationFetched <- continuationFetched,
shareReceipts <- shareReceipts,
shareConflicts <- shareConflicts,
windowClosed <- windowClosed,
missingShareClaims <- missingShareClaims,
missingThresholdCertificates <- missingThresholdCertificates,
recovered <- recovered,
recoveredSurfaces <- recoveredSurfaces,
recoveryConflicts <- recoveryConflicts,
aborted <- aborted
RecoveryRecurringClosedPrefixes ==
\A c \in Core!CycleRange :
<>Core!RecoveryClosedPrefix(c)
RecoveryParametricRecurrenceArgument ==
/\ Core!RecoveryRecurringInductionPremises
/\ Core!RecoveryRecurringInductionKernel
=> RecoveryRecurringClosedPrefixes
THEOREM PriorCycleRangeImpliesTotalCyclesNotOne ==
\A c \in Core!CycleRange :
\A i \in Core!PriorCycleRange(c) :
TotalCycles # 1
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF Core!CycleRange, Core!Core!CycleRange, Core!PriorCycleRange
THEOREM PriorCycleRangeImpliesPrefixAdvanceInterval ==
\A c \in Core!CycleRange :
\A i \in Core!PriorCycleRange(c) :
i \in 1..(TotalCycles - 1)
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF Core!CycleRange, Core!Core!CycleRange, Core!PriorCycleRange
THEOREM RecoveryInductionPremisesRestrict ==
\A c \in Core!CycleRange :
Core!RecoveryRecurringInductionPremises
=> Core!RecoveryInductionPremisesUpTo(c)
PROOF
<1>1. TAKE c \in Core!CycleRange
<1>2. ASSUME Core!RecoveryRecurringInductionPremises
PROVE Core!RecoveryInductionPremisesUpTo(c)
<2>1. Core!RecoveryInductionBase
BY <1>2 DEF Core!RecoveryRecurringInductionPremises
<2>2. \A i \in Core!PriorCycleRange(c) :
Core!RecoveryInductionStep(i)
PROOF
<3>1. TAKE i \in Core!PriorCycleRange(c)
<3>2. i \in Core!PrefixAdvanceRange
PROOF
<4>1. TotalCycles # 1
BY PriorCycleRangeImpliesTotalCyclesNotOne, <1>1, <3>1
<4>2. i \in 1..(TotalCycles - 1)
BY PriorCycleRangeImpliesPrefixAdvanceInterval, <1>1, <3>1
<4>3. TotalCycles # 1
BY <4>1
<4>6. QED
BY <4>3, <4>2
DEF Core!PrefixAdvanceRange, Core!Core!PrefixAdvanceRange
<3>3. Core!RecoveryInductionStep(i)
BY <1>2, <3>2 DEF Core!RecoveryRecurringInductionPremises
<3>4. QED
BY <3>3
<2>3. QED
BY <1>1, <2>1, <2>2
DEF Core!RecoveryInductionPremisesUpTo
<1>3. QED
BY <1>2
THEOREM RecoveryInductionKernelRestrict ==
\A c \in Core!CycleRange :
Core!RecoveryRecurringInductionKernel
=> Core!RecoveryClosedPrefixInductionKernel(c)
BY DEF Core!RecoveryRecurringInductionKernel,
Core!RecoveryClosedPrefixInductionKernel,
Core!CycleRange
THEOREM RecoveryRecurringClosedPrefixFromKernel ==
\A c \in Core!CycleRange :
/\ Core!RecoveryRecurringInductionPremises
/\ Core!RecoveryRecurringInductionKernel
=> <>Core!RecoveryClosedPrefix(c)
PROOF
<1>1. TAKE c \in Core!CycleRange
<1>2. ASSUME Core!RecoveryRecurringInductionPremises,
Core!RecoveryRecurringInductionKernel
PROVE <>Core!RecoveryClosedPrefix(c)
<2>1. Core!RecoveryInductionPremisesUpTo(c)
BY RecoveryInductionPremisesRestrict, <1>1, <1>2
<2>2. Core!RecoveryClosedPrefixInductionKernel(c)
BY RecoveryInductionKernelRestrict, <1>1, <1>2
<2>3. QED
BY <2>1, <2>2
DEF Core!RecoveryClosedPrefixInductionKernel
<1>3. QED
BY <1>2
THEOREM RecoveryParametricRecurrenceArgumentTheorem ==
RecoveryParametricRecurrenceArgument
BY RecoveryRecurringClosedPrefixFromKernel
DEF RecoveryParametricRecurrenceArgument,
RecoveryRecurringClosedPrefixes
====
NestedGuardianRecoveryClassicalAgreementReduction.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianRecoveryClassicalAgreementReduction.tla
---- MODULE NestedGuardianRecoveryClassicalAgreementReduction ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness, TotalCycles,
TargetSlotOf(_), TargetBlockOf(_), StableEpochOf(_),
SmallCommitteeSlot, SmallRecoveryThreshold, LargeRecoveryThreshold,
SmallRecoveryCommittee, LargeRecoveryCommittee
ASSUME InitialEpoch \in Epochs
ASSUME InitialWitness \in Witnesses
ASSUME QuorumSize \in 1..Cardinality(Validators)
ASSUME TotalCycles \in Nat
ASSUME TotalCycles >= 1
ASSUME \A c \in 1..TotalCycles :
/\ TargetSlotOf(c) \in Slots
/\ TargetBlockOf(c) \in Blocks
/\ StableEpochOf(c) \in Epochs
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth, currentCycle, phase, churnStage,
continuationBoundary, continuationAnchorPublished, continuationAnchorBoundary,
continuationPagePublished, continuationPageBoundary, continuationFetched,
shareReceipts, shareConflicts, windowClosed, missingShareClaims,
missingThresholdCertificates, recovered, recoveredSurfaces,
recoveryConflicts, aborted
Proof ==
INSTANCE NestedGuardianRecoveryRecurringProof
WITH Validators <- Validators,
Witnesses <- Witnesses,
Blocks <- Blocks,
Slots <- Slots,
Epochs <- Epochs,
QuorumSize <- QuorumSize,
MaxReassignmentDepth <- MaxReassignmentDepth,
InitialEpoch <- InitialEpoch,
InitialWitness <- InitialWitness,
TotalCycles <- TotalCycles,
TargetSlotOf <- TargetSlotOf,
TargetBlockOf <- TargetBlockOf,
StableEpochOf <- StableEpochOf,
SmallCommitteeSlot <- SmallCommitteeSlot,
SmallRecoveryThreshold <- SmallRecoveryThreshold,
LargeRecoveryThreshold <- LargeRecoveryThreshold,
SmallRecoveryCommittee <- SmallRecoveryCommittee,
LargeRecoveryCommittee <- LargeRecoveryCommittee,
votes <- votes,
witnessCerts <- witnessCerts,
finalized <- finalized,
finalizerSets <- finalizerSets,
registryEpoch <- registryEpoch,
guardianReady <- guardianReady,
witnessOnline <- witnessOnline,
witnessCheckpoint <- witnessCheckpoint,
assignedWitness <- assignedWitness,
reassignmentDepth <- reassignmentDepth,
currentCycle <- currentCycle,
phase <- phase,
churnStage <- churnStage,
continuationBoundary <- continuationBoundary,
continuationAnchorPublished <- continuationAnchorPublished,
continuationAnchorBoundary <- continuationAnchorBoundary,
continuationPagePublished <- continuationPagePublished,
continuationPageBoundary <- continuationPageBoundary,
continuationFetched <- continuationFetched,
shareReceipts <- shareReceipts,
shareConflicts <- shareConflicts,
windowClosed <- windowClosed,
missingShareClaims <- missingShareClaims,
missingThresholdCertificates <- missingThresholdCertificates,
recovered <- recovered,
recoveredSurfaces <- recoveredSurfaces,
recoveryConflicts <- recoveryConflicts,
aborted <- aborted
CycleRange == 1..TotalCycles
ClassicalAgreementDecisionObject(c) ==
[cycle |-> c,
slot |-> TargetSlotOf(c),
block |-> TargetBlockOf(c),
epoch |-> StableEpochOf(c)]
ClassicalAgreementPrefixObject(c) ==
[i \in 1..c |-> ClassicalAgreementDecisionObject(i)]
FiniteClassicalAgreementPrefixRealized(c) ==
/\ c \in CycleRange
/\ <>Proof!Core!RecoveryClosedPrefix(c)
FiniteClassicalAgreementLiveness ==
\A c \in CycleRange :
FiniteClassicalAgreementPrefixRealized(c)
ClassicalAgreementFiniteReduction ==
Proof!RecoveryRecurringClosedPrefixes
=> FiniteClassicalAgreementLiveness
THEOREM ProofCycleRangeMatchesCycleRange ==
Proof!Core!CycleRange = CycleRange
BY DEF Proof!Core!CycleRange, Proof!Core!Core!CycleRange, CycleRange
THEOREM FiniteClassicalAgreementPrefixFromRecurringPrefixes ==
\A c \in CycleRange :
Proof!RecoveryRecurringClosedPrefixes
=> FiniteClassicalAgreementPrefixRealized(c)
PROOF
<1>1. TAKE c \in CycleRange
<1>2. ASSUME Proof!RecoveryRecurringClosedPrefixes
PROVE FiniteClassicalAgreementPrefixRealized(c)
<2>1. c \in Proof!Core!CycleRange
BY ProofCycleRangeMatchesCycleRange, <1>1
<2>2. <>Proof!Core!RecoveryClosedPrefix(c)
BY <1>2, <2>1 DEF Proof!RecoveryRecurringClosedPrefixes
<2>3. QED
BY <1>1, <2>2 DEF FiniteClassicalAgreementPrefixRealized
<1>3. QED
BY <1>2
THEOREM ClassicalAgreementFiniteReductionTheorem ==
ClassicalAgreementFiniteReduction
BY FiniteClassicalAgreementPrefixFromRecurringPrefixes
DEF ClassicalAgreementFiniteReduction,
FiniteClassicalAgreementLiveness
====
NestedGuardianRecoveryClassicalAgreementTotality.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianRecoveryClassicalAgreementTotality.tla
---- MODULE NestedGuardianRecoveryClassicalAgreementTotality ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness, TotalCycles,
TargetSlotOf(_), TargetBlockOf(_), StableEpochOf(_),
SmallCommitteeSlot, SmallRecoveryThreshold, LargeRecoveryThreshold,
SmallRecoveryCommittee, LargeRecoveryCommittee
ASSUME InitialEpochInEpochs == InitialEpoch \in Epochs
ASSUME InitialWitnessInWitnesses == InitialWitness \in Witnesses
ASSUME QuorumSizeInValidatorRange == QuorumSize \in 1..Cardinality(Validators)
ASSUME TotalCyclesIsNat == TotalCycles \in Nat
ASSUME TotalCyclesAtLeastOne == TotalCycles >= 1
ASSUME TargetCycleDomains ==
\A c \in 1..TotalCycles :
/\ TargetSlotOf(c) \in Slots
/\ TargetBlockOf(c) \in Blocks
/\ StableEpochOf(c) \in Epochs
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth, currentCycle, phase, churnStage,
continuationBoundary, continuationAnchorPublished, continuationAnchorBoundary,
continuationPagePublished, continuationPageBoundary, continuationFetched,
shareReceipts, shareConflicts, windowClosed, missingShareClaims,
missingThresholdCertificates, recovered, recoveredSurfaces,
recoveryConflicts, aborted
Reduction ==
INSTANCE NestedGuardianRecoveryClassicalAgreementReduction
WITH Validators <- Validators,
Witnesses <- Witnesses,
Blocks <- Blocks,
Slots <- Slots,
Epochs <- Epochs,
QuorumSize <- QuorumSize,
MaxReassignmentDepth <- MaxReassignmentDepth,
InitialEpoch <- InitialEpoch,
InitialWitness <- InitialWitness,
TotalCycles <- TotalCycles,
TargetSlotOf <- TargetSlotOf,
TargetBlockOf <- TargetBlockOf,
StableEpochOf <- StableEpochOf,
SmallCommitteeSlot <- SmallCommitteeSlot,
SmallRecoveryThreshold <- SmallRecoveryThreshold,
LargeRecoveryThreshold <- LargeRecoveryThreshold,
SmallRecoveryCommittee <- SmallRecoveryCommittee,
LargeRecoveryCommittee <- LargeRecoveryCommittee,
votes <- votes,
witnessCerts <- witnessCerts,
finalized <- finalized,
finalizerSets <- finalizerSets,
registryEpoch <- registryEpoch,
guardianReady <- guardianReady,
witnessOnline <- witnessOnline,
witnessCheckpoint <- witnessCheckpoint,
assignedWitness <- assignedWitness,
reassignmentDepth <- reassignmentDepth,
currentCycle <- currentCycle,
phase <- phase,
churnStage <- churnStage,
continuationBoundary <- continuationBoundary,
continuationAnchorPublished <- continuationAnchorPublished,
continuationAnchorBoundary <- continuationAnchorBoundary,
continuationPagePublished <- continuationPagePublished,
continuationPageBoundary <- continuationPageBoundary,
continuationFetched <- continuationFetched,
shareReceipts <- shareReceipts,
shareConflicts <- shareConflicts,
windowClosed <- windowClosed,
missingShareClaims <- missingShareClaims,
missingThresholdCertificates <- missingThresholdCertificates,
recovered <- recovered,
recoveredSurfaces <- recoveredSurfaces,
recoveryConflicts <- recoveryConflicts,
aborted <- aborted
CycleRange == 1..TotalCycles
RecoveryRecurringClosedPrefixes == Reduction!Proof!RecoveryRecurringClosedPrefixes
RecoveryRecurringInductionPremises == Reduction!Proof!Core!RecoveryRecurringInductionPremises
RecoveryRecurringInductionKernel == Reduction!Proof!Core!RecoveryRecurringInductionKernel
RecoveryClosedPrefix(c) == Reduction!Proof!Core!RecoveryClosedPrefix(c)
ClassicalAgreementTotalHistoryObject ==
[i \in CycleRange |-> Reduction!ClassicalAgreementDecisionObject(i)]
ClassicalAgreementTotalHistoryExtendsFinitePrefixes ==
\A c \in CycleRange :
[i \in 1..c |-> ClassicalAgreementTotalHistoryObject[i]]
= Reduction!ClassicalAgreementPrefixObject(c)
TotalClassicalAgreementHistoryRealized ==
/\ <>RecoveryClosedPrefix(TotalCycles)
/\ ClassicalAgreementTotalHistoryExtendsFinitePrefixes
TotalClassicalAgreementReduction ==
Reduction!FiniteClassicalAgreementLiveness
=> TotalClassicalAgreementHistoryRealized
TotalClassicalAgreementFromRecurringPrefixes ==
RecoveryRecurringClosedPrefixes
=> TotalClassicalAgreementHistoryRealized
TotalClassicalAgreementFromRecurrenceKernel ==
/\ RecoveryRecurringInductionPremises
/\ RecoveryRecurringInductionKernel
=> TotalClassicalAgreementHistoryRealized
THEOREM TotalHistoryEntryMatchesDecisionObject ==
\A c \in CycleRange :
\A i \in 1..c :
ClassicalAgreementTotalHistoryObject[i]
= Reduction!ClassicalAgreementDecisionObject(i)
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF CycleRange, ClassicalAgreementTotalHistoryObject
THEOREM ClassicalAgreementTotalHistoryExtendsFinitePrefixesTheorem ==
ClassicalAgreementTotalHistoryExtendsFinitePrefixes
PROOF
<1>1. \A c \in CycleRange :
[i \in 1..c |-> ClassicalAgreementTotalHistoryObject[i]]
= Reduction!ClassicalAgreementPrefixObject(c)
PROOF
<2>1. TAKE c \in CycleRange
<2>2. \A i \in 1..c :
ClassicalAgreementTotalHistoryObject[i]
= Reduction!ClassicalAgreementDecisionObject(i)
BY TotalHistoryEntryMatchesDecisionObject, <2>1
<2>3. QED
BY IsaWithSetExtensionality, <2>1, <2>2
DEF Reduction!ClassicalAgreementPrefixObject
<1>2. QED
BY <1>1 DEF ClassicalAgreementTotalHistoryExtendsFinitePrefixes
THEOREM TotalCyclesInCycleRange ==
TotalCycles \in CycleRange
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne DEF CycleRange
THEOREM TotalFinitePrefixFromFiniteLiveness ==
Reduction!FiniteClassicalAgreementLiveness
=> Reduction!FiniteClassicalAgreementPrefixRealized(TotalCycles)
PROOF
<1>1. ASSUME Reduction!FiniteClassicalAgreementLiveness
PROVE Reduction!FiniteClassicalAgreementPrefixRealized(TotalCycles)
<2>1. TotalCycles \in Reduction!CycleRange
BY TotalCyclesInCycleRange DEF CycleRange, Reduction!CycleRange
<2>2. QED
BY <1>1, <2>1 DEF Reduction!FiniteClassicalAgreementLiveness
<1>2. QED
BY <1>1
THEOREM TotalRecoveryClosedPrefixFromFiniteLiveness ==
Reduction!FiniteClassicalAgreementLiveness
=> <>RecoveryClosedPrefix(TotalCycles)
BY TotalFinitePrefixFromFiniteLiveness
DEF Reduction!FiniteClassicalAgreementPrefixRealized,
RecoveryClosedPrefix
THEOREM TotalClassicalAgreementReductionTheorem ==
TotalClassicalAgreementReduction
BY TotalRecoveryClosedPrefixFromFiniteLiveness,
ClassicalAgreementTotalHistoryExtendsFinitePrefixesTheorem
DEF TotalClassicalAgreementReduction,
TotalClassicalAgreementHistoryRealized
THEOREM ReductionLivenessFromRecurringPrefixes ==
RecoveryRecurringClosedPrefixes
=> Reduction!FiniteClassicalAgreementLiveness
PROOF
<1>1. ASSUME RecoveryRecurringClosedPrefixes
PROVE Reduction!FiniteClassicalAgreementLiveness
<2>1. \A c \in Reduction!CycleRange :
Reduction!FiniteClassicalAgreementPrefixRealized(c)
PROOF
<3>1. TAKE c \in Reduction!CycleRange
<3>2. c \in Reduction!Proof!Core!CycleRange
BY <3>1
DEF Reduction!CycleRange,
Reduction!Proof!Core!CycleRange,
Reduction!Proof!Core!Core!CycleRange
<3>3. Reduction!Proof!RecoveryRecurringClosedPrefixes
BY <1>1 DEF RecoveryRecurringClosedPrefixes
<3>4. <>Reduction!Proof!Core!RecoveryClosedPrefix(c)
BY <3>2, <3>3 DEF Reduction!Proof!RecoveryRecurringClosedPrefixes
<3>5. QED
BY <3>1, <3>4 DEF Reduction!FiniteClassicalAgreementPrefixRealized
<2>2. QED
BY <2>1 DEF Reduction!FiniteClassicalAgreementLiveness
<1>2. QED
BY <1>1
THEOREM TotalClassicalAgreementFromRecurringPrefixesTheorem ==
TotalClassicalAgreementFromRecurringPrefixes
PROOF
<1>1. ASSUME RecoveryRecurringClosedPrefixes
PROVE TotalClassicalAgreementHistoryRealized
<2>1. Reduction!FiniteClassicalAgreementLiveness
BY ReductionLivenessFromRecurringPrefixes, <1>1
<2>2. Reduction!FiniteClassicalAgreementLiveness
=> TotalClassicalAgreementHistoryRealized
BY TotalClassicalAgreementReductionTheorem
DEF TotalClassicalAgreementReduction
<2>3. QED
BY <2>1, <2>2
<1>2. QED
BY <1>1 DEF TotalClassicalAgreementFromRecurringPrefixes
THEOREM RecoveryRecurringClosedPrefixesFromRecurrenceKernel ==
/\ RecoveryRecurringInductionPremises
/\ RecoveryRecurringInductionKernel
=> RecoveryRecurringClosedPrefixes
PROOF
<1>1. ASSUME RecoveryRecurringInductionPremises,
RecoveryRecurringInductionKernel
PROVE RecoveryRecurringClosedPrefixes
<2>1. \A c \in Reduction!Proof!Core!CycleRange :
<>Reduction!Proof!Core!RecoveryClosedPrefix(c)
PROOF
<3>1. TAKE c \in Reduction!Proof!Core!CycleRange
<3>2. Reduction!Proof!Core!RecoveryInductionPremisesUpTo(c)
PROOF
<4>1. Reduction!Proof!Core!RecoveryInductionBase
BY <1>1
DEF RecoveryRecurringInductionPremises,
Reduction!Proof!Core!RecoveryRecurringInductionPremises
<4>2. \A i \in Reduction!Proof!Core!PriorCycleRange(c) :
Reduction!Proof!Core!RecoveryInductionStep(i)
PROOF
<5>1. TAKE i \in Reduction!Proof!Core!PriorCycleRange(c)
<5>2. TotalCycles # 1
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne, <3>1, <5>1
DEF Reduction!Proof!Core!CycleRange,
Reduction!Proof!Core!Core!CycleRange,
Reduction!Proof!Core!PriorCycleRange
<5>3. i \in 1..(TotalCycles - 1)
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne, <3>1, <5>1
DEF Reduction!Proof!Core!CycleRange,
Reduction!Proof!Core!Core!CycleRange,
Reduction!Proof!Core!PriorCycleRange
<5>4. i \in Reduction!Proof!Core!PrefixAdvanceRange
BY <5>2, <5>3
DEF Reduction!Proof!Core!PrefixAdvanceRange,
Reduction!Proof!Core!Core!PrefixAdvanceRange
<5>5. QED
BY <1>1, <5>4
DEF RecoveryRecurringInductionPremises,
Reduction!Proof!Core!RecoveryRecurringInductionPremises
<4>3. QED
BY <3>1, <4>1, <4>2
DEF Reduction!Proof!Core!RecoveryInductionPremisesUpTo
<3>3. Reduction!Proof!Core!RecoveryClosedPrefixInductionKernel(c)
BY <1>1, <3>1
DEF RecoveryRecurringInductionKernel,
Reduction!Proof!Core!RecoveryRecurringInductionKernel
<3>4. QED
BY <3>2, <3>3
DEF Reduction!Proof!Core!RecoveryClosedPrefixInductionKernel
<2>2. QED
BY <2>1 DEF RecoveryRecurringClosedPrefixes,
Reduction!Proof!RecoveryRecurringClosedPrefixes
<1>2. QED
BY <1>1
DEF RecoveryRecurringClosedPrefixes,
RecoveryRecurringInductionPremises,
RecoveryRecurringInductionKernel,
Reduction!Proof!RecoveryRecurringClosedPrefixes
THEOREM TotalClassicalAgreementFromRecurrenceKernelTheorem ==
TotalClassicalAgreementFromRecurrenceKernel
PROOF
<1>1. ASSUME RecoveryRecurringInductionPremises,
RecoveryRecurringInductionKernel
PROVE TotalClassicalAgreementHistoryRealized
<2>1. RecoveryRecurringClosedPrefixes
BY RecoveryRecurringClosedPrefixesFromRecurrenceKernel, <1>1
<2>2. TotalClassicalAgreementFromRecurringPrefixes
BY TotalClassicalAgreementFromRecurringPrefixesTheorem
<2>3. QED
BY <2>1, <2>2 DEF TotalClassicalAgreementFromRecurringPrefixes
<1>2. QED
BY <1>1 DEF TotalClassicalAgreementFromRecurrenceKernel
====
NestedGuardianRecoveryClassicalAgreementCollapse.tla
Repository path: docs/architecture/protocols/aft/formal/nested_guardian/NestedGuardianRecoveryClassicalAgreementCollapse.tla
---- MODULE NestedGuardianRecoveryClassicalAgreementCollapse ----
EXTENDS Naturals, FiniteSets, TLC, TLAPS
CONSTANT Validators, Witnesses, Blocks, Slots, Epochs, QuorumSize, MaxReassignmentDepth,
InitialEpoch, InitialWitness, TotalCycles,
TargetSlotOf(_), TargetBlockOf(_), StableEpochOf(_),
SmallCommitteeSlot, SmallRecoveryThreshold, LargeRecoveryThreshold,
SmallRecoveryCommittee, LargeRecoveryCommittee
ASSUME InitialEpochInEpochs == InitialEpoch \in Epochs
ASSUME InitialWitnessInWitnesses == InitialWitness \in Witnesses
ASSUME QuorumSizeInValidatorRange == QuorumSize \in 1..Cardinality(Validators)
ASSUME TotalCyclesIsNat == TotalCycles \in Nat
ASSUME TotalCyclesAtLeastOne == TotalCycles >= 1
ASSUME TargetCycleDomains ==
\A c \in 1..TotalCycles :
/\ TargetSlotOf(c) \in Slots
/\ TargetBlockOf(c) \in Blocks
/\ StableEpochOf(c) \in Epochs
VARIABLES votes, witnessCerts, finalized, finalizerSets, registryEpoch, guardianReady, witnessOnline,
witnessCheckpoint, assignedWitness, reassignmentDepth, currentCycle, phase, churnStage,
continuationBoundary, continuationAnchorPublished, continuationAnchorBoundary,
continuationPagePublished, continuationPageBoundary, continuationFetched,
shareReceipts, shareConflicts, windowClosed, missingShareClaims,
missingThresholdCertificates, recovered, recoveredSurfaces,
recoveryConflicts, aborted
Totality ==
INSTANCE NestedGuardianRecoveryClassicalAgreementTotality
WITH Validators <- Validators,
Witnesses <- Witnesses,
Blocks <- Blocks,
Slots <- Slots,
Epochs <- Epochs,
QuorumSize <- QuorumSize,
MaxReassignmentDepth <- MaxReassignmentDepth,
InitialEpoch <- InitialEpoch,
InitialWitness <- InitialWitness,
TotalCycles <- TotalCycles,
TargetSlotOf <- TargetSlotOf,
TargetBlockOf <- TargetBlockOf,
StableEpochOf <- StableEpochOf,
SmallCommitteeSlot <- SmallCommitteeSlot,
SmallRecoveryThreshold <- SmallRecoveryThreshold,
LargeRecoveryThreshold <- LargeRecoveryThreshold,
SmallRecoveryCommittee <- SmallRecoveryCommittee,
LargeRecoveryCommittee <- LargeRecoveryCommittee,
votes <- votes,
witnessCerts <- witnessCerts,
finalized <- finalized,
finalizerSets <- finalizerSets,
registryEpoch <- registryEpoch,
guardianReady <- guardianReady,
witnessOnline <- witnessOnline,
witnessCheckpoint <- witnessCheckpoint,
assignedWitness <- assignedWitness,
reassignmentDepth <- reassignmentDepth,
currentCycle <- currentCycle,
phase <- phase,
churnStage <- churnStage,
continuationBoundary <- continuationBoundary,
continuationAnchorPublished <- continuationAnchorPublished,
continuationAnchorBoundary <- continuationAnchorBoundary,
continuationPagePublished <- continuationPagePublished,
continuationPageBoundary <- continuationPageBoundary,
continuationFetched <- continuationFetched,
shareReceipts <- shareReceipts,
shareConflicts <- shareConflicts,
windowClosed <- windowClosed,
missingShareClaims <- missingShareClaims,
missingThresholdCertificates <- missingThresholdCertificates,
recovered <- recovered,
recoveredSurfaces <- recoveredSurfaces,
recoveryConflicts <- recoveryConflicts,
aborted <- aborted
CycleRange == Totality!CycleRange
ClassicalAgreementDecision(c) ==
[cycle |-> c,
slot |-> TargetSlotOf(c),
block |-> TargetBlockOf(c),
epoch |-> StableEpochOf(c)]
ClassicalAgreementHistory(history) ==
\A i \in CycleRange :
history[i] = ClassicalAgreementDecision(i)
OrdinaryClassicalAgreementHistory(history) ==
/\ ClassicalAgreementHistory(history)
/\ <>Totality!RecoveryClosedPrefix(TotalCycles)
UnconditionalClassicalAgreementSentence ==
OrdinaryClassicalAgreementHistory(
Totality!ClassicalAgreementTotalHistoryObject
)
THEOREM TotalHistoryMatchesCollapsedClassicalHistory ==
ClassicalAgreementHistory(Totality!ClassicalAgreementTotalHistoryObject)
PROOF
<1>1. \A i \in CycleRange :
Totality!ClassicalAgreementTotalHistoryObject[i]
= ClassicalAgreementDecision(i)
PROOF
<2>1. TAKE i \in CycleRange
<2>2. QED
BY <2>1
DEF ClassicalAgreementDecision,
CycleRange,
Totality!ClassicalAgreementTotalHistoryObject,
Totality!Reduction!ClassicalAgreementDecisionObject
<1>2. QED
BY <1>1 DEF ClassicalAgreementHistory
THEOREM TotalityCyclePrefixEntriesStayInCycleRange ==
\A c \in Totality!CycleRange :
\A i \in 1..c :
i \in Totality!CycleRange
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF Totality!CycleRange
THEOREM TotalityReductionCorePriorCycleRangeImpliesPrefixAdvanceRange ==
\A c \in Totality!Reduction!Proof!Core!CycleRange :
\A i \in Totality!Reduction!Proof!Core!PriorCycleRange(c) :
i \in Totality!Reduction!Proof!Core!PrefixAdvanceRange
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF Totality!Reduction!Proof!Core!CycleRange,
Totality!Reduction!Proof!Core!Core!CycleRange,
Totality!Reduction!Proof!Core!PriorCycleRange,
Totality!Reduction!Proof!Core!PrefixAdvanceRange,
Totality!Reduction!Proof!Core!Core!PrefixAdvanceRange
THEOREM LocalReductionLivenessFromRecurringPrefixesTheorem ==
Totality!RecoveryRecurringClosedPrefixes
=> Totality!Reduction!FiniteClassicalAgreementLiveness
PROOF
<1>1. ASSUME Totality!RecoveryRecurringClosedPrefixes
PROVE Totality!Reduction!FiniteClassicalAgreementLiveness
<2>1. \A c \in Totality!Reduction!CycleRange :
Totality!Reduction!FiniteClassicalAgreementPrefixRealized(c)
PROOF
<3>1. TAKE c \in Totality!Reduction!CycleRange
<3>2. c \in Totality!Reduction!Proof!Core!CycleRange
BY <3>1
DEF Totality!Reduction!CycleRange,
Totality!Reduction!Proof!Core!CycleRange,
Totality!Reduction!Proof!Core!Core!CycleRange
<3>3. <>Totality!Reduction!Proof!Core!RecoveryClosedPrefix(c)
BY <1>1, <3>2
DEF Totality!RecoveryRecurringClosedPrefixes,
Totality!Reduction!Proof!RecoveryRecurringClosedPrefixes
<3>4. QED
BY <3>1, <3>3
DEF Totality!Reduction!FiniteClassicalAgreementPrefixRealized
<2>2. QED
BY <2>1 DEF Totality!Reduction!FiniteClassicalAgreementLiveness
<1>2. QED
BY <1>1
THEOREM LocalTotalClassicalAgreementHistoryFromFiniteLivenessTheorem ==
Totality!Reduction!FiniteClassicalAgreementLiveness
=> Totality!TotalClassicalAgreementHistoryRealized
PROOF
<1>1. ASSUME Totality!Reduction!FiniteClassicalAgreementLiveness
PROVE Totality!TotalClassicalAgreementHistoryRealized
<2>1. TotalCycles \in Totality!Reduction!CycleRange
BY SMT, TotalCyclesIsNat, TotalCyclesAtLeastOne
DEF Totality!Reduction!CycleRange
<2>2. Totality!Reduction!FiniteClassicalAgreementPrefixRealized(TotalCycles)
BY <1>1, <2>1 DEF Totality!Reduction!FiniteClassicalAgreementLiveness
<2>3. <>Totality!RecoveryClosedPrefix(TotalCycles)
BY <2>2
DEF Totality!Reduction!FiniteClassicalAgreementPrefixRealized,
Totality!RecoveryClosedPrefix
<2>4. Totality!ClassicalAgreementTotalHistoryExtendsFinitePrefixes
PROOF
<3>1. \A c \in Totality!CycleRange :
[i \in 1..c |-> Totality!ClassicalAgreementTotalHistoryObject[i]]
= Totality!Reduction!ClassicalAgreementPrefixObject(c)
PROOF
<4>1. TAKE c \in Totality!CycleRange
<4>2. \A i \in 1..c :
Totality!ClassicalAgreementTotalHistoryObject[i]
= Totality!Reduction!ClassicalAgreementDecisionObject(i)
PROOF
<5>1. TAKE i \in 1..c
<5>2. c \in 1..TotalCycles
BY <4>1 DEF Totality!CycleRange
<5>3. i \in Totality!CycleRange
BY TotalityCyclePrefixEntriesStayInCycleRange, <4>1, <5>1
<5>4. QED
BY <5>3
DEF Totality!ClassicalAgreementTotalHistoryObject
<4>3. QED
BY IsaWithSetExtensionality, <4>1, <4>2
DEF Totality!Reduction!ClassicalAgreementPrefixObject
<3>2. QED
BY <3>1 DEF Totality!ClassicalAgreementTotalHistoryExtendsFinitePrefixes
<2>5. QED
BY <2>3, <2>4 DEF Totality!TotalClassicalAgreementHistoryRealized
<1>2. QED
BY <1>1
THEOREM LocalRecurringPrefixesFromRecurrenceKernelTheorem ==
/\ Totality!RecoveryRecurringInductionPremises
/\ Totality!RecoveryRecurringInductionKernel
=> Totality!RecoveryRecurringClosedPrefixes
PROOF
<1>1. ASSUME Totality!RecoveryRecurringInductionPremises,
Totality!RecoveryRecurringInductionKernel
PROVE Totality!RecoveryRecurringClosedPrefixes
<2>1. \A c \in Totality!Reduction!Proof!Core!CycleRange :
<>Totality!Reduction!Proof!Core!RecoveryClosedPrefix(c)
PROOF
<3>1. TAKE c \in Totality!Reduction!Proof!Core!CycleRange
<3>2. /\ Totality!Reduction!Proof!Core!RecoveryRecurringInductionPremises
/\ Totality!Reduction!Proof!Core!RecoveryRecurringInductionKernel
BY <1>1
DEF Totality!RecoveryRecurringInductionPremises,
Totality!RecoveryRecurringInductionKernel
<3>3. Totality!Reduction!Proof!Core!RecoveryInductionPremisesUpTo(c)
PROOF
<4>1. Totality!Reduction!Proof!Core!RecoveryInductionBase
BY <3>2
DEF Totality!Reduction!Proof!Core!RecoveryRecurringInductionPremises
<4>2. \A i \in Totality!Reduction!Proof!Core!PriorCycleRange(c) :
Totality!Reduction!Proof!Core!RecoveryInductionStep(i)
PROOF
<5>1. TAKE i \in Totality!Reduction!Proof!Core!PriorCycleRange(c)
<5>2. i \in Totality!Reduction!Proof!Core!PrefixAdvanceRange
BY TotalityReductionCorePriorCycleRangeImpliesPrefixAdvanceRange,
<3>1, <5>1
<5>3. QED
BY <3>2, <5>2
DEF Totality!Reduction!Proof!Core!RecoveryRecurringInductionPremises
<4>3. QED
BY <3>1, <4>1, <4>2
DEF Totality!Reduction!Proof!Core!RecoveryInductionPremisesUpTo
<3>4. Totality!Reduction!Proof!Core!RecoveryClosedPrefixInductionKernel(c)
BY <3>1, <3>2
DEF Totality!Reduction!Proof!Core!RecoveryRecurringInductionKernel
<3>5. <>Totality!Reduction!Proof!Core!RecoveryClosedPrefix(c)
BY <3>3, <3>4
DEF Totality!Reduction!Proof!Core!RecoveryClosedPrefixInductionKernel
<3>6. (/\ Totality!Reduction!Proof!Core!RecoveryRecurringInductionPremises
/\ Totality!Reduction!Proof!Core!RecoveryRecurringInductionKernel)
=> <>Totality!Reduction!Proof!Core!RecoveryClosedPrefix(c)
BY <3>5
<3>7. QED
BY <3>5
<2>2. QED
BY <2>1
DEF Totality!RecoveryRecurringClosedPrefixes,
Totality!Reduction!Proof!RecoveryRecurringClosedPrefixes
<1>2. QED
BY <1>1
THEOREM UnconditionalClassicalAgreementFromTotalHistoryTheorem ==
Totality!TotalClassicalAgreementHistoryRealized
=> UnconditionalClassicalAgreementSentence
PROOF
<1>1. ASSUME Totality!TotalClassicalAgreementHistoryRealized
PROVE UnconditionalClassicalAgreementSentence
<2>1. ClassicalAgreementHistory(Totality!ClassicalAgreementTotalHistoryObject)
BY TotalHistoryMatchesCollapsedClassicalHistory
<2>2. <>Totality!RecoveryClosedPrefix(TotalCycles)
BY <1>1 DEF Totality!TotalClassicalAgreementHistoryRealized
<2>3. QED
BY <2>1, <2>2
DEF UnconditionalClassicalAgreementSentence,
OrdinaryClassicalAgreementHistory
<1>2. QED
BY <1>1
THEOREM UnconditionalClassicalAgreementFromRecurringPrefixesTheorem ==
Totality!RecoveryRecurringClosedPrefixes
=> UnconditionalClassicalAgreementSentence
PROOF
<1>1. ASSUME Totality!RecoveryRecurringClosedPrefixes
PROVE UnconditionalClassicalAgreementSentence
<2>1. Totality!Reduction!FiniteClassicalAgreementLiveness
BY LocalReductionLivenessFromRecurringPrefixesTheorem, <1>1
<2>2. Totality!TotalClassicalAgreementHistoryRealized
BY LocalTotalClassicalAgreementHistoryFromFiniteLivenessTheorem, <2>1
<2>3. QED
BY UnconditionalClassicalAgreementFromTotalHistoryTheorem, <2>2
<1>2. QED
BY <1>1
THEOREM UnconditionalClassicalAgreementFromRecurrenceKernelTheorem ==
/\ Totality!RecoveryRecurringInductionPremises
/\ Totality!RecoveryRecurringInductionKernel
=> UnconditionalClassicalAgreementSentence
PROOF
<1>1. ASSUME Totality!RecoveryRecurringInductionPremises,
Totality!RecoveryRecurringInductionKernel
PROVE UnconditionalClassicalAgreementSentence
<2>1. Totality!RecoveryRecurringClosedPrefixes
BY LocalRecurringPrefixesFromRecurrenceKernelTheorem, <1>1
<2>2. Totality!Reduction!FiniteClassicalAgreementLiveness
BY LocalReductionLivenessFromRecurringPrefixesTheorem, <2>1
<2>3. Totality!TotalClassicalAgreementHistoryRealized
BY LocalTotalClassicalAgreementHistoryFromFiniteLivenessTheorem, <2>2
<2>4. QED
BY UnconditionalClassicalAgreementFromTotalHistoryTheorem, <2>3
<1>3. QED
BY <1>1
====
References
- Maofan Yin, Dahlia Malkhi, Michael K. Reiter, Guy Golan-Gueta, and Ittai Abraham. HotStuff: BFT Consensus in the Lens of Blockchain. arXiv:1803.05069. https://arxiv.org/abs/1803.05069
- George Danezis, Lefteris Kokoris-Kogias, Alberto Sonnino, and Alexander Spiegelman. Narwhal and Tusk: A DAG-based Mempool and Efficient BFT Consensus. arXiv:2105.11827. https://arxiv.org/abs/2105.11827
- Ittai Abraham, Dahlia Malkhi, Kartik Nayak, Ling Ren, and Alexander Spiegelman. Bullshark: DAG BFT Protocols Made Practical. arXiv:2201.05677. https://arxiv.org/abs/2201.05677
- Andrew Miller, Yu Xia, Kyle Croman, Elaine Shi, and Dawn Song. The Honey Badger of BFT Protocols. Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. https://eprint.iacr.org/2016/199.pdf
- Bingyong Guo, Zhenliang Lu, Qiang Tang, Jing Xu, and Zhenfeng Zhang. Dumbo: Faster Asynchronous BFT Protocols. Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security. https://dblp.org/rec/conf/ccs/GuoL0XZ20
- Alistair Stewart and Eleftherios Kokoris-Kogias. GRANDPA: a Byzantine Finality Gadget. arXiv:2007.01560. https://arxiv.org/abs/2007.01560
- Jelena Dosenovic, Roger Wattenhofer, and others. Accountable Safety Implies Finality. arXiv:2308.16902. https://arxiv.org/abs/2308.16902
- Chainlink Labs. Chainlink CCIP's Defense-In-Depth Security and the Risk Management Network. Chainlink blog, 2023. https://blog.chain.link/ccip-risk-management-network/
- John P. Conley. Proof of Honesty: Coalition-Proof Blockchain Validation without Proof of Work or Stake. Geeq technical paper, version 2.0, 2019. https://geeq.io/wp-content/uploads/GEEQ-OFFICIAL-TECHNICAL-PAPER.pdf
- Sean Bowe, Jack Grigg, and Daira Hopwood. Halo: Recursive Proof Composition without a Trusted Setup. IACR ePrint 2019/1021. https://eprint.iacr.org/2019/1021
- Benedikt B{"u}nz, Alessandro Chiesa, Pratyush Mishra, and Nicholas Spooner. Proof-Carrying Data from Accumulation Schemes. IACR ePrint 2020/499. https://eprint.iacr.org/2020/499