# Espresso

Espresso is a high-performance base layer for rollups, making L2 transactions safe, fast, and seamless for users. Espresso is trusted by leading teams including Oﬀchain Labs (Arbitrum), Polygon, ApeChain, Cartesi, RARI Chain, Celo.

L2s and rollups that use Espresso as a decentralized base layer benefit from industry-leading speed in finalizing transactions. The confirmations that Espresso provides underpin cross-chain applications that can tap into liquidity and users of all connected Espresso-chains.\
\
Resources

<table><thead><tr><th>Website</th><th data-type="content-ref">https://www.espressosys.com/</th></tr></thead><tbody><tr><td>Github</td><td><a href="https://github.com/EspressoSystems">https://github.com/EspressoSystems</a></td></tr><tr><td>Explorer</td><td><a href="https://explorer.decaf.testnet.espresso.network/nodes">https://explorer.decaf.testnet.espresso.network/nodes</a></td></tr><tr><td>Docs</td><td><a href="https://docs.espressosys.com/network">https://docs.espressosys.com/network</a></td></tr><tr><td>Discord</td><td><a href="https://discord.com/invite/YHZPk5dbcq">https://discord.com/invite/YHZPk5dbcq</a></td></tr></tbody></table>

## Hardware requirements

<table data-view="cards"><thead><tr><th>CPU</th><th>RAM</th><th>Storage</th><th>Network</th><th>OS</th></tr></thead><tbody><tr><td>4 cores</td><td>16 GB</td><td>1 TGB NVME</td><td>25 MBit/s</td><td>Linux (Ubuntu 22.04 x64)</td></tr></tbody></table>

## Installation 💾

## Update repositories

```bash
apt update && apt upgrade -y
```

## Install dependencies

```bash
sudo apt install -y curl jq ca-certificates gnupg lsb-release openssl
```

Install Docker

```bash
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker
```

Create folders

```bash
mkdir -p $HOME/Espresso-test
cd ~/Espresso-test
mkdir -p sepolia/geth sepolia/lighthouse sepolia/jwt keys espresso-store
```

Create `.env` for your node identity + public IP

```bash
nano ~/Espresso-test/.env

PUBLIC_IP=YOUR_PUBLIC_IP
NODE_NAME=your-espresso-validator-01
COMPANY_NAME=YourCompany
COMPANY_WEBSITE=https://example.com
NETWORK_TYPE=Hosted
COUNTRY_CODE=US

SEPOLIA_CHECKPOINT_URL=https://beaconstate-sepolia.chainsafe.io
```

## Create `docker-compose.yml` (Sepolia EL+CL + Espresso Decaf)

```bash
nano ~/Espresso-test/docker-compose.yml
```

```bash
services:
  geth-sepolia:
    image: ethereum/client-go:stable
    restart: unless-stopped
    command: >
      --sepolia
      --datadir=/data
      --syncmode=snap
      --http --http.addr=0.0.0.0 --http.port=8545 --http.vhosts=* --http.corsdomain=*
      --http.api=eth,net,web3,txpool
      --ws --ws.addr=0.0.0.0 --ws.port=8546 --ws.origins=*
      --ws.api=eth,net,web3,txpool
      --authrpc.addr=0.0.0.0 --authrpc.port=8551 --authrpc.vhosts=* --authrpc.jwtsecret=/jwt/jwt.hex
      --port=30303
      --nat=any
    volumes:
      - ./sepolia/geth:/data
      - ./sepolia/jwt:/jwt
    ports:
      - "18545:8545/tcp"
      - "18546:8546/tcp"
      - "18551:8551/tcp"
      - "40303:30303/tcp"
      - "40303:30303/udp"

  lighthouse-sepolia:
    image: sigp/lighthouse:v8.0.0
    restart: unless-stopped
    depends_on:
      - geth-sepolia
    command: >
      lighthouse beacon_node
      --network sepolia
      --datadir /data
      --execution-endpoint http://geth-sepolia:8551
      --execution-jwt /jwt/jwt.hex
      --checkpoint-sync-url ${SEPOLIA_CHECKPOINT_URL}
      --checkpoint-sync-url-timeout 300
      --http --http-address 0.0.0.0 --http-port 5052
      --metrics --metrics-address 0.0.0.0 --metrics-port 5054
      --port 9000
      --discovery-port 9000
    volumes:
      - ./sepolia/lighthouse:/data
      - ./sepolia/jwt:/jwt:ro
    ports:
      - "15052:5052/tcp"
      - "15054:5054/tcp"
      - "49000:9000/tcp"
      - "49000:9000/udp"

  espresso-decaf:
    image: ghcr.io/espressosystems/espresso-sequencer/sequencer:20251120
    restart: unless-stopped
    depends_on:
      - geth-sepolia
      - lighthouse-sepolia
    environment:
      ESPRESSO_SEQUENCER_API_PORT: "8080"
      ESPRESSO_SEQUENCER_GENESIS_FILE: "/genesis/decaf.toml"
      ESPRESSO_SEQUENCER_KEY_FILE: "/mount/sequencer/keys/0.env"
      ESPRESSO_SEQUENCER_STORAGE_PATH: "/mount/sequencer/store"

      ESPRESSO_SEQUENCER_CONFIG_PEERS: "https://cache.decaf.testnet.espresso.network"
      ESPRESSO_SEQUENCER_ORCHESTRATOR_URL: "https://orchestrator-UZAFTUIMZOT.decaf.testnet.espresso.network/"
      ESPRESSO_SEQUENCER_CDN_ENDPOINT: "cdn.decaf.testnet.espresso.network:1737"
      ESPRESSO_STATE_RELAY_SERVER_URL: "https://state-relay.decaf.testnet.espresso.network"
      ESPRESSO_SEQUENCER_STATE_PEERS: "https://query.decaf.testnet.espresso.network"

      ESPRESSO_SEQUENCER_L1_PROVIDER: "http://geth-sepolia:8545"
      ESPRESSO_SEQUENCER_L1_WS_PROVIDER: "ws://geth-sepolia:8546"

      ESPRESSO_SEQUENCER_LIBP2P_BIND_ADDRESS: "0.0.0.0:9000"
      ESPRESSO_SEQUENCER_LIBP2P_ADVERTISE_ADDRESS: "${PUBLIC_IP}:19000"

      ESPRESSO_SEQUENCER_IDENTITY_NODE_NAME: "${NODE_NAME}"
      ESPRESSO_SEQUENCER_IDENTITY_COMPANY_NAME: "${COMPANY_NAME}"
      ESPRESSO_SEQUENCER_IDENTITY_COMPANY_WEBSITE: "${COMPANY_WEBSITE}"
      ESPRESSO_SEQUENCER_IDENTITY_NETWORK_TYPE: "${NETWORK_TYPE}"
      ESPRESSO_SEQUENCER_IDENTITY_COUNTRY_CODE: "${COUNTRY_CODE}"

      RUST_LOG: "warn,hotshot_libp2p_networking=off"
      RUST_LOG_FORMAT: "json"
    volumes:
      - ./keys:/mount/sequencer/keys
      - ./espresso-store:/mount/sequencer/store
    ports:
      - "18080:8080/tcp"
      - "19000:9000/tcp"
      - "19000:9000/udp"

```

start

```bash
cd ~/Espresso-test/ && docker compose up -d

docker compose ps
```

## Become Validator

#### You may need approval / tokens from Espresso

Decaf docs note node operation is limited to a select group and provide a form to request tokens.

#### Register your validator on Sepolia (staking-cli)

Decaf registration uses `staking-cli register-validator` and requires:

* your **validator Ethereum address** (the address you register)
* a **commission** value (decimal between 0 and 1)
* Sepolia RPC URL (your own is `http://127.0.0.1:18545`)

Decaf contract addresses from docs (set these exactly as environment variables when using staking-cli):

```bash
export STAKING_CONTRACT_ADDRESS=0x40304fbe94d5e7d1492dd90c53a2d63e8506a037
export ESP_TOKEN_CONTRACT_ADDRESS=0x4d4a35a5c843461cdf5f889045d69c59dd18be18
```

Example:

```bash
staking-cli register-validator \
  --validator-address 0xYOUR_VALIDATOR_ADDRESS \
  --commission 0.05 \
  --rpc-url http://127.0.0.1:18545
```

If you got `--commission ... empty`: it usually means your shell variable was empty (e.g. `--commission $COMMISSION` but COMMISSION wasn’t set). Use a literal number like `0.05`.

#### Delegation (required to actually participate)

Decaf uses a **dynamic active set (top 100 by delegation)** and you need ESP tokens delegated to your validator to be active.

Example:

```bash
staking-cli delegate \
  --validator-address 0xYOUR_VALIDATOR_ADDRESS \
  --amount YOUR_AMOUNT_IN_ESP \
  --rpc-url http://127.0.0.1:18545
```

**Validator address clarification:** it’s the address you used in `register-validator` (and that will receive commission/rewards), not “whatever address has Sepolia ETH”. Sepolia ETH is just gas to send the registration/delegation transactions.

## Cheat sheet (status, logs, quick health checks)

### Logs (use your container names)

```bash
docker logs --tail=100 espresso-test-geth-sepolia-1
docker logs --tail=100 espresso-test-lighthouse-sepolia-1
docker logs --tail=100 espresso-test-espresso-decaf-1
```

Follow live:

```bash
docker logs -f espresso-test-espresso-decaf-1
```

### Sepolia EL sync (geth)

```bash
curl -s -X POST http://127.0.0.1:18545 \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_syncing","params":[]}' | jq
```

### Sepolia CL health (lighthouse HTTP API)

```bash
curl -sS -i http://127.0.0.1:15052/eth/v1/node/health
```

### Espresso metrics (best single check)

```bash
curl -sSL http://127.0.0.1:18080/v1/status/metrics \
 | egrep -i 'consensus_libp2p_num_connected_peers|consensus_libp2p_is_ready|consensus_current_view|consensus_last_decided_view' \
 | head -50
```

Interpretation (rule of thumb):

* `consensus_libp2p_is_ready 1`
* `consensus_libp2p_num_connected_peers` > 0 (ideally dozens)
* `consensus_current_view` keeps increasing
* `consensus_last_decided_view` stays close to `current_view`

### Restart only Espresso (safe)

```bash
docker compose restart espresso-decaf
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cryptomolot.gitbook.io/cryptomolot-docs/testnets/espresso-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
