|
1 | 1 | # hydra-formal-specification |
2 | 2 |
|
3 | | -Agda specification for the hydra-protocol. |
| 3 | +Literate-Agda + Typst specification for the hydra-protocol. |
| 4 | + |
| 5 | +For an overview of the approach (the trust story, extraction pipeline and |
| 6 | +agreement tests), see the developer docs page `docs/docs/dev/agda.md` |
| 7 | +("Agda formalisation" on the docs site). |
| 8 | + |
| 9 | +The prose, math and figures are written in [Typst](https://typst.app); the source |
| 10 | +files are literate Typst (`.lagda.typ`) so that Agda code blocks are type-checked. |
| 11 | +Code fences render as follows (see `src/template.typ`): |
| 12 | + |
| 13 | +- ` ```agda ` blocks are type-checked by Agda **and** shown in the PDF (collected |
| 14 | + into the Agda appendix, grouped under the section they support; the body prose |
| 15 | + links there in place). |
| 16 | +- bare ` ``` ` blocks (module declarations, imports, proof bodies whose |
| 17 | + statements are shown separately) are type-checked but hidden. |
4 | 18 |
|
5 | 19 | ## Building |
6 | 20 |
|
7 | | -To produce the specification PDF in `result/`: |
| 21 | +To produce the specification PDF (via `nix build .#spec`): |
8 | 22 |
|
9 | 23 | ``` |
10 | | -nix build |
| 24 | +nix build .#spec |
11 | 25 | ``` |
12 | 26 |
|
| 27 | +The PDF is written to `result/hydra-spec.pdf`. |
| 28 | + |
13 | 29 | ## Developing / writing |
14 | 30 |
|
15 | | -In a nix shell (`nix develop` or using `nix-direnv`) you can type check: |
| 31 | +In a nix shell (`nix develop` or using `nix-direnv`) you can type-check the Agda: |
| 32 | + |
16 | 33 | ```sh |
17 | | -agda src/Hydra/Protocol/Main.lagda |
| 34 | +agda src/Hydra/Protocol/Main.lagda.typ |
18 | 35 | ``` |
19 | 36 |
|
20 | | -or build the PDF iteratively: |
21 | | -``` sh |
22 | | -shake |
| 37 | +or build the PDF iteratively with the build script (Agda typecheck + |
| 38 | +`check-refs.sh` + `check-trust-ledger.sh` + Typst render + a tooltip |
| 39 | +post-process, `annotate-notation.py`: invisible hover annotations giving the |
| 40 | +definition of each notation symbol; skip it with `ANNOTATE_NOTATION=skip`): |
| 41 | + |
| 42 | +```sh |
| 43 | +./build.sh |
23 | 44 | ``` |
24 | 45 |
|
25 | | -with the specification PDF available in `_build/hydra-spec.pdf`. |
| 46 | +with the specification PDF available in `_build/hydra-spec.pdf`. The script |
| 47 | +needs `JULIAMONO_FONT_DIR` (the code font); the nix dev shell exports it, so |
| 48 | +run it from `nix develop` (or set it to a directory containing the JuliaMono |
| 49 | +TTFs). Typst >= 0.14.1 is required (0.14.0 emits the PDF's named-destination |
| 50 | +table unsorted, typst#7248, which leaves internal section links dead in |
| 51 | +spec-compliant viewers); the dev shell and `nix build .#spec` provide a |
| 52 | +suitable typst. |
| 53 | + |
| 54 | +## Keeping the spec and the code in sync |
| 55 | + |
| 56 | +The machine-checked chain is: the `*Valid` bundles in the literate spec imply |
| 57 | +the decidable reference checkers (`Reference.agda`, proved in |
| 58 | +`ReferenceBridge.agda`), the checkers are extracted to Haskell |
| 59 | +(`hydra-agda/`, committed output regenerated by `hydra-agda/regenerate.sh`), |
| 60 | +and the extracted checkers are differentially tested against the real |
| 61 | +validators (`hydra-tx` `HeadValidatorAgreement`) and node logic (`hydra-node` |
| 62 | +off-chain agreement tests). Two flake checks gate all of this at PR time: |
| 63 | +`checks.spec` (the full spec build, including the consistency lints) and |
| 64 | +`checks.hydra-agda-generated` (fails if the committed extraction output is |
| 65 | +stale against the `.agda` sources). |
| 66 | + |
| 67 | +When you change something, the places to update: |
| 68 | + |
| 69 | +- **On-chain validator behaviour** (`hydra-plutus`, `deposit.ak`): update the |
| 70 | + transaction's section and `*Valid` bundle in |
| 71 | + `src/Hydra/Protocol/OnChain.lagda.typ`; if the changed condition is |
| 72 | + decidable, mirror it in `Reference.agda`, prove the bundle implies it in |
| 73 | + `ReferenceBridge.agda`, run `hydra-agda/regenerate.sh`, expose it in the |
| 74 | + `hydra-agda` shim, and extend the `HeadValidatorAgreement` family. New |
| 75 | + mocks/postulates in the bridge fail `check-trust-ledger.sh` until its |
| 76 | + trust-ledger table and `EXPECTED_*` lists are updated. |
| 77 | +- **Off-chain node behaviour** (`hydra-node` `HeadLogic`): update the §6 |
| 78 | + handler arms in `src/Hydra/Protocol/OffChain.lagda.typ` (and the protocol |
| 79 | + figure if the visible behaviour changed); mirror decidable decisions in |
| 80 | + `OffChainReference.agda` and bind them against the real handler in the |
| 81 | + `hydra-node` agreement tests. |
| 82 | +- **Datum/state shape**: `HeadDatum` in `OnChain.lagda.typ` plus the diagrams |
| 83 | + (`src/diagrams.typ` `state-fields`); `check-refs.sh` fails on constructor |
| 84 | + drift, but the per-state field *tuples* it does not compare, so eyeball the |
| 85 | + rendered figures. |
| 86 | +- **Discrepancies**: record anything found between the spec and the |
| 87 | + implementation in the PR description or an issue; the differential layer's |
| 88 | + trusted base (injected mocks and encoding/faithfulness postulates) is |
| 89 | + enumerated and drift-checked by `check-trust-ledger.sh`. |
0 commit comments