From 78e36885561326067e240a3611179c887f896ed0 Mon Sep 17 00:00:00 2001 From: Nuke Date: Mon, 8 Jun 2026 16:02:39 -0600 Subject: [PATCH 1/2] oneshot local devnet guide w/ claude --- docs/guides/deploy/local.md | 186 +++++++++++++++++++++++++++++++++ docs/guides/deploy/overview.md | 1 + 2 files changed, 187 insertions(+) create mode 100644 docs/guides/deploy/local.md diff --git a/docs/guides/deploy/local.md b/docs/guides/deploy/local.md new file mode 100644 index 0000000000..bd3bdac704 --- /dev/null +++ b/docs/guides/deploy/local.md @@ -0,0 +1,186 @@ +--- +description: Deploy an Evolve EVM chain locally for development and testing using local-da and Docker Compose. +--- + +# 🏠 Local Development Deployment + +This guide walks you through deploying a complete Evolve EVM chain on your local machine for development and testing. Unlike testnet and mainnet deployments, local dev uses the **local-da** mock DA layer so you have zero external dependencies. + + + + + +## 🏗️ Architecture Overview + +A local Evolve EVM deployment consists of three services running on your machine: + +```mermaid +graph TB + subgraph "Sequencer Stack" + SEQ_RETH[RETH Service
:8545 JSON-RPC
:8551 Engine API] + SEQ_EVOLVE[EVOLVE Service
--aggregator=true] + SEQ_RETH <--> SEQ_EVOLVE + end + + subgraph "Local DA" + LOCAL_DA[local-da
:7980] + end + + SEQ_EVOLVE -->|Post Blobs| LOCAL_DA + + USERS[Dev / Tests] --> SEQ_RETH + + classDef sequencer fill:#e1f5fe + classDef da fill:#fff3e0 + classDef user fill:#e8f5e8 + + class SEQ_RETH,SEQ_EVOLVE sequencer + class LOCAL_DA da + class USERS user +``` + +**Key differences from testnet/mainnet:** + +- `local-da` replaces Celestia — no tokens, no external network +- Single sequencer only — no full nodes required +- All services run on `localhost` + +## 💻 Prerequisites {#prerequisites} + +- [Go](https://golang.org/doc/install) {{ constants.golangVersion }} or later +- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) +- [just](https://github.com/casey/just#installation) (command runner) +- [Git](https://git-scm.com/) + +## 🛠️ Step 1 — Clone and Build {#clone-and-build} + +```bash +git clone --depth 1 --branch {{ constants.evolveLatestTag }} https://github.com/evstack/ev-node.git +cd ev-node + +# Build the EVM sequencer binary and local-da +just build-evm +just build-da +``` + +After building you will have: + +- `build/evm` — the Evolve EVM sequencer +- `build/local-da` — the mock DA node + +## 🌐 Step 2 — Start local-da {#start-local-da} + +Open a terminal and start the local DA node: + +```bash +./build/local-da +``` + +You should see: + +``` +INF NewLocalDA: initialized LocalDA component=da +INF Listening on component=da host=localhost maxBlobSize=1974272 port=7980 +INF server started component=da listening_on=localhost:7980 +``` + +Leave this running in its own terminal tab. + +## ⚡ Step 3 — Start the EVM (RETH) Layer {#start-evm-layer} + +Clone the `ev-reth` repository and start RETH using Docker Compose: + +```bash +git clone --depth 1 https://github.com/evstack/ev-reth.git +cd ev-reth +docker compose up -d +``` + +Note the path to the JWT secret — you will need it in the next step: + +```bash +# Default location after docker compose starts +ls ev-reth/execution/evm/docker/jwttoken/jwt.hex +``` + +## 🚀 Step 4 — Initialize and Start the Sequencer {#start-sequencer} + +Back in the `ev-node` directory, initialize the sequencer: + +```bash +./build/evm init \ + --evnode.node.aggregator=true \ + --evnode.signer.passphrase secret +``` + +Then start it, pointing at local-da and the JWT secret from RETH: + +```bash +./build/evm start \ + --evnode.node.aggregator=true \ + --evnode.signer.passphrase secret \ + --evnode.da.address http://localhost:7980 \ + --evnode.node.block_time 1s \ + --evm.jwt-secret /path/to/ev-reth/execution/evm/docker/jwttoken/jwt.hex +``` + +Replace `/path/to/ev-reth/` with the actual path to your cloned `ev-reth` directory. + +You should see block production logs like: + +``` +INF working in aggregator mode block_time=1000 component=main +INF using pending block component=BlockManager height=1 +INF block marked as DA included blockHash=... blockHeight=1 module=BlockManager +``` + +## ✅ Step 5 — Verify {#verify} + +Query the JSON-RPC endpoint to confirm the chain is producing blocks: + +```bash +curl -s -X POST http://localhost:8545 \ + -H 'Content-Type: application/json' \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' +``` + +The `result` field should increment with each call as new blocks are produced. + +## 🐳 Alternative: Docker Compose (all-in-one) {#docker-compose} + +The [ev-toolbox](https://github.com/evstack/ev-toolbox/tree/main/ev-stacks) project provides a pre-configured Docker Compose stack that wires up RETH, the Evolve EVM sequencer, and local-da for you: + +```bash +git clone https://github.com/evstack/ev-toolbox.git +cd ev-toolbox/ev-stacks/local +docker compose up +``` + +This is the fastest way to get a fully functional local environment without manually coordinating services. + +## ⚙️ Configuration Reference {#configuration} + +| Flag | Default | Description | +|---|---|---| +| `--evnode.node.aggregator` | `false` | Must be `true` for the sequencer | +| `--evnode.signer.passphrase` | — | Passphrase protecting the signing key | +| `--evnode.da.address` | — | DA node endpoint (`http://localhost:7980` for local-da) | +| `--evnode.node.block_time` | `1s` | How often the sequencer produces blocks | +| `--evm.jwt-secret` | — | Path to the JWT secret shared with RETH | +| `--evm.eth-url` | `http://localhost:8545` | RETH JSON-RPC URL | +| `--evm.engine-url` | `http://localhost:8551` | RETH Engine API URL | + +## 🎉 Next Steps {#next-steps} + +Once your local chain is running: + +- [Testnet Deployment](./testnet.md) — deploy with real Celestia DA and a multi-node setup +- [Single Sequencer Guide](../evm/single.md) — detailed sequencer configuration options +- [Local DA Guide](../da/local-da.md) — more details on the `local-da` mock DA node +- [Metrics](../metrics.md) — add Prometheus + Grafana monitoring + +:::warning +This setup is for development only. Do not use `local-da` or a passphrase-protected key in any production environment. +::: diff --git a/docs/guides/deploy/overview.md b/docs/guides/deploy/overview.md index 348b55fdae..4030f8085a 100644 --- a/docs/guides/deploy/overview.md +++ b/docs/guides/deploy/overview.md @@ -38,6 +38,7 @@ When you're ready to test with real network conditions, you can deploy to testne Choose the deployment approach that matches your current needs: +- [🏠 Local Development](./local.md) - Run everything on your machine with local-da (no external dependencies) - [🌐 Testnet Deployment](./testnet.md) - Deploy on testnet with external DA networks :::warning Disclaimer From 76b0bb81efea6da11b88f65e5058fd88c854ae2f Mon Sep 17 00:00:00 2001 From: Nuke Date: Mon, 8 Jun 2026 16:43:34 -0600 Subject: [PATCH 2/2] tested to work with docker, but really upstream tooling needs some tweaks --- docs/guides/deploy/local.md | 198 ++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 100 deletions(-) diff --git a/docs/guides/deploy/local.md b/docs/guides/deploy/local.md index bd3bdac704..2d2212f9fd 100644 --- a/docs/guides/deploy/local.md +++ b/docs/guides/deploy/local.md @@ -1,144 +1,134 @@ --- -description: Deploy an Evolve EVM chain locally for development and testing using local-da and Docker Compose. +description: Deploy an Evolve EVM chain locally for development and testing using ev-toolbox and local-da. --- # 🏠 Local Development Deployment -This guide walks you through deploying a complete Evolve EVM chain on your local machine for development and testing. Unlike testnet and mainnet deployments, local dev uses the **local-da** mock DA layer so you have zero external dependencies. +This guide walks you through deploying a complete Evolve EVM chain on your local machine using [ev-toolbox](https://github.com/evstack/ev-toolbox). It uses the **local-da** mock DA layer so there are no external dependencies or token costs. - - - +## 🏗️ How it works -## 🏗️ Architecture Overview - -A local Evolve EVM deployment consists of three services running on your machine: +The local stack is split into two Docker Compose stacks that share a Docker network (`evstack_shared`): ```mermaid graph TB - subgraph "Sequencer Stack" - SEQ_RETH[RETH Service
:8545 JSON-RPC
:8551 Engine API] - SEQ_EVOLVE[EVOLVE Service
--aggregator=true] - SEQ_RETH <--> SEQ_EVOLVE - end - - subgraph "Local DA" + subgraph "da-local stack" LOCAL_DA[local-da
:7980] end - SEQ_EVOLVE -->|Post Blobs| LOCAL_DA + subgraph "single-sequencer stack" + SEQ_RETH[ev-reth
:8545 JSON-RPC] + SEQ_EVM[ev-node-evm
aggregator mode] + SEQ_RETH <--> SEQ_EVM + end - USERS[Dev / Tests] --> SEQ_RETH + SEQ_EVM -->|Post blobs| LOCAL_DA classDef sequencer fill:#e1f5fe classDef da fill:#fff3e0 - classDef user fill:#e8f5e8 - - class SEQ_RETH,SEQ_EVOLVE sequencer + class SEQ_RETH,SEQ_EVM sequencer class LOCAL_DA da - class USERS user ``` -**Key differences from testnet/mainnet:** - -- `local-da` replaces Celestia — no tokens, no external network -- Single sequencer only — no full nodes required -- All services run on `localhost` +The `da-local` stack is started first because it creates the shared Docker network that the sequencer stack joins. ## 💻 Prerequisites {#prerequisites} -- [Go](https://golang.org/doc/install) {{ constants.golangVersion }} or later -- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) -- [just](https://github.com/casey/just#installation) (command runner) +- [Docker](https://docs.docker.com/get-docker/) 20.10 or later +- [Docker Compose](https://docs.docker.com/compose/install/) v2 or later - [Git](https://git-scm.com/) -## 🛠️ Step 1 — Clone and Build {#clone-and-build} +## 🛠️ Step 1 — Clone ev-toolbox {#clone} ```bash -git clone --depth 1 --branch {{ constants.evolveLatestTag }} https://github.com/evstack/ev-node.git -cd ev-node - -# Build the EVM sequencer binary and local-da -just build-evm -just build-da +git clone --depth 1 https://github.com/evstack/ev-toolbox.git +cd ev-toolbox/ev-stacks/stacks ``` -After building you will have: +## 🌐 Step 2 — Start local-da {#start-local-da} -- `build/evm` — the Evolve EVM sequencer -- `build/local-da` — the mock DA node +The `da-local` stack must be started first. It creates the `evstack_shared` Docker network that the sequencer stack joins. -## 🌐 Step 2 — Start local-da {#start-local-da} +```bash +cd da-local +docker compose up -d +``` -Open a terminal and start the local DA node: +Verify it is running: ```bash -./build/local-da +docker logs local-da ``` -You should see: +Expected output: ``` INF NewLocalDA: initialized LocalDA component=da -INF Listening on component=da host=localhost maxBlobSize=1974272 port=7980 -INF server started component=da listening_on=localhost:7980 +INF Listening on component=da host=0.0.0.0 maxBlobSize=1970176 port=7980 +INF server started component=da listening_on=0.0.0.0:7980 ``` -Leave this running in its own terminal tab. +## 🔑 Step 3 — Create the passphrase file {#passphrase} -## ⚡ Step 3 — Start the EVM (RETH) Layer {#start-evm-layer} - -Clone the `ev-reth` repository and start RETH using Docker Compose: +The sequencer signs blocks with a key protected by a passphrase. Create the passphrase file in the single-sequencer directory: ```bash -git clone --depth 1 https://github.com/evstack/ev-reth.git -cd ev-reth -docker compose up -d +cd ../single-sequencer +echo -n "devpassword" > passphrase ``` -Note the path to the JWT secret — you will need it in the next step: - -```bash -# Default location after docker compose starts -ls ev-reth/execution/evm/docker/jwttoken/jwt.hex -``` +:::tip +For local development, any string works as a passphrase. Keep it simple — you will not need it again unless you restart with a wiped volume. +::: -## 🚀 Step 4 — Initialize and Start the Sequencer {#start-sequencer} +## 🚀 Step 4 — Start the sequencer {#start-sequencer} -Back in the `ev-node` directory, initialize the sequencer: +Make the entrypoint script executable (required after `git clone` on some systems), then start the stack using the local-DA variant of the compose file: ```bash -./build/evm init \ - --evnode.node.aggregator=true \ - --evnode.signer.passphrase secret +chmod +x entrypoint.sequencer.sh +docker compose -f docker-compose.da.local.yml up -d ``` -Then start it, pointing at local-da and the JWT secret from RETH: +Monitor startup: ```bash -./build/evm start \ - --evnode.node.aggregator=true \ - --evnode.signer.passphrase secret \ - --evnode.da.address http://localhost:7980 \ - --evnode.node.block_time 1s \ - --evm.jwt-secret /path/to/ev-reth/execution/evm/docker/jwttoken/jwt.hex +docker compose -f docker-compose.da.local.yml logs -f ``` -Replace `/path/to/ev-reth/` with the actual path to your cloned `ev-reth` directory. - -You should see block production logs like: +A healthy startup looks like: ``` -INF working in aggregator mode block_time=1000 component=main -INF using pending block component=BlockManager height=1 -INF block marked as DA included blockHash=... blockHeight=1 module=BlockManager +single-sequencer | 🚀 INIT: Starting EVM Sequencer initialization +single-sequencer | ✅ SUCCESS: Sequencer initialization completed +single-sequencer | ✅ SUCCESS: Exported genesis.json to /volumes/sequencer_export/genesis.json +single-sequencer | ✅ SUCCESS: Successfully retrieved genesis hash: 0x6aec2... +single-sequencer | 🚀 INIT: Starting EVM sequencer with command: evm start ... +single-sequencer | INF Starting aggregator node component=main +single-sequencer | INF produced block component=executor height=1 +single-sequencer | INF produced block component=executor height=2 ``` +:::info DA submission errors +You may see errors like `DA layer submission failed: method 'blob.Submit' not found`. This is a known version mismatch between the current local-da Docker images and ev-node-evm. It is **non-fatal** — blocks are produced and the JSON-RPC is fully functional for local development. You can ignore these errors. +::: + ## ✅ Step 5 — Verify {#verify} -Query the JSON-RPC endpoint to confirm the chain is producing blocks: +The sequencer JSON-RPC port (`8545`) is not exposed to the host by default. To expose it for local testing, create an override file: + +```bash +cat > docker-compose.override.yml << 'EOF' +services: + ev-reth-sequencer: + ports: + - "8545:8545" +EOF + +docker compose -f docker-compose.da.local.yml -f docker-compose.override.yml up -d +``` + +Then query the chain: ```bash curl -s -X POST http://localhost:8545 \ @@ -146,41 +136,49 @@ curl -s -X POST http://localhost:8545 \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' ``` -The `result` field should increment with each call as new blocks are produced. - -## 🐳 Alternative: Docker Compose (all-in-one) {#docker-compose} +The `result` field (a hex block number) should increment with each call as new blocks are produced. -The [ev-toolbox](https://github.com/evstack/ev-toolbox/tree/main/ev-stacks) project provides a pre-configured Docker Compose stack that wires up RETH, the Evolve EVM sequencer, and local-da for you: +## 🔍 Useful commands {#commands} ```bash -git clone https://github.com/evstack/ev-toolbox.git -cd ev-toolbox/ev-stacks/local -docker compose up +# Check container status +docker ps + +# Follow all sequencer logs +docker compose -f docker-compose.da.local.yml logs -f + +# Follow just the ev-node logs (block production) +docker logs -f single-sequencer + +# Follow just the reth logs +docker logs -f ev-reth-sequencer + +# Stop everything +docker compose -f docker-compose.da.local.yml down +cd ../da-local && docker compose down ``` -This is the fastest way to get a fully functional local environment without manually coordinating services. +## ⚙️ Configuration {#configuration} + +All configuration is via environment variables in `.env` and the `docker-compose.da.local.yml` file. -## ⚙️ Configuration Reference {#configuration} +| Variable | Default | Description | +| ----------------------------------- | ------- | -------------------------------------------------------- | +| `SEQUENCER_EV_RETH_PROMETHEUS_PORT` | `9000` | Host port for ev-reth Prometheus metrics | +| `SEQUENCER_EV_NODE_PROMETHEUS_PORT` | `26660` | Host port for ev-node Prometheus metrics | +| `DA_SIGNING_ADDRESSES` | (empty) | DA signing addresses — leave empty for local-da | +| `EVM_BLOCK_TIME` | `500ms` | How often the sequencer produces blocks (set in compose) | -| Flag | Default | Description | -|---|---|---| -| `--evnode.node.aggregator` | `false` | Must be `true` for the sequencer | -| `--evnode.signer.passphrase` | — | Passphrase protecting the signing key | -| `--evnode.da.address` | — | DA node endpoint (`http://localhost:7980` for local-da) | -| `--evnode.node.block_time` | `1s` | How often the sequencer produces blocks | -| `--evm.jwt-secret` | — | Path to the JWT secret shared with RETH | -| `--evm.eth-url` | `http://localhost:8545` | RETH JSON-RPC URL | -| `--evm.engine-url` | `http://localhost:8551` | RETH Engine API URL | +To change the block time or other settings, edit `docker-compose.da.local.yml` directly or add them to your `docker-compose.override.yml`. ## 🎉 Next Steps {#next-steps} Once your local chain is running: - [Testnet Deployment](./testnet.md) — deploy with real Celestia DA and a multi-node setup -- [Single Sequencer Guide](../evm/single.md) — detailed sequencer configuration options -- [Local DA Guide](../da/local-da.md) — more details on the `local-da` mock DA node +- [Local DA Guide](../da/local-da.md) — more about the `local-da` mock DA node - [Metrics](../metrics.md) — add Prometheus + Grafana monitoring :::warning -This setup is for development only. Do not use `local-da` or a passphrase-protected key in any production environment. +This setup is for development only. The `local-da` mock does not provide real data availability guarantees. Do not use it for any production environment. :::