{"id":21526952,"url":"https://github.com/lambdaclass/lambda_ethereum_consensus","last_synced_at":"2025-04-09T23:34:30.913Z","repository":{"id":180804093,"uuid":"664716838","full_name":"lambdaclass/lambda_ethereum_consensus","owner":"lambdaclass","description":"Elixir implementation of an Ethereum consensus client, which offers high reliance \u0026 fault tolerance","archived":false,"fork":false,"pushed_at":"2025-04-09T16:42:15.000Z","size":9280,"stargazers_count":110,"open_issues_count":140,"forks_count":37,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-09T16:48:09.422Z","etag":null,"topics":["consensus-client","eth2","ethereum"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lambdaclass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-07-10T15:31:02.000Z","updated_at":"2025-04-06T19:58:21.000Z","dependencies_parsed_at":"2023-12-27T11:24:30.443Z","dependency_job_id":"9380d41f-1930-416e-bfdf-153e6b1bb828","html_url":"https://github.com/lambdaclass/lambda_ethereum_consensus","commit_stats":null,"previous_names":["lambdaclass/lambda_ethereum_consensus"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flambda_ethereum_consensus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flambda_ethereum_consensus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flambda_ethereum_consensus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flambda_ethereum_consensus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lambdaclass","download_url":"https://codeload.github.com/lambdaclass/lambda_ethereum_consensus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248130264,"owners_count":21052726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consensus-client","eth2","ethereum"],"created_at":"2024-11-24T01:47:19.937Z","updated_at":"2025-04-09T23:34:30.900Z","avatar_url":"https://github.com/lambdaclass.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lambda Ethereum Consensus Client\n\n[![CI](https://github.com/lambdaclass/lambda_ethereum_consensus/actions/workflows/ci.yml/badge.svg)](https://github.com/lambdaclass/lambda_ethereum_consensus/actions/workflows/ci.yml)\n[![Telegram chat](https://img.shields.io/endpoint?url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Flambdaconsensus%2F\u0026logo=telegram\u0026label=chat\u0026color=neon)](https://t.me/lambdaconsensus)\n\n## Security\n\nWe take security seriously. If you discover a vulnerability in this project, please report it responsibly. \n\n- You can report vulnerabilities directly via the **[GitHub \"Report a Vulnerability\" feature](../../security/advisories/new)**.\n- Alternatively, send an email to **[security@lambdaclass.com](mailto:security@lambdaclass.com)**.\n\nFor more details, please refer to our [Security Policy](./.github/SECURITY.md).\n\n\n## Prerequisites\n\n### Basic Tools\n\n- [Git](https://git-scm.com/)\n- [wget](https://www.gnu.org/software/wget/)\n- [CMake](https://cmake.org/)\n\n### Direct Installation\n\nYou can install the necessary components directly from official sources:\n\n- [Elixir](https://elixir-lang.org/install.html)\n- [Erlang](https://www.erlang.org/downloads)\n- [Go](https://go.dev/doc/install)\n- [Rust](https://www.rust-lang.org/tools/install)\n- [Protoc](https://grpc.io/docs/protoc-installation/)\n\n### Alternative (Recommended) Installation\n\nFor precise control over versions, it's recommended to use the **asdf** tool version manager and follow the versions specified in `.tool-versions` in this repository.\n\n- [asdf tool version manager](https://asdf-vm.com/guide/getting-started.html)\n\nAfter installing **asdf**, add the required plugins for managing the tools:\n\n```shell\nasdf plugin add elixir\nasdf plugin add erlang\nasdf plugin add golang\nasdf plugin add rust\nasdf plugin add protoc\n```\n\nFinally, install the specific versions of these tools as specified in `.tool-versions`:\n\n```shell\nasdf install\n```\n\n### Alternative (easier) Installation using Nix \nTo create a sandbox environment with all the required tool chains, use Nix. Steps to get Nix working are as follows:\n\n1. Install Nix from the official website: https://nixos.org/download.\n2. To allow experimental features (nix develop and nix-command) you might need to do the following:\n\n```shell\nmkdir ~/.config/nix\necho \"experimental-features = nix-command flakes \" \u003e ~/.config/nix/nix.conf\n```\n\nAlternatively, for a smoother experience you can use the following script from [Determinate Systems](https://zero-to-nix.com/start/install) that takes care of setting up everything for you:\n\n```shell \ncurl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install\n```\n\n- Check if Nix has been successfully installed: `nix --version`.\n- To launch the environment: `nix develop`.\n\n## Installing and running\n\nThere are Makefile targets for these tasks.\n\n\u003e [!TIP]\n\u003e You can list the available targets with `make help`\n\n\u003e [!NOTE]\n\u003e If `make deps` is failing with `protoc-gen-go: program not found or is not executable` you might need to run\n\u003e ```Shell\n\u003e export PATH=$PATH:~/go/bin\n\u003e ```\n\n```shell\nmake deps # Installs dependencies\nmake iex  # Runs a terminal with the application started\n```\n\nThe iex terminal can be closed by pressing ctrl+c two times.\n\n\u003e [!WARNING]\n\u003e The node isn't capable of syncing from genesis yet, and so requires using checkpoint-sync to start (see [Checkpoint Sync](#checkpoint-sync)).\n\u003e In case checkpoint-sync is needed, `make iex` will end immediately with an error.\n\n### Checkpoint Sync\n\nYou can also sync from a checkpoint given by a trusted third-party.\nYou can specify a URL to fetch it from with the \"--checkpoint-sync-url\" flag:\n\n```shell\niex -S mix run -- --checkpoint-sync-url \u003cyour_url_here\u003e\n```\n\nSome public endpoints can be found in [eth-clients.github.io/checkpoint-sync-endpoints](https://eth-clients.github.io/checkpoint-sync-endpoints/).\n\n\u003e [!IMPORTANT]\n\u003e The data retrieved from the URL is stored in the DB once the node is initiated (i.e. the iex prompt shows).\n\u003e Once this happens, following runs of `make iex` will start the node using that data.\n\n### APIs\n#### Beacon API\n\nYou can start the application with the Beacon API on the default port `4000` running:\n```shell\nmake start\n```\n\nYou can also specify a port with the \"--beacon-api-port\" flag:\n\n```shell\niex -S mix run --  --beacon-api-port \u003cyour_port_here\u003e\n```\n\u003e [!WARNING]\n\u003e In case checkpoint-sync is needed, following the instructions above will end immediately with an error (see [Checkpoint Sync](#checkpoint-sync)).\n\u003e\n\n#### Key-Manager API\n\nImplemented following the [Ethereum specification](https://ethereum.github.io/keymanager-APIs/#/).\n\nYou can start the application with the key manager API on the default port `5000` running:\n\n```shell\niex -S mix run -- --validator-api\n```\n\n\nYou can also specify a port with the \"--validator-api-port\" flag:\n\n```shell\niex -S mix run -- --validator-api-port \u003cyour_port_here\u003e\n```\n\u003e [!WARNING]\n\u003e In case checkpoint-sync is needed, following the instructions above will end immediately with an error (see [Checkpoint Sync](#checkpoint-sync)).\n\u003e\n\n### Tests, linting and formatting\n\nOur CI runs tests, linters, and also checks formatting and typing.\nTo run these checks locally:\n\n```shell\nmake test      # Runs tests\nmake spec-test # Runs all spec-tests\nmake lint      # Runs linter and format-checker\nmake dialyzer  # Runs type-checker\n```\n\nSource code can be formatted using `make fmt`.\nThis formats not only the Elixir code, but also the code under [`native/`](./native/).\n\n### Consensus spec tests\n\nYou can run all of them with:\n\n```shell\nmake spec-test\n```\n\nOr only run those of a specific config with:\n\n```shell\nmake spec-test-config-`config`\n\n# Some examples\nmake spec-test-config-mainnet\nmake spec-test-config-minimal\nmake spec-test-config-general\n```\n\nOr by a single runner in all configs, with:\n\n```shell\nmake spec-test-runner-`runner`\n\n# Some examples\nmake spec-test-runner-ssz_static\nmake spec-test-runner-bls\nmake spec-test-runner-operations\n```\n\nThe complete list of test runners can be found [here](https://github.com/ethereum/consensus-specs/tree/dev/tests/formats).\n\nIf you want to specify both a config and a runner:\n\n```shell\nmake spec-test-mainnet-operations\nmake spec-test-minimal-epoch_processing\nmake spec-test-general-bls\n```\n\nMore advanced filtering (e.g. by fork or handler) will be re-added again, but if you want to only run a specific test, you can always do that manually with:\n\n```shell\nmix test --no-start test/generated/\u003cconfig\u003e/\u003cfork\u003e/\u003crunner\u003e.exs:\u003cline_of_your_testcase\u003e\n```\nYou can put a \"*\" in any directory (e.g. config) you don't want to filter by, although that won't work if adding the line of the testcase.\n\n\u003e [!NOTE]\n\u003e We specify the `--no-start` flag to stop *ExUnit* from starting the application, to reduce resource consumption.\n\n### Docker\n\nThe repo includes a `Dockerfile` for the consensus client. It can be built with:\n\n```bash\ndocker build -t consensus .\n```\n\nThen you run it with `docker run`, adding CLI flags as needed:\n\n```bash\ndocker run consensus --checkpoint-sync \u003curl\u003e --network \u003cnetwork\u003e ...\n```\n\n## Testing Environment with Kurtosis\n\nTo test the node locally, we can simulate other nodes and start from genesis using [`Kurtosis`](https://docs.kurtosis.com/) and the Lambda Class fork of [`ethereum-package`](https://github.com/lambdaclass/ethereum-package.git).\n\n### Why Use Kurtosis\nWe can test the process and transition of the Beacon state and execution of the consensus rules by connecting the node to Sepolia or even Mainnet. However, testing validators requires at least 32 ETH, which is hard to acquire even in Testnet, and being selected as a block proposer can be a never-ending task. For these reasons, and especially the ability to test multiple validators and completely different scenarios, the best approach currently is to use [`Kurtosis`](https://docs.kurtosis.com/). In combination with the [`ethereum-package`](https://github.com/lambdaclass/ethereum-package.git), kurtosis is a great way to simulate local testnets with a high level of control over the network participants.\n\n### Prerequisites\n- [`Docker`](https://docs.docker.com/get-docker/)\n- [`Kurtosis`](https://docs.kurtosis.com/install/#ii-install-the-cli)\n\n### Consensus node setup + ethereum-package\n\nAs stated in the `ethereum-package` README:\n\u003e This is a Kurtosis package that will spin up a private Ethereum testnet over Docker or Kubernetes with multi-client support, Flashbot's mev-boost infrastructure for PBS-related testing/validation, and other useful network tools (transaction spammer, monitoring tools, etc). Kurtosis packages are entirely reproducible and composable, so this will work the same way over Docker or Kubernetes, in the cloud or locally on your machine.\n\nAfter kurtosis is installed, we need to do three setup steps.\n\n1. Download the lambdaclass ethereum-package fork submodule's content.\n2. Copy our Grafana custom dashboards to be able to look at them\n3. Build the Docker image of the service\n\nWe can accomplish all the steps with a simple.\n\n```bash\nmake kurtosis.setup\n```\n\nor executed each at a time\n\n```bash \nmake kurtosis.setup.ethereum-package\n# git submodule update --init --recursive\n\nmake kurtosis.setup.grafana\n# cp -r ./metrics/grafana/provisioning/dashboards/* ./ethereum-package/static_files/grafana-config/dashboards/lambdaconsensus\n\nmake kurtosis.setup.lambdaconsensus\n# docker build --build-arg IEX_ARGS=\"--sname lambdaconsensus --cookie secret\" -t lambda_ethereum_consensus .\n\n# alternatively, you could build the repo without the node config and cookie just by running\n# docker build -t lambda_ethereum_consensus .\n```\n\nAfter that, we will be ready to tweak the configuration.\n\n```bash\nvim network_params.yaml\n```\n\nWe have some sensible defaults for a simple network of 3 clients with 64 Validators each (ethereum-package default) and a slight tweak to the memory limit. Here is an example of the doc; all parameters are explained in [their documentation](https://github.com/ethpandaops/ethereum-package?tab=readme-ov-file#configuration).\n\n```yaml\nparticipants:\n - el_type: geth\n    cl_type: lighthouse\n    count: 2\n - el_type: geth\n    cl_type: lambda\n    cl_image: lambda_ethereum_consensus:latest\n    use_separate_vc: false\n    count: 1\n    cl_max_mem: 4096\n    keymanager_enabled: true\n```\n\n### Kurtosis Execution and Make tasks\n\nFor starting the local environment after the setup run:\n\n```bash\n# Using the make task\nmake kurtosis.start\n\n# which executes\nkurtosis run --enclave lambdanet ./ethereum-package --args-file network_params.yaml\n```\n\nThen, you can connect to the service (running docker instance) with the following:\n\n```bash\n# to connect to the instance\nmake kurtosis.connect\n\n# you can specify the KURTOSIS_SERVICE if the config is different from the default provided:\nmake kurtosis.connect KURTOSIS_SERVICE=cl-6-lambda-geth\n```\n\nOnce inside the service, you can connect to the node with a new IEX session running the following.\n\n```bash\nmake kurtosis.connect.iex\n\n# if you set a specific cookie, you can add it as an argument as before\nmake kurtosis.connect.iex KURTOSIS_COOKIE=my_secret\n\n# which is just a convenient task over:\niex --sname client --remsh lambdaconsensus --cookie my_secret\n```\n\nNow you can check it is working, for example, by examining some constants:\n\n```elixir\n#Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:8:1] [ds:8:1:10] [async-threads:1] [jit]\n\n#Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help)\n\nConstants.versioned_hash_version_kzg()\n# \u003c\u003c1\u003e\u003e\n```\n\n### Kurtosis metrics\n\nThe [`ethereum-package`](https://github.com/lambdaclass/ethereum-package.git) has prometheus and grafana support built-in. Metrics are being picked up correctly by prometheus, and we have already copied our custom grafana dashboards during the setup step, so you can inspect all of that by accessing the home pages for any of the services (looking for the mapped docker ports). If you want to make changes to the dashboards and see them working with kurtosis afterward, you'll need to update them running again:\n\n```bash\nmake kurtosis.setup.grafana\n```\n\nBy default, `ethereum-package` shows it's dashboards in the home page, to see our custom dashboards it's needed to go to `Dashboards` in the left panel and then enter our own `lambdaconsensus` folder.\n\n### Kurtosis cleanup\n\nFor a complete cleanup, you could execute the following task.\n\n```bash\n# Stop, remove and clean\nmake kurtosis.purge\n```\n\nSuppose the stop was made manually, the purge failed in some step, or the environment was inconsistent for other reasons. In that case, It is also possible to execute every cleanup task individually avoiding the ones not needed:\n\n```bash\n# kurtosis enclave stop lambdanet\nmake kurtosis.stop\n# kurtosis enclave rm lambdanet\nmake kurtosis.remove\n# kurtosis clean -a\nmake kurtosis.clean\n\n# or do it all at once\nmake kurtosis.purge\n```\n\n## Live Metrics\n\nWhen running the node, use the `--metrics` flag to enable metrics at [`http://localhost:9568/metrics`](http://localhost:9568/metrics) in Prometheus format.\n\n### Grafana\n\nA docker-compose is available at [`metrics/`](./metrics) with a Grafana-Prometheus setup preloaded with dashboards that disponibilize the data.\nTo run it, install [Docker Compose](https://docs.docker.com/compose/) and execute:\n\n```shell\nmake grafana-up\n```\n\nAfter that, open [`http://localhost:3000/`](http://localhost:3000/) in a browser.\nThe default username and password are both `admin`.\n\nTo stop the containers run `make grafana-down`. For cleaning up the metrics data, run `make grafana-clean`.\n\n## Benchmarks\n\nSeveral benchmarks are provided in the `/bench` directory. They are all standard elixir scripts, so they can be run as such. For example:\n\n```bash\nmix run bench/byte_reversal.exs\n```\n\nSome of the benchmarks require a state or blocks to be available in the db. For this, the easiest thing is to run `make checkpoint-sync` so an anchor state and block are downloaded for mainnet, and optimistic sync starts. If the benchmark requires additional blocks, maybe wait until the first chunk is downloaded and block processing is executed at least once.\n\nSome need to be executed with `--mode db` in order to not have the store replaced by the application. This needs to be added at the end, like so:\n\n```bash\nmix run \u003cscript\u003e --mode db\n```\n\nA quick summary of the available benchmarks:\n\n- `deposit_tree`: measures the time of saving and loading an the \"execution chain\" state, mainly to test how much it costs to save and load a realistic deposit tree. Uses benchee. The conclusion was very low (the order of μs).\n- `byte_reversal`: compares three different methods for byte reversal as a bitlist/bitvector operation. This concludes that using numbers as internal representation for those types would be the most efficient. If we ever need to improve them, that would be a good starting point. \n- `shuffling_bench`: compares different methods for shuffling: shuffling a list in one go vs computing each shuffle one by one. Shuffling the full list was proved to be 10x faster.\n- `block_processing`: builds a fork choice store with an anchor block and state. Uses the next block available to apply `on_block`, `on_attestation` and `on_attester_slashing` handlers. Runs these handlers 30 times. To run this, at least 2 blocks and a state must be available in the db. It also needs you to set the slot manually at the beginning of an epoch. Try it for the slot that appeared when you ran checkpoint sync (you'll see in the logs something along the lines of `[Checkpoint sync] Received beacon state and block slot=9597856`)\n- `multiple_block_processing`: _currently under revision_. Similar to block processing but with a range of slots so state transition is performed multiple times. The main advantage is that by performing more than one state transition it helps test caches and have a more average-case measurement.\n- `SSZ benchmarks`: they compare between our own library and the rust nif ssz library. To run any of these two benchmarks you previously need to have a BeaconState in the database.\n  - `encode_decode_bench`: compares the libraries at encoding and decoding a Checkpoint and a BeaconState container. \n  - `hash_tree_root_bench`: compares the libraries at performing the hash tree root of a Beacon State and packed list of numbers.\n\n## Profiling\n\n### QCachegrind\n\nTo install [QCachegrind](https://github.com/KDE/kcachegrind) via [Homebrew](https://formulae.brew.sh/formula/qcachegrind), run:\n\n```sh\nbrew install qcachegrind\n```\n\nTo build a qcachegrind profile, run, inside iex:\n\n```elixir\nLambdaEthereumConsensus.Profile.build()\n```\n\nOptions and details are in the `Profile` package. After the profile trace is generated, you open it in qcachegrind with:\n\n```shell\nqcachegrind callgrind.out.\u003ctrace_name\u003e\n```\n\nIf you want to group the traces by function instead of process, you can use the following before viewing it in qcachegrind:\n\n```shell\ngrep -v \"^ob=\" callgrind.out.trace_name \u003e callgrind.out.merged.trace_name\n```\n\n### etop\n\nAnother useful tool to quickly diagnose processes taking too much CPU is `:etop`, similar to UNIX `top` command. This is installed by default in erlang, and included in the `:observer` extra application in `mix.exs`. You can run it with:\n\n```elixir\n:etop.start()\n```\n\nIn particular, the `reds` metric symbolizes `reductions`, which can roughly be interpreted as the number of calls a function got.\nThis can be used to identify infinite loops or busy waits.\n\nAlso of note is the `:sort` option, that allows sorting the list by, for example, message queue size:\n\n```elixir\n:etop.start(sort: :msg_q)\n```\n\n_Note: If you want to use the `:observer` GUI and not just `etop`, you'll probably need `:wx` also set in your extra applications, there is an easy way to do this, just set the `EXTRA_APPLICATIONS` environment variable to `WX` (`export EXTRA_APPLICATIONS=WX`) before starting the node_\n\n### eFlambè\n\nWhen optimizing code, it might be useful to have a graphic way to determine bottlenecks in the system.\nIn that case, you can use [eFlambè](https://github.com/Stratus3D/eflambe) to generate flamegraphs of specific functions.\nThe following code will capture information from 10 calls to `Handlers.on_block/2`, dumping it in different files named \\\u003ctimestamp\\\u003e-eflambe-output.bggg.\n\n```elixir\n:eflambe.capture({LambdaEthereumConsensus.ForkChoice, :on_block, 2}, 2)\n```\n\nThe files generated can be processed via common flamegraph tools.\nFor example, using [Brendan Gregg's stack](https://github.com/brendangregg/FlameGraph):\n\n```shell\ncat *-eflambe-output.bggg | flamegraph.pl - \u003e flamegraph.svg\n```\n\n## Why Elixir?\n\nElixir is a functional programming language that runs atop the Erlang Virtual Machine (BEAM). It offers enhanced readability, syntactic sugar, and reduced boilerplate, enabling developers to achieve more with fewer lines of code compared to Erlang. Like Erlang, Elixir compiles to bytecode that is interpreted by the VM. As a result, it inherits several notable properties, including:\n\n- Fault tolerance for increased reliability\n- High availability\n- Simplified construction of complex distributed systems\n- Predictable latency\n\n[Erlang](https://www.erlang.org/) and its VM were originally developed in 1986 for telecommunication systems that demanded unparalleled uptime and reliability. We recognize that these attributes could be immensely beneficial for an Ethereum client, particularly in the realm of consensus. This is why our current focus is on building a consensus layer (CL) rather than an execution layer (EL). Elixir may not be tailored for sheer performance, but it excels in delivering predictable latency and creating systems designed for continuous operation—qualities essential for the CL.\n\nOur aim is to infuse these strengths into the Ethereum consensus client ecosystem with our offering.\n\nWe also have for objective to bootstart an Ethereum Elixir community, and to make Elixir a first-class citizen in the Ethereum ecosystem.\n\n## Contributor Package\n\nDream of becoming an Ethereum core developer? Eager to shape the protocol that will underpin tomorrow's world? Want to collaborate with a passionate team, learn, grow, and be a pivotal part of the Ethereum Elixir community?\n\n**Then you're in the right place! 🚀**\n\n### Getting Started\n\n#### 1. **Installation**\n\n- **Prerequisites**: Before diving in, ensure you have the necessary tools installed. Check out the [Prerequisites](#prerequisites) section for guidance.\n  \n- **Clone the Repository**:\n\n  ```shell\n  git clone [REPO_URL]\n  cd lambda_ethereum_consensus\n  ```\n\n- **Setup**: Once you've cloned the repository, follow the steps in the [Installing and running](#installing-and-running) section to set up your environment.\n\n#### 2. **Prerequisite Knowledge**\n\nTo contribute effectively, you'll need a foundational understanding of both the Ethereum protocol and the Elixir language, including the Erlang VM (BEAM). If you're new to these areas, we've curated a list of resources to get you started:\n\n**Learning Elixir**:\n\n- **Videos**:\n  - [Intro to Elixir](https://youtube.com/playlist?list=PLJbE2Yu2zumA-p21bEQB6nsYABAO-HtF2)\n  - [Hitchhiker's tour of the BEAM](https://www.youtube.com/watch?v=_Pwlvy3zz9M)\n- **Blogs**:\n  - [Zen of Erlang](https://ferd.ca/the-zen-of-erlang.html)\n  - [Where Erlang Blooms](https://ferd.ca/rtb-where-erlang-blooms.html)\n  - [What can I only do in Erlang](https://erlang.org/pipermail/erlang-questions/2014-November/081570.html)\n  - [Stacking theory for systems design](https://medium.com/@jlouis666/stacking-theory-for-systems-design-2450e6300689)\n  - [On Erlang States and Crashes](http://jlouisramblings.blogspot.com/2010/11/on-erlang-state-and-crashes.html)\n  - [How Erlang does scheduling](http://jlouisramblings.blogspot.com/2013/01/how-erlang-does-scheduling.html)\n- **Books**:\n  - [Elixir in Action](https://www.manning.com/books/elixir-in-action-third-edition)\n  - [Learn You Some Erlang](https://learnyousomeerlang.com/)\n\nWith this foundation you should have a basic understanding of the Elixir language and the Erlang VM. You can then start (or in parallel) learning about the Ethereum protocol.\n\n**Learning Ethereum**:\n\n- **Videos**:\n  - [Basic technical details of Ethereum](https://youtu.be/gjwr-7PgpN8)\n  - [Ethereum in 30 minutes](https://youtu.be/UihMqcj-cqc)\n  - [Foundations of Blockchains](https://www.youtube.com/playlist?list=PLEGCF-WLh2RLOHv_xUGLqRts_9JxrckiA)\n  - [Ethereum Foundation youtube channel](https://www.youtube.com/@EthereumFoundation)\n  - [Ethereum youtube channel](https://www.youtube.com/@EthereumProtocol)\n- **Posts**\n  - [What happens when you send 1 DAI](https://www.notonlyowner.com/learn/what-happens-when-you-send-one-dai)\n- **Books**:\n  - [Inevitable Ethereum](https://inevitableeth.com/site/content)\n- **Blogs**:\n  - [Vitalik Buterin's blog](https://vitalik.ca/)\n  - [Ethereum Foundation blog](https://blog.ethereum.org/)\n  - [Ethereum Magicians forum](https://ethereum-magicians.org/)\n  - [Ethresear.ch forum](https://ethresear.ch/)\n  - [EIP's](https://eips.ethereum.org/)\n  - [ACD \u0026 Related meetings](https://github.com/ethereum/pm)\n- **Papers**:\n  - [Ethereum Whitepaper](https://ethereum.org/en/whitepaper/)\n  - [Ethereum Yellowpaper](https://ethereum.github.io/yellowpaper/paper.pdf)\n    - [Yellow paper discussion](https://www.youtube.com/watch?v=e84V1MxRlYs)\n    - [Yellow paper walkthrough](https://www.lucassaldanha.com/ethereum-yellow-paper-walkthrough-1/)\n  - [Ethereum Beige Paper](https://github.com/chronaeon/beigepaper/blob/master/beigepaper.pdf)\n  - [Ethereum Mauve Paper](https://cdn.hackaday.io/files/10879465447136/Mauve%20Paper%20Vitalik.pdf)\n\n**Learning Ethereum Consensus**:\n\n- **Books**:\n  - [Eth2Book by Ben Edgington](https://eth2book.info). This book is indispensable for understanding the Ethereum consensus protocol. If you can read only one thing, read this.\n- **Specifications**:\n  - [Consensus specs](https://github.com/ethereum/consensus-specs)\n  - [Vitalik Buterin's annotated specs](https://github.com/ethereum/annotated-spec)\n  - [Eth2Book annotated specs](https://eth2book.info/capella/part3/)\n\nWhile some of the resources listed might appear outdated, it's important to understand that the Ethereum protocol is continuously evolving. As such, there isn't a definitive, unchanging source of information. However, these resources, even if older, provide foundational knowledge that remains pertinent to understanding the protocol's core concepts.\n\nTruly mastering the Ethereum protocol is a complex endeavor. The list provided here is just a starting point, and delving deeper will necessitate exploring a broader range of readings and resources. As you immerse yourself in the project, continuous learning and adaptation will be key.\n\nIf you come across any resource that you find invaluable and believe should be added to this list, please don't hesitate to suggest its inclusion.\n\n#### 3. **Dive In**\n\nWith your newfound knowledge, explore the various areas of our project. Whether you're interested in the core consensus layer, networking, CLI, documentation, testing, or tooling, there's a place for you.\n\nStart by browsing our [issues](https://github.com/lambdaclass/lambda_ethereum_consensus/issues), especially those tagged as `good first issue`. These are beginner-friendly and a great way to familiarize yourself with our codebase.\n\n### How to contribute\n\nFound an issue you're passionate about? Comment with `\"I'd like to tackle this!\"` to claim it. Once assigned, you can begin your work. After completing your contribution, submit a pull request for review. Our team and other contributors will be able to provide feedback, and once approved, your contribution will be merged.\n\nPlease adhere to the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification when crafting PR titles. Also, run `make fmt` to format source code according to the configured style guide. The repo enforces these automatically via GitHub Actions.\n\n\u003e [!IMPORTANT]  \n\u003e We believe in fostering an inclusive, welcoming, and respectful community. All contributors are expected to adhere to our [Code of Conduct](#code-of-conduct). Please familiarize yourself with its contents before participating.\n\n### Communication\n\n**Open communication** is key to the success of any project. We encourage all contributors to join our [Telegram chat](https://t.me/lambdaconsensus) for real-time discussions, updates, and collaboration.\n\n**For more structured discussions or proposals**, consider opening an issue or a discussion on the GitHub repository.\n\n### Recognition\n\nWe value every contribution, no matter how small. All contributors will be recognized in our project's documentation. Additionally, consistent and significant contributors may be offered more formal roles within the project over time.\n\n### Support\n\nIf you encounter any issues or have questions, don't hesitate to reach out. Our team and the community are here to help. You can ask questions in our Telegram chat or open an issue on GitHub for technical challenges.\n\n### Conclusion\n\nLambda Ethereum Consensus is more than just a project; it's a community-driven initiative to bring the power and reliability of Elixir to the Ethereum ecosystem. With your help, we can make this vision a reality. Dive in, contribute, learn, and let's shape the future of Ethereum together!\n\n---\n\n**Thank you for being a part of our journey. Let's build an amazing future for Ethereum together! 🚀🌍**\n\n## Code of Conduct\n\n### Our Pledge\n\nWe, as members, contributors, and leaders of open source communities and projects pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community and project.\n\n### Our Standards\n\nExamples of behavior that contributes to a positive environment for our community include:\n\n- Demonstrating empathy and kindness toward other people.\n- Being respectful of differing opinions, viewpoints, and experiences.\n- Giving and gracefully accepting constructive feedback.\n- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience.\n- Focusing on what is best not just for us as individuals, but for the overall community and project.\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or advances of any kind.\n- Trolling, insulting or derogatory comments, and personal or political attacks.\n- Public or private harassment.\n- Publishing others' private information, such as a physical or electronic address, without their explicit permission.\n- Other conduct which could reasonably be considered inappropriate in a professional setting.\n\n## Enforcement Responsibilities\n\nMaintainers are responsible for clarifying and enforcing standards of acceptable behavior and will take appropriate and fair corrective action.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported with proof to the maintainers through Telegram. All complaints will be reviewed and investigated promptly, fairly and anonymously.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html), version 2.1.\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://www.linkedin.com/in/paul-henrykajfasz/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/42912740?v=4?s=100\" width=\"100px;\" alt=\"Paul-Henry Kajfasz\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePaul-Henry Kajfasz\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=phklive\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=phklive\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/MegaRedHand\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/47506558?v=4?s=100\" width=\"100px;\" alt=\"Tomás\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTomás\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=MegaRedHand\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/mpaulucci\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1040971?v=4?s=100\" width=\"100px;\" alt=\"Martin Paulucci\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMartin Paulucci\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=mpaulucci\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/Arkenan\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6244161?v=4?s=100\" width=\"100px;\" alt=\"Tomás Arjovsky\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTomás Arjovsky\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=Arkenan\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/h3lio5\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/47632450?v=4?s=100\" width=\"100px;\" alt=\"Akash S M\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAkash S M\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=h3lio5\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/berwingan\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/45144467?v=4?s=100\" width=\"100px;\" alt=\"berwin\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eberwin\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=berwingan\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=berwingan\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://f3r10.github.io/#/all-pages\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/4682815?v=4?s=100\" width=\"100px;\" alt=\"Fernando Ledesma\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eFernando Ledesma\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=f3r10\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/karasakalmt\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/32202283?v=4?s=100\" width=\"100px;\" alt=\"Mete Karasakal\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMete Karasakal\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=karasakalmt\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://federicocarrone.com/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/569014?v=4?s=100\" width=\"100px;\" alt=\"Federico Carrone\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eFederico Carrone\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=unbalancedparentheses\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://godspowereze.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/61994334?v=4?s=100\" width=\"100px;\" alt=\"Godspower Eze\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGodspower Eze\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=Godspower-Eze\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/namn-grg\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/97289118?v=4?s=100\" width=\"100px;\" alt=\"Naman Garg\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eNaman Garg\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=namn-grg\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ayushm2003\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/62571011?v=4?s=100\" width=\"100px;\" alt=\"Ayush\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAyush\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=ayushm2003\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=ayushm2003\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/sm-stack\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/94497407?v=4?s=100\" width=\"100px;\" alt=\"Seungmin Jeon\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSeungmin Jeon\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=sm-stack\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/manojkgorle\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/65953961?v=4?s=100\" width=\"100px;\" alt=\"Manoj\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eManoj\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=manojkgorle\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/avilagaston9\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/72628438?v=4?s=100\" width=\"100px;\" alt=\"Avila Gastón\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAvila Gastón\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=avilagaston9\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/guha-rahul\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/52607971?v=4?s=100\" width=\"100px;\" alt=\"guha-rahul\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eguha-rahul\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=guha-rahul\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/artemd24\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/19683603?v=4?s=100\" width=\"100px;\" alt=\"Artem\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eArtem\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/lambdaclass/lambda_ethereum_consensus/commits?author=artemd24\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaclass%2Flambda_ethereum_consensus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flambdaclass%2Flambda_ethereum_consensus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaclass%2Flambda_ethereum_consensus/lists"}