> For the complete documentation index, see [llms.txt](https://docs.ethgas.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ethgas.com/get-started/validators-node-operators.md).

# Validators / Node Operators

Validators play a critical role in supporting realtime execution. ETHGas is designed to unambiguously earn more than MEV-Boost alone, with both minimal risk and minimal technical integration required.&#x20;

## Quick Start Guide

{% stepper %}
{% step %}

### Set up Commit-Boost

{% endstep %}

{% step %}

### Register validators to ETHGas

{% endstep %}

{% step %}

### Earn higher rewards

That's it, you're earning higher rewards! You can sit back and relax 🏖️
{% endstep %}
{% endstepper %}

{% hint style="info" %}
This guide is a simplified quick start configuration that assumes a standard validator setup. For a full technical guide with every available configuration option, check out the [repo README](https://github.com/ethgas-developer/ethgas-preconf-commit-boost-module).
{% endhint %}

### Commit-Boost

Commit-Boost is a direct replacement for MEV-Boost and performs the same function, with the ability to add additional functionality.

Commit-Boost is a sidecar for proposers to create commitments. Validators need to run Commit-Boost, which uses a validator's BLS key to sign messages signaling their intent to register on ETHGas exchange platform and delegate to more sophisticated parties (e.g. our Pricer server) to sell preconfs.

Link: <https://github.com/ethgas-developer/ethgas-preconf-commit-boost-module>

<figure><img src="https://1913553586-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBk99eVkZsNrI6feXAyYs%2Fuploads%2F5Fv5HWbxGOMqDkzzNupa%2Fcommit%20boost.jpg?alt=media&amp;token=e01a7785-7f1a-4b92-9ac4-4bae413e6f0d" alt=""><figcaption><p>Different commit boost components</p></figcaption></figure>

The `ethgas-preconf-commit-boost-module` repo contains everything needed to setup and run Commit-Boost as well as the ETHGas module. If you are already running an existing version of Commit-Boost, you can either:

1. Use this single repo instead for simpler configuration management.
2. Or, continue using your existing version, making sure to add the configuration, `rpc_url`, ETHGas `[[relays]]`, etc.&#x20;

To get started, clone the repo:

```bash
git clone https://github.com/ethgas-developer/ethgas-preconf-commit-boost-module.git
```

Copy `docker-compose-example.yml` as `docker-compose.yml` and make any required modifications.

```bash
cp docker-compose-example.yml docker-compose.yml
```

Create an empty `.cb.env` file and generate a new jwt for the signer module by running:

```bash
touch .cb.env
docker compose -f docker-compose.yml up cb_gen_jwt
```

Create a `config.toml` file and enter the following configuration:

```bash
touch config.toml
```

{% hint style="info" %}
This is a minimal setup and does not cover all environment types. For a comprehensive list of all available configuration options, open the `config.example.mainnet.toml` file.&#x20;
{% endhint %}

{% tabs %}
{% tab title="Mainnet" %}
{% code title="config.toml" overflow="wrap" lineNumbers="true" %}

```toml
chain = "Mainnet"

[pbs]
# Must be set to true to allow signers to work with PBS module.
with_signer = true

# Port to receive BuilderAPI calls from beacon node
# NOTE: This is the same as the default mev-boost port,
#       since this PBS module replaces the default mev-boost client 
port = 18550

# The PBS module needs one or more [[relays]] as defined below.
# The configuration options enable_timing_games, target_first_request_ms and frequency_get_header_ms are set as recommended defaults. If those default settings are not included, it may lead to reduced validator performance.
[[relays]]
id = "ethgas"
url = "https://0x88ef3061f598101ca713d556cf757763d9be93d33c3092d3ab6334a36855b6b4a4020528dd533a62d25ea6648251e62e@relay.ethgas.com"
enable_timing_games = true
target_first_request_ms = 0
frequency_get_header_ms = 100

[[relays]]
id = "ethgas-us"
url = "https://0x88ef3061f598101ca713d556cf757763d9be93d33c3092d3ab6334a36855b6b4a4020528dd533a62d25ea6648251e62e@us-relay.ethgas.com"
enable_timing_games = true
target_first_request_ms = 0
frequency_get_header_ms = 100

[[relays]]
id = "ethgas-eu"
url = "https://0x88ef3061f598101ca713d556cf757763d9be93d33c3092d3ab6334a36855b6b4a4020528dd533a62d25ea6648251e62e@eu-relay.ethgas.com"
enable_timing_games = true
target_first_request_ms = 0
frequency_get_header_ms = 100

[[relays]]
id = "ethgas-ap"
url = "https://0x88ef3061f598101ca713d556cf757763d9be93d33c3092d3ab6334a36855b6b4a4020528dd533a62d25ea6648251e62e@ap-relay.ethgas.com"
enable_timing_games = true
target_first_request_ms = 0
frequency_get_header_ms = 100

[signer]
port = 20000
```

{% endcode %}
{% endtab %}

{% tab title="Hoodi" %}
{% code title="config.toml" overflow="wrap" lineNumbers="true" %}

```toml
chain = "Hoodi"

[pbs]
# Must be set to true to allow signers to work with PBS module.
with_signer = true

# Port to receive BuilderAPI calls from beacon node
# NOTE: This is the same as the default mev-boost port,
#       since this PBS module replaces the default mev-boost client 
port = 18550

# Execution Layer RPC url to use for extra validation
# REQUIRED. Can be set to any accessible RPC.
rpc_url = "https://ethereum-hoodi-rpc.publicnode.com"

# The PBS module needs one or more [[relays]] as defined below.
# The configuration options enable_timing_games, target_first_request_ms and frequency_get_header_ms are set as recommended defaults. If those default settings are not included, it may lead to reduced validator performance.
[[relays]]
id = "ethgas"
url = "https://0xb20c3fe59db9c3655088839ef3d972878d182eb745afd8abb1dd2abf6c14f93cd5934ed4446a5fe1ba039e2bc0cf1011@hoodi-relay.ethgas.com"
enable_timing_games = true
target_first_request_ms = 0
frequency_get_header_ms = 100

[signer]
docker_image = "ghcr.io/commit-boost/signer:latest"
port = 20000
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Signers

This section continues the configuration of the `config.toml` file for the signer modules. Select the signer that you are using add the configuration below the `[signer]` section in your `config.toml` file

#### Local Signers (link to CB docs)

<details>

<summary>Lighthouse</summary>

**File structure:**

```
├── keys
│   ├── <PUBLIC_KEY_1>
│   │   └── voting-keystore.json
│   └── <PUBLIC_KEY_2>
│       └── voting-keystore.json
└── secrets
    ├── <PUBLIC_KEY_1>
    └── <PUBLIC_KEY_2>
```

**Config:**

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.local.loader]
format = "lighthouse"
keys_path = "keys"
secrets_path = "secrets"
```

{% endcode %}

</details>

<details>

<summary>Prysm</summary>

**File structure:**

```
├── wallet
│   └── direct
│       └── accounts
│           └──all-accounts.keystore.json
└── secrets
    └── password.txt
```

**Config:**

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.local.loader]
format = "prysm"
keys_path = "wallet/direct/accounts/all-accounts.keystore.json"
secrets_path = "secrets/password.txt"
```

{% endcode %}

</details>

<details>

<summary>Teku</summary>

**File structure:**

```
├── keys
│   ├── <PUBLIC_KEY_1>.json
│   └── <PUBLIC_KEY_2>.json
└── secrets
    ├── <PUBLIC_KEY_1>.txt
    └── <PUBLIC_KEY_2>.txt
```

**Config:**

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.local.loader]
format = "teku"
keys_path = "keys"
secrets_path = "secrets"
```

{% endcode %}

</details>

<details>

<summary>Lodestar</summary>

**File structure:**

```
├── keys
│   ├── <PUBLIC_KEY_1>.json
│   └── <PUBLIC_KEY_2>.json
└── secrets
    └── password.txt
```

**Config:**

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.local.loader]
format = "lodestar"
keys_path = "keys"
secrets_path = "secrets/password.txt"
```

{% endcode %}

{% hint style="info" %}
All keys have the same password stored in `secrets/password.txt`
{% endhint %}

</details>

<details>

<summary>Nimbus</summary>

**File structure:**

```
├── keys
│   ├── <PUBLIC_KEY_1>
│   │   └── keystore.json
│   └── <PUBLIC_KEY_2>
│       └── keystore.json
└── secrets
    ├── <PUBLIC_KEY_1>
    └── <PUBLIC_KEY_2>
```

**Config:**

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.local.loader]
format = "nimbus"
keys_path = "keys"
secrets_path = "secrets"
```

{% endcode %}

</details>

#### Remote Signers

<details>

<summary>Web3Signer</summary>

Web3Signer implements the same API as Commit-Boost, so there's no need to set up a Signer module. The parameters needed for the remote signer are:

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.remote]
# URL of the Web3Signer instance
url = "https://remote.signer.url"
```

{% endcode %}

</details>

<details>

<summary>Dirk</summary>

Dirk is a distributed key management system that can be used to sign transactions. In this case the Signer module is needed as an intermediary between the modules and Dirk. The following parameters are needed:

{% code title="config.toml" lineNumbers="true" %}

```toml
[signer.dirk]
# Path to the client certificate to authenticate with Dirk
cert_path = "/path/to/client.crt"
# Path to the client key
key_path = "/path/to/client.key"
# Path to the secrets directory where the accounts passwords are stored
secrets_path = "/path/to/secrets"
# Path to the CA certificate that signed the Dirk server certificate
# OPTIONAL
ca_cert_path = "/path/to/ca.crt"

# Add one entry like this for each Dirk host
[[signer.dirk.hosts]]
# Domain name of the server to use in TLS verification, if different from the URL
# OPTIONAL
server_name = "localhost-1"
# Complete URL of a Dirk gateway
url = "https://localhost:8881"
# Wallets to load consensus keys from
accounts = ["Wallet1", "DistributedWallet"]

[[signer.dirk.hosts]]
server_name = "localhost-2"
url = "https://localhost:8882"
accounts = ["Wallet2", "DistributedWallet"]
```

{% endcode %}

* `cert_path` and `key_path` are the paths to the client certificate and key used to authenticate with Dirk.
* `wallets` is a list of wallets from which the Signer module will load all accounts as consensus keys. Generated proxy keys will have format `<WALLET_NAME>/<ACCOUNT>/<MODULE_ID>/<UUID>`, so accounts found with that pattern will be ignored.
* `secrets_path` is the path to the folder containing the passwords of the generated proxy accounts, which will be stored in `<secrets_path>/<WALLET_NAME>/<ACCOUNT>/<MODULE_ID>/<UUID>.pass`.

{% code title="config.mainnet.toml" lineNumbers="true" %}

```toml
# Configuration for how the Signer module should store proxy delegations.
# OPTIONAL
[signer.dirk.store]
proxy_dir = "/path/to/proxies"
```

{% endcode %}

Delegation signatures will be stored in files with the format `<proxy_dir>/delegations/<MODULE_ID>/<PROXY_KEY>.sig`.

A full example of a config file with Dirk can be found [here](https://github.com/Commit-Boost/commit-boost-client/blob/main/examples/configs/dirk_signer.toml).

</details>

### ETHGas Module

The ETHGas module is run each time you want to update your ETHGas account configuration. This includes actions like:

* Registering and deregistering validators.
* Updating your entity name, etc.

{% tabs %}
{% tab title="Mainnet" %}
{% code title="config.toml" lineNumbers="true" %}

```toml
[[modules]]
id = "ETHGAS_COMMIT"
type = "commit"
env_file = ".cb.env"

# Default Settings
docker_image = "ghcr.io/ethgas-developer/commitboost_ethgas_commit:latest"
exchange_api_base = "https://mainnet.app.ethgas.com"

# Custom Settings
entity_name = "..." # my_amazing_team
enable_registration = true # false deregisters all, true registers all
registration_mode = "standard" # standard, standard-mux, ssv, obol, skipped
enable_ofac = true

# Specify either eoa_signing_key or access_jwt & refresh_jwt depending on is_jwt_provided boolean value
# Alternatively, you can set EOA_SIGNING_KEY or ACCESS_JWT & REFRESH_JWT in .cb.env as env variables

# This EOA is just your ETHGas account private key, it can be a clean, new address, not related to your validator
eoa_signing_key = "0x..." # for registration in exchange, required if is_jwt_provided = false

is_jwt_provided = false
access_jwt = "xxx.xxx.xxx" # required if is_jwt_provided = true
refresh_jwt = "xxx.xxx.xxx" # required if is_jwt_provided = true
```

{% endcode %}
{% endtab %}

{% tab title="Hoodi" %}
{% code title="config.toml" lineNumbers="true" %}

```toml
[[modules]]
id = "ETHGAS_COMMIT"
type = "commit"
env_file = ".cb.env"

# Default Settings
docker_image = "ghcr.io/ethgas-developer/commitboost_ethgas_commit:latest"
exchange_api_base = "https://hoodi.app.ethgas.com"

# Custom Settings
entity_name = "..." # my_amazing_team
enable_registration = true # false deregisters all, true registers all
registration_mode = "standard" # standard, standard-mux, ssv, obol, skipped
enable_ofac = true

# Specify either eoa_signing_key or access_jwt & refresh_jwt depending on is_jwt_provided boolean value
# Alternatively, you can set EOA_SIGNING_KEY or ACCESS_JWT & REFRESH_JWT in .cb.env as env variables

# This EOA is just your ETHGas account private key, it can be a clean, new address, not related to your validator
eoa_signing_key = "0x..." # for registration in exchange, required if is_jwt_provided = false

is_jwt_provided = false
access_jwt = "xxx.xxx.xxx" # required if is_jwt_provided = true
refresh_jwt = "xxx.xxx.xxx" # required if is_jwt_provided = true
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Metrics and Logs (Optional)

<details>

<summary>Optional metrics and logs configuration</summary>

{% code title="config.toml" lineNumbers="true" %}

```toml
# Configuration for how metrics should be collected and scraped
# OPTIONAL, skip metrics collection if missing
[metrics]
# Whether to collect metrics
# OPTIONAL, DEFAULT: true
enabled = true
# Host to listen on for metrics
# OPTIONAL, DEFAULT: 127.0.0.1
host = "127.0.0.1"
# Services will listen for Prometheus scrapes on this port, port + 1, +2, etc.
# OPTIONAL, DEFAULT: 10000
start_port = 10000

# Configuration stdout logs
# OPTIONAL, DEFAULT: enabled
[logs.stdout]
# Whether to enable stdout logging
# OPTIONAL, DEFAULT: true
enabled = true
# Log level. Supported values: trace, debug, info, warn, error
# OPTIONAL, DEFAULT: info
level = "info"
# Log in JSON format
# OPTIONAL, DEFAULT: false
use_json = false
# Whether to enable ANSI color codes
# OPTIONAL, DEFAULT: true
color = true

# Configuration file logs
# OPTIONAL, DEFAULT: disabled
[logs.file]
# Whether to enable file logging
# OPTIONAL, DEFAULT: false
enabled = true
# Log level. Supported values: trace, debug, info, warn, error
# OPTIONAL, DEFAULT: info
level = "debug"
# Log in JSON format
# OPTIONAL, DEFAULT: true
use_json = true
# Path to the log directory
# OPTIONAL, DEFAULT: /var/logs/commit-boost
dir_path = "./logs"
# Maximum number of log files to keep
# OPTIONAL
max_files = 30
```

{% endcode %}

</details>

### Start the Signer module

{% hint style="info" %}
For **DVT validators** or **remote signer**, you don't need to run this module.
{% endhint %}

For registration of non-DVT validators, run:

```bash
docker compose -f docker-compose.yml up cb_signer
```

✅ If your signer starts successfully, you should see the log similar to:

{% code overflow="wrap" %}

```
INFO Starting signing service version="0.8.0" commit_hash="f51f5bd61831fde943057b29ffd6e26e7eb23765" modules=["ETHGAS_COMMIT"] endpoint=0.0.0.0:20000 loaded_consensus=100 loaded_proxies=0
```

{% endcode %}

&#x20;where `loaded_consensus` indicates the total number of loaded keys.

### Start the ETHGas Commit module

You are advised to run this module at or after the 2nd slot of the current epoch, so you can have more time to configure the PBS module.

This module only needs to be run whenever you modify the configuration of this module, e.g. when you want to register or deregister a validator to the ETHGas Exchange, or to change account configuration settings, etc. Think of running this module as `"Update my config and sync with ETHGas"`.

To register the validators to the ETHGas Exchange, run:

```bash
docker compose -f docker-compose.yml up cb_ethgas_commit
```

✅  If all goes well, you will see the log:

{% code overflow="wrap" %}

```
INFO successful registration, you can now sell preconfs on ETHGas! or INFO successful registration, the default pricer can now sell preconfs on ETHGas on behalf of you!
```

{% endcode %}

❌ If the module encounters `ConnectionRefused` error when it tries to connect to `http://cb_signer:20000/signer/v1/get_pubkeys`, please wait for 20 minutes to retry.

### Start the PBS module

Start the PBS module by running:

```bash
docker compose -f docker-compose.yml up cb_pbs
```

The default port used by the PBS module is the same default port as MEV-Boost. If you had previously configured a custom port for MEV-Boost, make sure you have configured that on the PBS module.

✅ If all goes well, you will see the log:

{% code overflow="wrap" %}

```
DEBUG register_validators{req_id=...}:handler{relay_id="ethgas"}: registration successful code=200 latency=...ms
```

{% endcode %}

Once the ETHGas Commit module has completed the registration process and right before the start of the next epoch, stop your existing MEV-Boost client, restart the beacon node with new builder endpoint (if the port is different), and immediately start the PBS module.

To hot reload the config without restarting the module, run:

```bash
docker compose -f docker-compose.yml exec cb_pbs curl -X POST http://localhost:18550/reload
```

✅ You will see the log `INFO : config reload successful` if the config reloads successfully.&#x20;

Refer [here](https://commit-boost.github.io/commit-boost-client/get_started/configuration/#hot-reload) for more details about hot reloading.

***

### ⭐️ You're Realtime Ready ⭐️

Now your validators are registered to ETHGas and you're connected to the ETHGas relay, that's it! You're ready to propose Realtime blocks when the market is open.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ethgas.com/get-started/validators-node-operators.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
