Setting Up Your GenLayer Validator
Running a GenLayer Validator node ensures the security and reliability of the GenLayer network. Below are the requirements for running a GenLayer validator.
Validators require both a staking deposit and a validator priming transaction to enter the set.
For a deeper understanding of how staking works in GenLayer, see the Staking documentation.
System Requirements
| Resource | Requirement |
|---|---|
| Memory | 16 GB RAM |
| CPU | 8-core (AMD64 only) |
| Disk | 128 GB SSD/NVMe |
| Network | 100 Mbps |
| OS | 64-bit Linux |
| Software | Docker, Python 3 (with pip and venv) |
GPU not required unless running LLMs locally. See detailed requirements for more info.
Create the Validator Wallet
Before setting up your validator node, you need to create your validator wallet and stake GEN tokens.
Understanding Validator Addresses
GenLayer validators use three distinct addresses:
| Address | Description | Where Used |
|---|---|---|
| Owner | The only address that can withdraw staked funds. Keep this secure (cold wallet). | CLI wizard - signs staking transaction |
| Operator | Hot wallet on your server that signs blocks. Can be same as owner, but separate is recommended. | Node config: operatorAddress |
| Validator Wallet | Smart contract created when you join. This is your validator's on-chain identity. | Node config: validatorWalletAddress |
The wizard outputs all three addresses at the end. Save them - you'll need the Validator Wallet and Operator addresses for your node configuration.
Prerequisites
- Node.js (v18 or higher)
- GenLayer CLI - Install the latest version:
npm install -g genlayer - GEN tokens - You need at least 42,000 GEN for the minimum self-stake requirement
Using the Validator Wizard
The easiest way to create your validator wallet is using the interactive wizard:
genlayer staking wizardThe wizard guides you through:
- Account setup - Create or select your owner account
- Network selection - Choose testnet-asimov
- Balance verification - Confirms you have at least 42,000 GEN
- Operator setup - Create and export an operator keystore for your validator server
- Stake amount - Enter how much GEN to stake (minimum 42,000)
- Validator creation - Submits the staking transaction
- Identity setup - Set your validator's public profile (moniker, website, etc.)
Save Your Validator Wallet Address! After the wizard completes, note down your Validator Wallet address. You'll need this for your node configuration.
Operator Keystore Export
The wizard creates and exports an operator keystore file for you to transfer to your validator server. If your server is compromised, your staked funds (controlled by owner) remain safe.
Verify Your Validator
After completing the wizard, verify your status:
genlayer staking validator-info --validator 0xYourValidatorWallet...Managing Your Validator
# Add more stake
genlayer staking validator-deposit --amount 1000gen
# Check active validators
genlayer staking active-validators
# Exit (initiates 7-epoch unbonding)
genlayer staking validator-exit --shares 100
# Claim after unbonding period
genlayer staking validator-claim
# Update identity
genlayer staking set-identity --validator 0x... --moniker "New Name"Set Up the Validator Node
Once your validator wallet is created and staked, set up your node software.
Dependencies
LLM Access
Each validator needs access to a Large Language Model (LLM) for executing and evaluating Intelligent Contracts.
It is up to each validator to select the model they want to use.
Possible options:
- Run an open-source model locally on the same machine with a GPU
- Run an open-source model on a different machine
- Connect to a hosted inference provider (OpenAI, Anthropic, Heurist, Atoma network etc.)
ZKSync Full Node for the GenLayer Chain
Each validator needs access to a ZKSync Full Node (opens in a new tab) connected to the GenLayer chain. Validators use this node to read the chain state and submit transactions.
One full node can be shared between multiple validators. The optimal validator-to-node ratio is currently under evaluation.
Setup
Download the node software
-
Select the version of the node you want to run by checking the available builds
You can use this command to list available versions:
curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | grep -o '"name": *"[^"]*"' | sed -n 's/.*\/\(v[^/]*\)\/.*/\1/p' | sort -ru | grep -v "rc" | head -n 5You should see a list like this
v0.4.4 v0.4.3 v0.4.2 v0.4.1 v0.4.0Typically, you will want to run the latest version
-
Download the packaged application
export version=v0.4.4 # set your desired version here wget https://storage.googleapis.com/gh-af/genlayer-node/bin/amd64/${version}/genlayer-node-linux-amd64-${version}.tar.gz -
Extract the node software
mkdir -p ${version} tar -xzvf `genlayer-node-linux-amd64-${version}.tar.gz` -C `./${version}` -
Change the directory
cd `./${version}` -
Run Genvm setup
python3 ./third_party/genvm/bin/setup.py
It does following:
- Downloads missing runners if any
- Verifies runners hashes
- Sets
elf/mach-ointerpreter for all binaries (modules, genvm) - Rust precompilation for built-in runners
Configuration
Before you can start up the node, you need to configure it.
config.yaml
This is the main configuration file of your node. Without it, your node won't start
The file needs to be located at configs/node/config.yaml
You can use the following example configuration. Note: For most users, you will only need to modify the genlayerchainrpcurl and genlayerchainwebsocketurl values below.
# rollup configuration
rollup:
genlayerchainrpcurl: "TODO: Set your GenLayer Chain ZKSync HTTP RPC URL here" # GenLayer Chain RPC URL
genlayerchainwebsocketurl: "TODO: Set your GenLayer Chain ZKSync WebSocket RPC URL here" # GenLayer Chain WebSocket URL
# consensus contracts configuration
consensus:
# Asimov - Phase 4
contractmainaddress: "0x67fd4aC71530FB220E0B7F90668BAF977B88fF07" # ConsensusMain Smart Contract Address
contractdataaddress: "0xB6E1316E57d47d82FDcEa5002028a554754EF243" # ConsensusData Smart Contract Address
genesis: 4632386 # (Optional) Genesis block number for this consensus deployment. If not provided, it will be auto-detected by searching for the first log from the ConsensusMain contract.
# data directory
datadir: "./data/node"
# logging configuration
logging:
level: "INFO"
# json: `true` for json output to console, false for human readable log formatting
json: false
# Configuration for https://github.com/natefinch/lumberjack
file:
# enabled: set to `true` to save logs to a folder
enabled: true
level: "DEBUG"
# folder: path to the folder where to store logs. Relative paths go under `datadir`.
folder: logs
# maxsize: maximum size in megabytes of the log file before it gets rotated.
maxsize: 10
# maxage: maximum number of days to retain old log files based on the timestamp encoded in their filename.
maxage: 7
# maxbackups: maximum number of old log files to retain. Set to 0 for no limit
maxbackups: 100
# localtime: determines if the time used for formatting the timestamps in backup files is the computer's local time. Set to `false` to use UTC time.
localtime: false
# compress: determines if the rotated log files should be compressed using gzip
compress: true
# node configuration
node:
# Uncomment if the ID of the node is different from the validator wallet address.
# It is used to identify the node in the network.
# id: "node"
# Mode can be "validator" or "full".
# Default value is "validator".
mode: "validator"
# Address of the ValidatorWallet contract (required for validator mode)
validatorWalletAddress: ""
# Address of the operator that owns the ValidatorWallet
operatorAddress: ""
admin:
port: 9155
rpc:
port: 9151 # RPC server port
endpoints:
# Group-level configuration (enables/disables all methods in a group)
groups:
genlayer: true # gen_* methods (call, getContractSchema, etc.)
genlayer_debug: true # gen_dbg_* methods (ping, load_test, trie)
ethereum: true # eth_* proxy methods
zksync: true # zks_* proxy methods
# Method-level configuration (overrides group settings for specific methods)
methods:
gen_call: true
gen_getContractSchema: true
gen_getTransactionStatus: true
gen_getTransactionReceipt: true
gen_dbg_ping: true
gen_dbg_load_test: true
eth_blockNumber: true
eth_getBlockByNumber: true
eth_getBlockByHash: true
eth_sendRawTransaction: true
zks_getTransaction: true
ops:
port: 9153 # Metrics port
endpoints:
metrics: true # Enable metrics endpoint
health: true # Enable health endpoint
balance: true # Enable balance endpoint
# genvm configuration
genvm:
root_dir: ./third_party/genvm
start_manager: true # if true node will start genvm manager itself
manager_url: http://127.0.0.1:3999
permits: # Leave empty for autodiscovery, put a number for updating genvm permits on startup
# Advanced configuration
merkleforest:
maxdepth: 16
dbpath: "./data/node/merkle/forest/data.db"
indexdbpath: "./data/node/merkle/index.db"
merkletree:
maxdepth: 16
dbpath: "./data/node/merkle/tree/"
# metrics configuration
metrics:
interval: "15s" # Default interval for all collectors (can be overridden per collector)
collectors:
node:
enabled: true
# interval: "30s" # Optional: Override default interval for this collector
genvm:
enabled: true
# interval: "20s" # Optional: Override default interval for this collector
# enable_simulated_traffic: false # Optional: Enable simulated network traffic metrics for GenVM processes (default: false)
# simulated_rx_bytes_per_process: 1024 # Optional: Simulated received bytes per process per interval (default: 1024)
# simulated_tx_bytes_per_process: 512 # Optional: Simulated transmitted bytes per process per interval (default: 512)
webdriver:
enabled: true
# interval: "60s" # Optional: Override default interval for this collector
Overriding Configuration with Environment Variables
Any configuration value in config.yaml can be overridden using environment variables with the prefix GENLAYERNODE_.
Pattern:
- Replace dots (
.) with underscores (_) - Convert to uppercase
- Add the
GENLAYERNODE_prefix
Examples:
| Config Key | Environment Variable |
|---|---|
rollup.genlayerchainrpcurl | GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL |
rollup.genlayerchainwebsocketurl | GENLAYERNODE_ROLLUP_GENLAYERCHAINWEBSOCKETURL |
consensus.contractmainaddress | GENLAYERNODE_CONSENSUS_CONTRACTMAINADDRESS |
consensus.contractdataaddress | GENLAYERNODE_CONSENSUS_CONTRACTDATAADDRESS |
consensus.genesis | GENLAYERNODE_CONSENSUS_GENESIS |
node.mode | GENLAYERNODE_NODE_MODE |
node.validatorWalletAddress | GENLAYERNODE_NODE_VALIDATORWALLETADDRESS |
node.operatorAddress | GENLAYERNODE_NODE_OPERATORADDRESS |
node.rpc.port | GENLAYERNODE_NODE_RPC_PORT |
logging.level | GENLAYERNODE_LOGGING_LEVEL |
Usage example:
# Override the RPC port
export GENLAYERNODE_CONSENSUS_CONTRACTMAINADDRESS="0x..."
# Set validator wallet address
export GENLAYERNODE_NODE_VALIDATORWALLETADDRESS="0x..."
# Set logging level
export GENLAYERNODE_LOGGING_LEVEL="DEBUG"Environment variables take precedence over values in config.yaml, making them ideal for Docker deployments or sensitive values you don't want in configuration files.
GenVM Configuration
See the GenVM Configuration page for detailed LLM provider setup, configuration files, and advanced features like greyboxing.
Import the Operator Key
The operator key is used by your node to sign blocks and perform validator duties.
Option 1: Import from CLI Wizard (Recommended)
If you used genlayer staking wizard, it exported an operator keystore file. Transfer this file to your validator server and import it:
./bin/genlayernode account import \
--password "your node password" \
--passphrase "password you set when exporting from wizard" \
--path "/path/to/operator-keystore.json" \
-c $(pwd)/configs/node/config.yaml \
--setupYou should see:
Account imported:
Address: 0xA0b12Fd2f3F7e86fEC458D114A5E7a6f571160a8
Account setup as a validatorOption 2: Generate New Operator Key
You can also generate a new operator key directly on the server:
./bin/genlayernode account new -c $(pwd)/configs/node/config.yaml --setup --password "your secret password"Then use this address when running the wizard on your local machine.
Restoring Your Operator Key
To restore from a backup (e.g., after migrating to a new server):
./bin/genlayernode account import \
--password "your node password" \
--passphrase "your backup encryption passphrase" \
--path "/path/to/your/secure/backup.key" \
-c $(pwd)/configs/node/config.yaml \
--setupAlways verify that your imported key works by checking the operator address matches what's configured for your validator.
Backing Up Your Operator Key
After setting up your operator key, back it up securely:
./bin/genlayernode account export \
--password "your node password" \
--address "your operator address" \
--passphrase "your backup encryption passphrase" \
--path "/path/to/your/secure/backup.key" \
-c $(pwd)/configs/node/config.yamlImportant: Back up your operator key! Losing access means you'll need to set up a new operator and update your validator configuration. Store the backup securely.
To print the private key from your backup file, use the --print flag. Keep this private key secure and never share it.
Running the node
Once you have configured everything, you are ready to start the node.
Important: Before starting the node, ensure you have:
- Operator key imported into the node (see "Import the Operator Key" above)
- Validator wallet address - obtained after joining as validator via
genlayer staking wizardorvalidator-join
Without both configured, your node will run as a full node instead of a validator.
Running the Node using the binary
-
Set the LLM Provider API Key
Set the appropriate environment variable for your chosen LLM provider. See the GenVM Configuration page for details on LLM providers and obtaining API credits.
# For Heurist export HEURISTKEY='your_heurist_api_key' # For Comput3 export COMPUT3KEY='your_comput3_api_key' # For io.net export IOINTELLIGENCE_API_KEY='your_ionet_api_key' # For other providers, use the appropriate environment variable name -
Run the WebDriver container
docker compose up -d # Starts the WebDriver needed by the GenVM web module -
(Optional) Run two services (modules) in background (this is a crucial step for running Intelligent contracts). This can be done automatically or manually.
- To start them automatically in node configuration set
genvm.manage_modulestotrue - To start them manually run
./third_party/genvm/bin/genvm-modules web & ./third_party/genvm/bin/genvm-modules llm &
- To start them automatically in node configuration set
Note: If you are using the default configuration, genvm.manage_modules is
set to true by default, meaning the node will manage these modules
automatically.
-
Checking Your Configuration
To ensure your node is correctly configured, you can run the following command:
./bin/genlayernode doctorThe
doctorcommand now includes comprehensive GenVM diagnostics integration to validate:- Consensus contract configuration and accessibility
- GenVM module connectivity and health status
- LLM provider configuration and API connectivity
- Network configuration and ZKSync node accessibility
-
Run the node
./bin/genlayernode run -c $(pwd)/configs/node/config.yaml --password "your secret password" # The same password you used when creating the account
If you are running the node via SSH, the process might terminate if your
connection drops. To prevent this, consider using a terminal multiplexer like
screen or tmux to keep the node running in the background even if your SSH
session ends. You can find a guide on using screen
here (opens in a new tab).
Running the Node using docker-compose
You can also run the GenLayer node using Docker and Docker Compose.
- Create a
docker-compose.yamlfile with the following content:
services:
webdriver-container:
container_name: genlayer-node-webdriver
image: yeagerai/genlayer-genvm-webdriver:0.0.9
shm_size: 2gb
security_opt:
- no-new-privileges:true
environment:
PORT: 4444
ports:
- "${WEBDRIVER_PORT:-4444}:4444"
restart: unless-stopped
genlayer-node:
image: yeagerai/genlayer-node:${NODE_VERSION:-latest}
entrypoint: ["sh", "-c", "/app/bin/genlayernode run --password ${NODE_PASSWORD:-12345678}"]
container_name: genlayer-node
restart: unless-stopped
env_file:
- path: ./.env
required: false
ports:
- "${NODE_RPC_PORT:-9151}:9151"
- "${NODE_OPS_PORT:-9153}:9153"
volumes:
- ${NODE_CONFIG_PATH:-./configs/node/config.yaml}:/app/configs/node/config.yaml:ro
- ${NODE_DATA_PATH:-./data}:/app/data
- ./genvm-module-web-docker.yaml:/app/third_party/genvm/config/genvm-module-web.yaml
- /var/run/docker.sock:/var/run/docker.sock:ro # required for webdriver metrics collection
security_opt:
- no-new-privileges:true
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
compress: "true"
depends_on:
- webdriver-container
profiles:
- node
- Create
genvm-module-web-docker.yamlfor Docker networking:
The extracted tarball includes third_party/genvm/config/genvm-module-web.yaml configured for localhost, which works when running
the binary directly. For docker-compose, you need a version that points to the webdriver service name.
Create genvm-module-web-docker.yaml in the same directory as your docker-compose.yaml:
- Copy the contents of
third_party/genvm/config/genvm-module-web.yamlintogenvm-module-web-docker.yaml. - Modify the
webdriver_hostconfiguration to use the service namewebdriver-containerinstead oflocalhost:
webdriver_host: http://webdriver-container:4444This allows the node container to reach the webdriver container using Docker's internal networking.
The key difference:
- Binary execution: uses
localhost:4444(webdriver runs on same machine) - Docker-compose: uses
webdriver-container:4444(container service name)
- Set the required environment variables in a
.envfile:
This .env file serves two purposes: it configures Docker Compose variables (like NODE_VERSION, NODE_PASSWORD, ports) and can also include GENLAYERNODE_* variables to override node configuration values as described in Overriding Configuration with Environment Variables.
# GenLayer Node Release Configuration
# =============================================================================
# WebDriver Configuration (required for GenVM)
# =============================================================================
WEBDRIVER_PORT=4444
# =============================================================================
# Node Service Configuration (optional - use node profile)
# =============================================================================
# Docker image version
NODE_VERSION=v0.4.0
# Keystore password (used to unlock the pre-imported wallet)
NODE_PASSWORD=12345678
# Path to node configuration file
NODE_CONFIG_PATH=./configs/node/config.yaml
# Path to node data directory (for persistence)
NODE_DATA_PATH=./data
# Port mappings
NODE_RPC_PORT=9151
NODE_OPS_PORT=9153
# LLM API Key (required for GenVM LLM module)
HEURISTKEY=
ANTHROPICKEY=
XAIKEY=
GEMINIKEY=
ATOMAKEY=or simply use the provided docker-compose.yaml, .env.example and the genvm-module-web-docker.yaml from the extracted tarball.
- Checking Your Configuration
To ensure your node is correctly configured, you can run the following command:
source .env && docker run --rm --env-file ./.env \
-v ${NODE_CONFIG_PATH:-./configs/node/config.yaml}:/app/configs/node/config.yaml \
yeagerai/genlayer-node:${NODE_VERSION:-v0.4.0} \
./bin/genlayernode doctor- Start the services using Docker Compose:
source .env && docker compose --profile node up -dTelemetry
For a quick setup using Docker Compose:
-
Configure your
.envfile with the required variables for monitoring:# Central monitoring server endpoints for GenLayer Foundation CENTRAL_MONITORING_URL=https://prometheus-prod-66-prod-us-east-3.grafana.net/api/prom/push CENTRAL_LOKI_URL=https://logs-prod-042.grafana.net/loki/api/v1/push # Authentication for central monitoring # Metrics (Prometheus) credentials CENTRAL_MONITORING_USERNAME=your-metrics-username CENTRAL_MONITORING_PASSWORD=your-metrics-password # Logs (Loki) credentials CENTRAL_LOKI_USERNAME=your-logs-username CENTRAL_LOKI_PASSWORD=your-logs-password # Node identification NODE_ID=validator-001 VALIDATOR_NAME=MyValidator -
Run docker compose:
docker compose --profile monitoring up -d -
Verify your node is pushing metrics by checking the GenLayer Foundation public dashboard (opens in a new tab)
For detailed monitoring setup including Prometheus metrics, Grafana dashboards, and centralized logging with Alloy, see the Monitoring Guide.