-
Notifications
You must be signed in to change notification settings - Fork 3
Update README #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update README #26
Changes from 10 commits
bb244bb
75f14b6
b7d6fec
28b06d9
22521e4
1bc053d
99eaebf
a3ed970
4818691
5a9ca32
198eb26
ce18b4b
ea10419
7c7bdfe
4286b09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,125 @@ | ||
| # qlean-mini | ||
| Lean Ethereum PQ devnet client implementation in C++ | ||
|
|
||
| Lean Ethereum consensus client for devnets, implemented in modern C++. | ||
|
|
||
| qlean-mini follows the Lean Ethereum devnet specification: | ||
| - Spec: https://github.com/leanEthereum/leanSpec/ | ||
|
|
||
| This repository builds a small, modular node binary called `qlean` and a set of loadable modules. It uses CMake, Ninja, and vcpkg (manifest mode) for dependency management. | ||
|
|
||
|
|
||
| ## Quick start | ||
|
|
||
| ### 0) Clone the repository and set system dependencies | ||
|
|
||
| ```bash | ||
| git clone https://github.com/qdrvm/qlean-mini.git | ||
| cd qlean-mini | ||
| ``` | ||
|
|
||
| Prerequisites: | ||
| - CMake ≥ 3.25 | ||
| - Ninja | ||
| - A C++23-capable compiler (AppleClang/Clang/GCC) | ||
| - Python 3 (required by the CMake build) | ||
| - vcpkg (manifest mode) | ||
|
|
||
| Note: Dependencies are also listed in the `.ci/.env` file for both macOS and Linux. To install on Debian Linux: | ||
|
|
||
| ```bash | ||
| source .ci/.env | ||
| sudo apt update && sudo apt install -y $(echo $LINUX_PACKAGES) | ||
| ``` | ||
|
|
||
| Make sure gcc-$GCC_VERSION is default compiler (where GCC_VERSION is defined in .ci/.env): | ||
|
|
||
| ```bash | ||
| sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-$GCC_VERSION 100 | ||
| sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-$GCC_VERSION 100 | ||
| ``` | ||
|
|
||
| For macOS: | ||
|
|
||
| ```zsh | ||
| source .ci/.env | ||
| brew install $(echo $MACOS_PACKAGES) | ||
| ``` | ||
|
|
||
| ### 1) Install and bootstrap vcpkg | ||
|
|
||
| ```zsh | ||
| # Clone vcpkg somewhere on your machine (e.g. in your home directory) | ||
| git clone https://github.com/microsoft/vcpkg.git "$HOME/vcpkg" | ||
|
|
||
| # Bootstrap vcpkg | ||
| "$HOME/vcpkg"/bootstrap-vcpkg.sh | ||
|
|
||
| # Export VCPKG_ROOT for the current shell session (and add to ~/.zshrc if use zsh for convenience) | ||
| export VCPKG_ROOT="$HOME/vcpkg" | ||
| ``` | ||
|
|
||
| Notes: | ||
| - This project uses vcpkg in manifest mode with custom overlay ports from `vcpkg-overlay/` and the registry settings in `vcpkg-configuration.json`. | ||
| - CMake presets expect `CMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake`. | ||
|
|
||
| ### 2) Configure and build | ||
|
|
||
| Use the provided CMake preset (generator: Ninja): | ||
|
|
||
| ```zsh | ||
| # From the repository root | ||
| cmake --preset default | ||
| cmake --build build -j | ||
| ``` | ||
|
|
||
| You can also build the project's Docker images (builder + runtime) with: | ||
|
|
||
| ```zsh | ||
| make docker_build_all | ||
| ``` | ||
|
|
||
| See the `Makefile` for more Docker targets. | ||
|
|
||
| This will: | ||
| - Configure the project into `./build/` | ||
| - Build the main node executable at `./build/src/executable/qlean` | ||
|
|
||
| ### 3) Ensure build was successful | ||
| Print help: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean --help | ||
| ``` | ||
|
|
||
| ## Run the node | ||
|
|
||
| For step-by-step instructions to run a local single-node devnet, see `example/0-single/README.md`. It includes the exact CLI command and an explanation of all flags. | ||
|
|
||
|
|
||
| ## Generate a node key | ||
|
|
||
| The binary includes a helper subcommand to generate a node key and corresponding PeerId: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean key generate-node-key | ||
| ``` | ||
|
|
||
| This prints two lines: | ||
| 1) The private key (hex) | ||
| 2) The PeerId (base58) | ||
|
|
||
|
|
||
| ## Tests | ||
|
|
||
| If `TESTING` is enabled (default ON in top-level CMakeLists), tests are built and can be run with CTest: | ||
|
|
||
| ```zsh | ||
| # After building | ||
| ctest --test-dir build --output-on-failure | ||
| ``` | ||
|
|
||
| Individual test binaries are placed under `build/test_bin/`. | ||
|
|
||
| ## License | ||
|
|
||
| SPDX-License-Identifier: Apache-2.0 — Copyright Quadrivium LLC | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # 0-single — run a single-node devnet | ||
|
|
||
| This example shows how to start a one-node network using the `qlean` binary built from this repository. | ||
|
|
||
| Files in this folder: | ||
| - `genesis/config.yaml` — genesis settings (e.g., `GENESIS_TIME`, `VALIDATOR_COUNT`) | ||
| - `genesis/validators.yaml` — validator registry for this example | ||
| - `genesis/nodes.yaml` — static bootnodes list used at startup | ||
|
|
||
| Prerequisites: | ||
| - Build the project first. See the root README “Quick start” for setup and build steps. | ||
| - Run commands from the repository root so relative paths resolve correctly. | ||
|
|
||
| ## Start the node | ||
|
|
||
| Before starting the node, update the GENESIS_TIME in the genesis config file to a future Unix timestamp (e.g., current time + 20 seconds) to allow the node to bootstrap the network. For example: | ||
|
|
||
| ```bash | ||
| future_time=$(( $(date +%s) + 20 )) | ||
| sed -i "s/GENESIS_TIME: .*/GENESIS_TIME: $future_time/" example/0-single/genesis/config.yaml | ||
| ``` | ||
|
|
||
| Example CLI command: | ||
|
|
||
|
||
| ```zsh | ||
| ./build/src/executable/qlean \ | ||
| --modules-dir ./build/src/modules \ | ||
| --bootnodes example/0-single/genesis/nodes.yaml \ | ||
| --validator-registry-path example/0-single/genesis/validators.yaml \ | ||
| --node-id node_0 \ | ||
| --genesis example/0-single/genesis/config.yaml \ | ||
| --node-key cb920fbda3b96e18f03e22825f4a5a61343ec43c7be1c8c4a717fffee2f4c4ce \ | ||
| --listen-addr /ip4/0.0.0.0/udp/9000/quic-v1 | ||
| ``` | ||
|
|
||
| ## What each flag means | ||
|
|
||
| - `--modules-dir ./build/src/modules` | ||
| - Where the node looks for loadable modules built by this repository. The default build places them under `./build/src/modules`. | ||
| - `--bootnodes example/0-single/genesis/nodes.yaml` | ||
| - A YAML file with a list of peers (ENRs or multiaddrs) used for initial connectivity. | ||
| - `--validator-registry-path example/0-single/genesis/validators.yaml` | ||
| - The validator registry for this devnet. For a single-node network, it typically contains a single validator. | ||
| - `--node-id node_0` | ||
| - A human-friendly identifier used in logs and for distinguishing nodes when running multiple instances. | ||
| - `--genesis <path>` | ||
| - Genesis configuration describing initial chain parameters, such as `GENESIS_TIME` and the number of validators. | ||
| - `--node-key <hex>` | ||
| - Hex-encoded libp2p private key. Using a fixed key gives a stable PeerId across restarts. You can generate one with: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean key generate-node-key | ||
| ``` | ||
| - `--listen-addr /ip4/0.0.0.0/udp/9000/quic-v1` | ||
| - libp2p multiaddress to bind the QUIC transport. Adjust the port if `9000` is taken, or bind to `127.0.0.1` if you want local-only access. | ||
|
|
||
| ## Tips | ||
|
|
||
| - If the binary cannot find modules, double-check you built the project and the `--modules-dir` path is correct. | ||
| - You can run multiple nodes by copying this command and changing `--node-id`, `--node-key`, ports in `--listen-addr`, and using appropriate bootnodes. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Genesis Settings | ||
| GENESIS_TIME: 946684803 | ||
|
|
||
| # Validator Settings | ||
| VALIDATOR_COUNT: 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| - enr:-IW4QIh9cSo0CPOcsTq5T6SAYr0HrGFMYekZjrgC7ZTgdsMhBKjIQgzCfgqsxulCO4O1TXyjRLZ3BYc4GgqVRvl3d1sBgmlkgnY0gmlwhAoAAAqEcXVpY4IjKIlzZWNwMjU2azGhAmVoFLEuozqtJ7uxbf6RlL8ow-UlDKSYLzxKcbpZ13Zg | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| node_0: | ||
| - 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # 1-network — run a 4-validator devnet | ||
|
|
||
| This example shows how to start a 4-validator network using the `qlean` binary built from this repository. | ||
|
|
||
| Files in this folder: | ||
| - `genesis/config.yaml` — genesis settings (e.g., `GENESIS_TIME`, `VALIDATOR_COUNT`) | ||
| - `genesis/validators.yaml` — validator registry for this network | ||
| - `genesis/nodes.yaml` — bootnodes list used at startup | ||
|
|
||
| Prerequisites: | ||
| - Build the project first. See the root README “Quick start” for setup and build steps. | ||
| - Run commands from the repository root so relative paths resolve correctly. | ||
|
|
||
| ## Prepare genesis time | ||
|
|
||
| Before starting nodes, set `GENESIS_TIME` in `example/1-network/genesis/config.yaml` to a future Unix timestamp so the chain can start. For example, current time + 20 seconds: | ||
|
|
||
| ```bash | ||
| future_time=$(( $(date +%s) + 20 )) | ||
| sed -i "s/GENESIS_TIME: .*/GENESIS_TIME: $future_time/" example/1-network/genesis/config.yaml | ||
| ``` | ||
|
|
||
| ## Start the 4 validators | ||
|
|
||
| Open four terminals (or run in background) and launch each node with its own key and ports. | ||
|
|
||
| Node 0: | ||
|
|
||
|
||
| ```zsh | ||
| ./build/src/executable/qlean \ | ||
| --modules-dir ./build/src/modules \ | ||
| --bootnodes example/1-network/genesis/nodes.yaml \ | ||
| --genesis example/1-network/genesis/config.yaml \ | ||
| --validator-registry-path example/1-network/genesis/validators.yaml \ | ||
| --node-id node_0 \ | ||
| --node-key cb920fbda3b96e18f03e22825f4a5a61343ec43c7be1c8c4a717fffee2f4c4ce \ | ||
| --listen-addr /ip4/0.0.0.0/udp/9000/quic-v1 \ | ||
| --prometheus_port 9100 | ||
| ``` | ||
|
|
||
| Node 1: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean \ | ||
| --modules-dir ./build/src/modules \ | ||
| --bootnodes example/1-network/genesis/nodes.yaml \ | ||
| --genesis example/1-network/genesis/config.yaml \ | ||
| --validator-registry-path example/1-network/genesis/validators.yaml \ | ||
| --node-id node_1 \ | ||
| --node-key a87e7d23bb1de4613b67002b700bce41e031f4ab1529a3436bd73c893ea039b3 \ | ||
| --listen-addr /ip4/0.0.0.0/udp/9001/quic-v1 \ | ||
| --prometheus_port 9101 | ||
| ``` | ||
|
|
||
| Node 2: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean \ | ||
| --modules-dir ./build/src/modules \ | ||
| --bootnodes example/1-network/genesis/nodes.yaml \ | ||
| --genesis example/1-network/genesis/config.yaml \ | ||
| --validator-registry-path example/1-network/genesis/validators.yaml \ | ||
| --node-id node_2 \ | ||
| --node-key f2f53f6acf312c5e92c2a611bbca7a1932b4db0b9e0c43bec413badca9b76760 \ | ||
| --listen-addr /ip4/0.0.0.0/udp/9002/quic-v1 \ | ||
| --prometheus_port 9102 | ||
| ``` | ||
|
|
||
| Node 3: | ||
|
|
||
| ```zsh | ||
| ./build/src/executable/qlean \ | ||
| --modules-dir ./build/src/modules \ | ||
| --bootnodes example/1-network/genesis/nodes.yaml \ | ||
| --genesis example/1-network/genesis/config.yaml \ | ||
| --validator-registry-path example/1-network/genesis/validators.yaml \ | ||
| --node-id node_3 \ | ||
| --node-key fa5ddbec80f964d17d28221c2c5bac0f4a3f9cfcf4b86674e605f459e195a1c4 \ | ||
| --listen-addr /ip4/0.0.0.0/udp/9003/quic-v1 \ | ||
| --prometheus_port 9103 | ||
| ``` | ||
|
|
||
| ## Notes and tips | ||
|
|
||
| - Start Node 0 first so others can discover it via the bootnodes list; the rest can follow in any order. | ||
| - Ports (9000–9003) must be free; adjust if they’re taken. Prometheus ports (9100–9103) are optional and can be changed or omitted. | ||
| - For an explanation of the common flags, see `example/0-single/README.md` (the meanings are the same). | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Genesis Settings | ||
| GENESIS_TIME: 946684803 | ||
|
|
||
| # Validator Settings | ||
| VALIDATOR_COUNT: 4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| - enr:-IW4QIh9cSo0CPOcsTq5T6SAYr0HrGFMYekZjrgC7ZTgdsMhBKjIQgzCfgqsxulCO4O1TXyjRLZ3BYc4GgqVRvl3d1sBgmlkgnY0gmlwhAoAAAqEcXVpY4IjKIlzZWNwMjU2azGhAmVoFLEuozqtJ7uxbf6RlL8ow-UlDKSYLzxKcbpZ13Zg | ||
| - enr:-IW4QG_-KOB94fI18bEqxW8B_lKgG3cGVdvKIIKdZJBLftoaZE5y3Vg4PFQQIPmIRpeD1QawVKrd_6HDd1D2K7WLsLQBgmlkgnY0gmlwhAoAAAuEcXVpY4IjKYlzZWNwMjU2azGhA8PFJzjZs3Nmzn34yVzbnN5Mo5RhzwiWDxLnmoW1U7AV | ||
| - enr:-IW4QDEHjhkVEcEX5GS4qAjAHbiqCevwjwFd6ce1SYxLEIgYXDmozUjm8ao4Nl1YoFVhNBs1cn8zW2kwb6yaJpgVDLkBgmlkgnY0gmlwhAoAAAyEcXVpY4IjKolzZWNwMjU2azGhAsQeX5os8a2pG4v2cGuMMXZYY2B-yzYLcZM3yEHa3_kW | ||
| - enr:-IW4QEgn7uYKIhbom8qWeFGWBTOh_WZGKjLCfoJay5PHND9yAG359yxsK84DBxfOWm86U5zvVF_UbCO5n1Uz6P2tG28BgmlkgnY0gmlwhAoAAA2EcXVpY4IjK4lzZWNwMjU2azGhAhXhXn0CrP2llJ7PNcWcimcUJ31GeGVMfk0MF2lnH4Ri | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| node_0: | ||
| - 0 | ||
| node_1: | ||
| - 1 | ||
| node_2: | ||
| - 2 | ||
| node_3: | ||
| - 3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| Shadow example | ||
| =============== | ||
|
|
||
| Quick steps | ||
|
|
||
| 1) Install Shadow | ||
|
|
||
| Follow the official guide: https://github.com/shadow/shadow | ||
|
|
||
| 2) Update paths | ||
|
|
||
| Replace the placeholder `/path/to/qlean-mini` in `shadow/shadow.yaml` with your project root. From the project root run: | ||
|
|
||
| ```bash | ||
| cd /path/to/qlean-mini | ||
| sed -i "s|/path/to/qlean-mini|$(pwd)|g" shadow/shadow.yaml | ||
|
||
| ``` | ||
|
|
||
| 3) Run the example | ||
|
|
||
| ```bash | ||
| shadow --progress true --parallelism $(nproc) shadow/shadow.yaml | ||
|
||
| ``` | ||
|
|
||
| 4) Cleanup | ||
|
|
||
| Remove generated state before re-running: | ||
|
|
||
| ```bash | ||
| rm -rf shadow.data | ||
| ``` | ||
|
|
||
| Notes | ||
| - Ensure the `qlean` executable path in `shadow/shadow.yaml` points to your built binary (build it if needed). | ||
| - If you run Shadow from a different directory, make all paths in `shadow/shadow.yaml` absolute. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| general: | ||
| stop_time: 60s | ||
| model_unblocked_syscall_latency: true | ||
| experimental: | ||
| native_preemption_enabled: true | ||
| network: | ||
| graph: | ||
| type: 1_gbit_switch | ||
| hosts: | ||
| node0: | ||
| network_node_id: 0 | ||
| ip_addr: 10.0.0.10 | ||
| processes: | ||
| - path: build/src/executable/qlean | ||
| args: --modules-dir /path/to/qlean-mini/build/src/modules --bootnodes /path/to/qlean-mini/example/1-network/genesis/nodes.yaml --genesis /path/to/qlean-mini/example/1-network/genesis/config.yaml --validator-registry-path /path/to/qlean-mini/example/1-network/genesis/validators.yaml --node-id node_0 --node-key cb920fbda3b96e18f03e22825f4a5a61343ec43c7be1c8c4a717fffee2f4c4ce --listen-addr /ip4/0.0.0.0/udp/9000/quic-v1 --prometheus_port 9100 | ||
| expected_final_state: running | ||
|
|
||
| node1: | ||
| network_node_id: 0 | ||
|
||
| ip_addr: 10.0.0.11 | ||
| processes: | ||
| - path: build/src/executable/qlean | ||
| args: --modules-dir /path/to/qlean-mini/build/src/modules --bootnodes /path/to/qlean-mini/example/1-network/genesis/nodes.yaml --genesis /path/to/qlean-mini/example/1-network/genesis/config.yaml --validator-registry-path /path/to/qlean-mini/example/1-network/genesis/validators.yaml --node-id node_1 --node-key a87e7d23bb1de4613b67002b700bce41e031f4ab1529a3436bd73c893ea039b3 --listen-addr /ip4/0.0.0.0/udp/9001/quic-v1 --prometheus_port 9101 | ||
| expected_final_state: running | ||
|
|
||
| node2: | ||
| network_node_id: 0 | ||
|
||
| ip_addr: 10.0.0.12 | ||
| processes: | ||
| - path: build/src/executable/qlean | ||
| args: --modules-dir /path/to/qlean-mini/build/src/modules --bootnodes /path/to/qlean-mini/example/1-network/genesis/nodes.yaml --genesis /path/to/qlean-mini/example/1-network/genesis/config.yaml --validator-registry-path /path/to/qlean-mini/example/1-network/genesis/validators.yaml --node-id node_2 --node-key f2f53f6acf312c5e92c2a611bbca7a1932b4db0b9e0c43bec413badca9b76760 --listen-addr /ip4/0.0.0.0/udp/9002/quic-v1 --prometheus_port 9102 | ||
| expected_final_state: running | ||
|
|
||
| node3: | ||
| network_node_id: 0 | ||
|
||
| ip_addr: 10.0.0.13 | ||
| processes: | ||
| - path: build/src/executable/qlean | ||
| args: --modules-dir /path/to/qlean-mini/build/src/modules --bootnodes /path/to/qlean-mini/example/1-network/genesis/nodes.yaml --genesis /path/to/qlean-mini/example/1-network/genesis/config.yaml --validator-registry-path /path/to/qlean-mini/example/1-network/genesis/validators.yaml --node-id node_3 --node-key fa5ddbec80f964d17d28221c2c5bac0f4a3f9cfcf4b86674e605f459e195a1c4 --listen-addr /ip4/0.0.0.0/udp/9003/quic-v1 --prometheus_port 9103 | ||
| expected_final_state: running | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Shell code blocks should use 'bash' instead of 'zsh' for better compatibility. While zsh-specific features like export commands work in bash, using 'bash' as the language identifier is more universally compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense