# How to setup local, multi-client testnets using Kurtosis Co-ordinating releases between clients can be hard to orchestrate, especially when testing new features that have no devnet. Kurtosis is a tool that allows us to create testing environments using just a few commands. We can additionally setup various scenario's and write tests for them using the kurtosis module. This guide explores the use of kurtosis to help setup a local dev environment. Link to Kurtosis docs: [here](https://docs.kurtosis.com/) The doc below has a TLDR section for testing your feature, a verkle section and a mev section. All the steps are exactly the same in every scenario, just the config file changes. ## TLDR: - 1. Ensure Docker is installed locally - 2. Dowload kurtosis with the instructions provided [here](https://docs.kurtosis.com/install/#ii-install-the-cli) - 3. Save the below JSON in a file called `example.json` ```jsonld= { "participants": [ { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:dencun-devnet-8-946a2da", "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:deneb-modern", "count": 3 } ], "network_params": { "capella_fork_epoch": 2, "deneb_fork_epoch": 3 }, "launch_additional_services": false, "wait_for_finalization": false, "wait_for_verifications": false, "global_client_log_level": "info", "snooper_enabled": true } ``` - 4. Start the module with the following command: ```shell kurtosis run --enclave ethTestnet github.com/kurtosis-tech/ethereum-package "$(cat ./example.json)" ``` - 5. Testnet will start in the background. You can use the following commands to get more information: ``` kurtosis enclave inspect ethTestnet kurtosis service logs ethTestnet <nane> -f ``` ## Config Explanation: Kurtosis has built a module for the devnets. The module can be seen [here](https://github.com/kurtosis-tech/ethereum-package). It's written in starlark and the core "genesis" tooling is its own package [here](https://github.com/kurtosis-tech/eth-network-package). The module takes in parameters and starts a testnet accordingly. We can specify the client combinations, number of clients, fork epoch and so on. Naturally the larger the number of clients, the more CPU/RAM is needed. Most systems should be able to handle a 3-4 node setup locally. For more elaborate setups, please use a cloud instance or get a fast computer to run it. We will just assume a 3 node setup for this example. Let node 1 be the EL:CL combination you wish to test(feature branch for example). node 2 and node 3 can be tested, stable clients(lighthouse-geth and nimbus-nethermind for example). Since our node 1 is used for testing new features or cli flags, we can specify them under `elExtraParams`,`beaconExtraParams` or `validatorExtraParams` as needed. Kurtosis works on the basis of docker images, so your feature branch would need to have a docker image built. The below config describes what that looks like in JSON: ```jsonld= { "participants": [ { "elType": "<your-EL-client>", "elImage": "<your-EL-docker-image", "elLogLevel": "<log-level-you-want>", "elExtraParams": [<EL-extra-params-if-needed>], "clType": "<your-CL-client>", "clImage": "<your-CL-docker-image", "beaconExtraParams": [<beacon-extra-params-if-needed>], "validatorExtraParams": [<val-extra-params-if-needed>], }, { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:dencun-devnet-8-946a2da", "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:deneb-modern" }, { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:dencun-devnet-8-946a2da", "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:deneb-modern" } ], "network": { "networkId": "3151908", "depositContractAddress": "0x4242424242424242424242424242424242424242", "secondsPerSlot": 12, "slotsPerEpoch": 32, "capella_fork_epoch": 2, "deneb_fork_epoch": 5, "numValidatorKeysPerNode": 64, "preregisteredValidatorKeysMnemonic": "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete" }, "waitForMining": true, "waitForFinalization": true, "logLevel": "info" } ``` ## Verbose Steps: 1. Dowload kurtosis with the instructions provided [here](https://docs.kurtosis.com/install/#ii-install-the-cli) 2. Ensure `docker` is installed and your user can execute docker commands (i.e, run `docker ps -a`) 3. Copy the JSON file shown above and place it in a file locally accessible, make the required changes to the JSON config. You'd probably want to reduce the number of clients you're running if you're on a laptop. 4. Start the module with the following command: ```shell kurtosis run --enclave ethTestnet github.com/kurtosis-tech/ethereum-package "$(cat ./example.json)" ``` 4. Check the logs for the URL to `forkmon`, alternatively check the module logs 5. You can use the kurtosis module to fetch logs, e.g: ```shell kurtosis enclave inspect ethTestnet kurtosis service logs ethTestnet <enter-GUID-of-service-from-previous-step> ``` 6. If you need shell access, you can achieve that with: ```shell kurtosis service shell ethTestnet <enter-GUID-of-service-from-previous-step> ``` 7. When done, run `kurtosis enclave rm -f ethTestnet` to delete the testnet ### Verkle config example: ```jsonld= { "participants": [ { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:<VERKLE_IMAGE>", "elExtraParams": ["--override.verkle=<UNIXTIMESTAMP>"], "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:latest" }, { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:<VERKLE_IMAGE>", "elExtraParams": ["--override.verkle=<UNIXTIMESTAMP>"], "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:latest" }, { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:<VERKLE_IMAGE>", "elExtraParams": ["--override.verkle=<UNIXTIMESTAMP>"], "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:latest" } ], "network_params": { "capella_fork_epoch": 2, "deneb_fork_epoch": 5 }, "launch_additional_services": false, "wait_for_finalization": false, "wait_for_verifications": false, "global_client_log_level": "info" } ``` ### mock-mev example Useful for testing `mev-boost` and the client implimentations without adding the complexity of the relay. This can be enabled by a single config command and would deploy the [mock-builder](https://github.com/marioevz/mock-builder) from Mario instead of the relay infrastructure. ```jsonld= { "participants": [ { "el_client_type": "geth", "el_client_image": "ethpandaops/geth:dencun-devnet-8-946a2da", "cl_client_type": "lighthouse", "cl_client_image": "sigp/lighthouse:deneb-modern", "count": 3 } ], "network_params": { "capella_fork_epoch": 2, "deneb_fork_epoch": 4 }, "launch_additional_services": true, "global_client_log_level": "debug", "snooper_enabled": true, "mev_type": "mock" } ``` ### Debugging - To grab the genesis files, you can run: ``` kurtosis files download <enclave name> <service name> <path to copy to> ``` e.g. to get the EL genesis data: ``` kurtosis files download ethTestnet el-genesis-data ~/Downloads ```