Thank you for taking the time to contribute 🙌
The following is a set of guidelines for contributing to the Consensus component of Cardano. If you have suggestions on how to improve this document, please feel free to propose changes to it in a pull request. Bear in mind that the document should remain simple. See the quick reference section if you are in a hurry.
Documentation should be a first-class citizen of the Consensus code base. We are in the process of improving the Consensus documentation, and your improvement proposals are welcome.
We have two types of documentation:
-
Markdown files, which can be found in the docs directory. They contain information that is not strictly related to the code itself, such as getting started guides, references, tutorials, etc.
They are rendered at the Consensus website.
-
Haddock comments. They contain more low level information about the code and should be used as a reference, although we aim to provide some context navigation (cross referencing modules) on the module descriptions.
When starting to work on Consensus, we recommend to take a look at the following resources:
When adding or improving documentation about the implementation, it is preferable to add haddock comments since they are closer to the code. However not all documentation can be placed inside haddock comments, and in such cases the contributor can update the markdown files in docs.
This repository also contains a technical report that describes the implementation of the Consensus layer. We will not update this report. We keep it here as a historical reference, and we will systematically convert the relevant parts of the report into the two types of documentation mentioned above.
When somebody asks a question about the code, we should try to refer people to the documentation. If no relevant entry exists, we should create it and submit a pull request.
For the time being, all markdown files that contain the Consensus documentation live in this repository.
Consensus can be built using Nix. The
installation and configuration instructions are taken from
cardano-node,
and detailed below. To install nix
run:
curl -L https://nixos.org/nix/install > install-nix.sh
chmod +x install-nix.sh
./install-nix.sh
Then enable the following features:
sudo mkdir -p /etc/nix
cat <<EOF | sudo tee /etc/nix/nix.conf
experimental-features = nix-command flakes
allow-import-from-derivation = true
EOF
As an optional step, to improve build speed (highly recommended), you can set up a binary cache maintained by IOG. If you use flakes, you will be asked to accept using it automatically; alternatively, you can add it globally:
sudo mkdir -p /etc/nix
cat <<EOF | sudo tee -a /etc/nix/nix.conf
substituters = https://cache.nixos.org https://cache.iog.io
trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
EOF
An alternative to using nix
is to set up the development
environment yourself. Follow these
instructions
to properly configure your system.
To build all the packages in this repository run:
cabal build all
in the command line, either inside nix-shell
if you use nix
, or in a
system with cabal
installed.
Specific executables can be executed through cabal once built:
cabal run db-analyser
To test all the packages in this repository run:
cabal test all
in the command line, either inside nix-shell
if you use nix
, or in a
system with cabal
installed.
For running specific test-suites (such as consensus-test
), we recommend one of
the following commands:
cabal run ouroboros-consensus:test:consensus-test -- <args>
cabal test ouroboros-consensus:test:consensus-test --test-show-details=direct
Note the second one cannot be used when we want to provide CLI arguments to the test-suite.
The following sections contain some guidelines that should be followed when contributing to the Consensus code base. Please take some time to go through them. We do not expect newcomers to adhere to these guidelines perfectly, and we will guide you through the process when reviewing your pull request.
This section contain guidelines on what to check when making a pull request.
- When bumping version bounds on the dependencies it is not necessary to increase the package version number. See this section.
- When you want to create a changelog entry, follow this and the following section.
Our git process describes
the git
practices we encourage when working with the code in this repository.
When submitting a pull request, please look update the relevant parts of the documentation (see this section).
We have a Haskell style guide that should be followed when writing code in Consensus. Our style guide is not set in stone, and improvements are always welcome.
We use stylish-haskell
0.14.6.0 for Haskell code formatting.
Either enable editor integration or call the script used by CI itself:
./scripts/ci/run-stylish.sh
When using Nix, you can use the following command, which will build and use
the right version of stylish-haskell
.
nix develop -c ./scripts/ci/run-stylish.sh
To generate the documentation, use the documentation script:
./scripts/docs/haddocks.sh
Often times, it is useful to have a
hoogle
server at hand, with the
packages and its dependencies. Our suggestion is to use
cabal-hoogle
which is included in
the nix
shell:
nix develop
$ cabal-hoogle generate
$ cabal-hoogle run -- server --local
This will fire a hoogle
server at https://localhost:8080/ with the local
packages and their dependencies.
If you are working on changing a substantial part of Consensus, it is important that you contact the core developers first to discuss design considerations (See section Contacting the developers). This will help detecting any potential problems with the change in the design phase, preventing misunderstandings and frustrations later on in the process.
We maintain a changelog. If your pull request requires a changelog entry, please follow these instructions. Even if your change doesn't require a changelog fragment, create an empty one as CI will reject your change otherwise. We made this choice to ensure authors of PRs would always take a moment to consider whether a changelog fragment should be added for their PR. For more information see our release process.
When creating a pull-request (PR), it is crucial that the PR:
-
has a clear description,
-
targets the
main
branch (unless there is a good reason not to), -
is as small as possible, and
-
is organized in a cohesive sequence of commits, each representing a meaningful, logical and reviewable step.
Our Haskell packages come from two package repositories:
- Hackage
- CHaP (which is essentially another Hackage)
The index-state
of each repository is pinned to a particular time in
cabal.project
. This tells Cabal to treat the repository as if it was the
specified time, ensuring reproducibility. If you want to use a package version
from repository X which was added after the pinned index state time, you need to
bump the index state for X. This is not a big deal, since all it does is change
what packages cabal
considers to be available when doing solving, but it will
change what package versions cabal picks for the plan, and so will likely result
in significant recompilation, and potentially some breakage. That typically just
means that we need to fix the breakage (increasing the lower-bound on the
problematic package if fix is not backward compatible), or delay that work and
instead decrease the upper-bound on the problematic package for now.
Note that cabal
's own persistent state includes which index states it is
aware of, so when you bump the pinned index state you may need to
call cabal update
in order for cabal
to be happy.
The Nix code which builds our packages also needs some information relating to
the index-state. This information needs to be new enough to include the
index-state specified in cabal.project
. The information is represented by Nix
flake inputs. You can update these by running:
nix flake update hackageNix
for Hackagenix flake update CHaP
for CHaP
If you fail to do this you may get an error like this from Nix:
error: Unknown index-state 2021-08-08T00:00:00Z, the latest index-state I know about is 2021-08-06T00:00:00Z. You may need to update to a newer hackage.nix.
The index-state
of the tools is pinned in ./nix/tools.nix
to ensure that an
incompatible change in the set of packages available in Hackage doesn't break
the shell. From time to time, this index-state
should be updated manually.
Sometimes, when creating pull requests to CHaP, it is desirable to loose/tighten certain dependencies bounds via a revision.
-
If you do so for a Consensus package, please first open a PR to Consensus mirroring the change in CHaP; but do not increment the version number of the Consensus package.
-
If your revision is about allowing a new version of package, please update the version bound in a way that keeps the previously allowed versions, unless this is undesirable due to eg a bug in an earlier version.
For example, if we have
cardano-ledger-core ^>= 1.1
and you want to also allow1.2
, use^>= 1.1 || ^>= 1.2
.
We can use Cabal's source-repository-package
mechanism to pull in
un-released package versions. This can be useful when debugging/developing
across different repositories. However, we should not release our packages
to CHaP while we depend on a source-repository-package
since downstream
consumers would not be able to build such package.
If we are stuck in a situation where we need a long-running fork of a package, we should release it to CHaP instead (see the CHaP README for more).
If you do add a temporary source-repository-package
stanza, you need to
provide a --sha256
comment in cabal.project
so that Nix knows the hash
of the content. There are two relatively straightforward ways to do this:
- The TOFU approach: put in the wrong hash and then Nix will tell you the correct one, which you can copy in.
- Calculate the hash with
nix-shell -p nix-prefetch-git --run 'nix-prefetch-git <URL> <COMMIT_HASH>'
When debugging an issue or when not using the shipped Nix shell, it is often desirable to know the exact version/revision of a specific tool or library as used by Nix.
To get the exact libsodium-vrf
used by Nix:
$ nix eval --json .#libsodium-vrf.src.rev
"dbb48cce5429cb6585c9034f002568964f1ce567"
To get the cabal-gild
version used by Nix:
$ nix eval --json .#cabal-gild.version
"1.3.0.1"
In more complex cases, you can start a Nix REPL and go on to explore interactively:
$ nix repl
nix-repl> :lf .
nix-repl> pkgs = legacyPackages.${__currentSystem}
nix-repl> pkgs.hsPkgs.ouroboros-consensus-cardano.components.exes.db-
pkgs.hsPkgs.ouroboros-consensus-cardano.components.exes.db-analyser pkgs.hsPkgs.ouroboros-consensus-cardano.components.exes.db-synthesizer
If you happen to encounter what you think is a bug or you wish there was some feature that was added to Consensus, please open an issue in our issue tracker.
We monitorize the repository constantly so we should be aware if you open a pull-request, however if some reasonable time passes and we miss your PR, feel free to ping someone from the team.
The core contributors to consensus codebase are:
See Cardano engineering handbook's code of conduct.