|
| 1 | +# Agda specification of the Consensus Layer |
| 2 | + |
| 3 | +This directory contains the Agda specification of the Consensus Layer. The current version of the specification only covers block header validation but, since this is work in progress, the specification will eventually cover other consensus-related features such as chain selection, HFC, mempools, etc. |
| 4 | + |
| 5 | +The specification is both *formal* (meaning that is machine-checked and amenable to formal proofs of properties) and *executable* (meaning that can be used as a reference implementation for conformance testing against the real implementation). |
| 6 | + |
| 7 | +## Directory structure |
| 8 | + |
| 9 | +The project is comprised by the following subdirectories: |
| 10 | + |
| 11 | +* `Axiom`: The Agda set theory library |
| 12 | + |
| 13 | +* `Data`: Extensions to the Agda standard library |
| 14 | + |
| 15 | +* `Foreign`: General utilities to automatically generate Haskell code from Agda code |
| 16 | + |
| 17 | +* `Interface`: General-purpose type classes not included in the Agda standard library |
| 18 | + |
| 19 | +* `InterfaceLibrary`: Interfaces exposed by other Cardano components, currently only for the Ledger Layer |
| 20 | + |
| 21 | + - `Common`: Component-agnostic features (e.g. stake pool distributions) |
| 22 | + |
| 23 | +* `Ledger`: Components borrowed from the Ledger specification, most of them actually not Ledger-specific (e.g. slots, epochs, cryptographic primitives) |
| 24 | + |
| 25 | +* `Reflection`: Extensions to the reflection support in the Agda standard library |
| 26 | + |
| 27 | +* `Tactic`: General-purpose tactics not included in the Agda standard library |
| 28 | + |
| 29 | +* `latex`: Auxiliary $$\LaTeX$$-related files required to generate the PDF version of the specification (e.g. fonts, references and static content) |
| 30 | + |
| 31 | +* `Spec`: Root directory of the specification |
| 32 | + |
| 33 | + - `<STS>.lagda` (e.g. `TickNonce.lagda` for TICKN): The definition of `<STS>` in a human-readable format |
| 34 | + |
| 35 | + - `<STS>/Properties.agda` (e.g. `TickNonce/Properties.agda` for TICKN): Proofs of properties about `<STS>`. In particular, this file contains a proof that `<STS>` can be 'computed' by a given function. This means that we have an executable version of `<STS>` which is guaranteed to be correct |
| 36 | + |
| 37 | + - `PDF.lagda`: Source Agda file from which the corresponding PDF file is generated |
| 38 | + |
| 39 | + - `Foreign`: Machinery required for the automatic generation of an executable (Haskell) version of the Agda specification |
| 40 | + |
| 41 | + - `HSConsensus/<STS>.agda` (e.g. `HSConsensus/TickNonce.agda` for TICKN): Contains the code to automatically generate the Haskell types used by `<STS>` and a \*`Step` Haskell function to execute `<STS>` |
| 42 | + |
| 43 | + - `ExternalFunctions.agda`: Automatically generates a Haskell record of 'external functions'. An external function is a function used by the Agda specification whose Haskell version should be provided by the calling environment. Dummy external functions are also available |
| 44 | + |
| 45 | + - `HSTypes.agda`: Generates Haskell versions for common Agda types used in the specification, such as sets and maps |
| 46 | + |
| 47 | + - `HSConsensus.agda`: Top-level Agda module from which the executable specification is generated |
| 48 | + |
| 49 | + - `hs-src`: A Haskell test suite for the executable specification |
| 50 | + |
| 51 | + - `test/<STS>Spec.hs` (e.g. `test/TickNonceSpec.hs` for TICKN): A Haskell program that tests the executable version of `<STS>` |
| 52 | + |
| 53 | +## Generating the PDF file |
| 54 | + |
| 55 | +To generate the specification in PDF format, one can use: |
| 56 | + |
| 57 | +``` bash |
| 58 | +> nix build .#agda-spec.docs |
| 59 | +``` |
| 60 | + |
| 61 | +This command generates the `consensus-spec.pdf` file inside the resulting `pdfs` directory. Alternatively, one can enter the Nix shell: |
| 62 | + |
| 63 | +``` bash |
| 64 | +> nix develop .#agda-spec |
| 65 | +``` |
| 66 | + |
| 67 | +and then use: |
| 68 | + |
| 69 | +``` bash |
| 70 | +> make docs |
| 71 | +``` |
| 72 | + |
| 73 | +This command generates the `consensus-spec.pdf` file inside the resulting `src/dist/pdfs` directory. Also, temporary artifacts resulting from the build (such as `.aux` and `.bbl` files) are stored in `src/latex`. To remove these temporary files, one can use: |
| 74 | + |
| 75 | +``` bash |
| 76 | +> make clean |
| 77 | +``` |
| 78 | + |
| 79 | +## Generating the executable specification |
| 80 | + |
| 81 | +### Building |
| 82 | + |
| 83 | +To build the executable (Haskell) specification, one can use: |
| 84 | + |
| 85 | +``` bash |
| 86 | +> nix build .#agda-spec.hsSrc |
| 87 | +``` |
| 88 | + |
| 89 | +This command compiles the Agda code into Haskell code using the MAlonzo backend, placing the files in the resulting subdirectory `haskell/Spec/MAlonzo/Code`. In addition, it copies the contents of `src/Spec/hs-src` to `haskell/Spec` and completes the `library.other-modules` section of the `cardano-consensus-executable-spec.cabal` file with the names of the Haskell modules just generated. |
| 90 | + |
| 91 | +Alternatively, one can enter the Nix shell: |
| 92 | + |
| 93 | +``` bash |
| 94 | +> nix develop .#agda-spec |
| 95 | +``` |
| 96 | + |
| 97 | +and then use: |
| 98 | + |
| 99 | +``` bash |
| 100 | +> make hs |
| 101 | +``` |
| 102 | + |
| 103 | +This command generates the same results as the previous alternative but using the directory `src/dist` as the temporary directory. As before, one can remove these temporary files by using: |
| 104 | + |
| 105 | +``` bash |
| 106 | +> make clean |
| 107 | +``` |
| 108 | + |
| 109 | +### Testing |
| 110 | + |
| 111 | +To run the test suite for the executable (Haskell) specification, one can use: |
| 112 | + |
| 113 | +``` bash |
| 114 | +> nix build .#agda-spec.hsExe --rebuild --print-build-logs 2>&1 |
| 115 | +``` |
| 116 | + |
| 117 | +The test results should show up near the end of the output. Alternatively, one can enter the Nix shell: |
| 118 | + |
| 119 | +``` bash |
| 120 | +> nix develop .#agda-spec |
| 121 | +``` |
| 122 | + |
| 123 | +and then use: |
| 124 | + |
| 125 | +``` bash |
| 126 | +> make hsTest |
| 127 | +``` |
| 128 | + |
| 129 | +## Setup without Nix |
| 130 | + |
| 131 | +It is possible to perform the above-mentioned tasks without the use of Nix, using the instructions below: |
| 132 | + |
| 133 | +- Install [latexmk](https://ctan.org/pkg/latexmk/) and [XeTeX](https://xetex.sourceforge.net/) |
| 134 | + |
| 135 | +- Install Agda version `2.7.0` (e.g. follow the instructions in <https://agda.readthedocs.io/en/v2.7.0/getting-started/installation.html#step-1-install-agda> |
| 136 | +) |
| 137 | + |
| 138 | +- In a folder `<LIB>`, clone the dependencies and checkout the respective commits/tags: |
| 139 | + |
| 140 | + | *Dependency* | *Tag/commit* | |
| 141 | + |--------------------------------------------------------------------|--------------------------------------------| |
| 142 | + | [agda-stdlib](https://github.com/agda/agda-stdlib) | `v2.1.1` | |
| 143 | + | [agda-stdlib-classes](https://github.com/agda/agda-stdlib-classes) | `73f4da05aeea040fea4587629f9fd83a8f04e656` | |
| 144 | + | [agda-stdlib-meta](https://github.com/agda/agda-stdlib-meta) | `v2.1.1` | |
| 145 | + |
| 146 | +- Create a file `<LIB>/libraries` with the following content: |
| 147 | +``` |
| 148 | +<LIB>/agda-stdlib/standard-library.agda-lib |
| 149 | +<LIB>/agda-stdlib-classes/agda-stdlib-classes.agda-lib |
| 150 | +<LIB>/agda-stdlib-meta/agda-stdlib-meta.agda-lib |
| 151 | +``` |
| 152 | + |
| 153 | +- Instead of `agda` use `agda --library-file <LIB>/libraries`. For example, to typecheck `Everything.agda`: |
| 154 | + ``` |
| 155 | + cd src/ |
| 156 | + agda --library-file <LIB>/libraries Everything.agda |
| 157 | + ``` |
| 158 | + |
| 159 | + To build targets from the Makefile (e.g. `docs`), use: |
| 160 | + ``` |
| 161 | + AGDA="agda --library-file <LIB>/libraries" make <TARGET> |
| 162 | + ``` |
0 commit comments