Using Caplin as Validator
Caplin, the Erigon embedded Consensus Layer, is also suitable for staking. However, it is required to pair it with a validator key manager, such as Lighthouse or Teku, since it doesn't have a native key management system.
This guide explains how to use Erigon with its embedded Caplin consensus layer and Lighthouse as the validator client for staking on Ethereum.
1. Start Erigon with Caplin
The following command starts Erigon with the embedded Caplin consensus layer with the beacon API on:
erigon \
--datadir=/data/erigon \
--http \
--http.addr=0.0.0.0 \
--http.port=8545 \
--http.api=engine,eth,net,web3 \
--ws \
--ws.port=8546 \
--caplin.enable-upnp \
--caplin.discovery.addr=0.0.0.0 \
--caplin.discovery.port=4000 \
--caplin.discovery.tcpport=4001 \
--beacon.api=beacon,validator,builder,config,debug,events,node,lighthouse
Flags Explanation:
- Execution Layer (Erigon):
--http.api=engine,eth,net,web3: enables the necessary APIs for external clients and Caplin.--ws: enables WebSocket-based communication (optional).
- Consensus Layer (Caplin):
--caplin.discovery.addrand--caplin.discovery.port: configures Caplin's gossip and discovery layer.--beacon.api=beacon,validator,builder,config,debug,events,node,lighthouse: enables all possible API endpoints for the validator client.
2. Set Up Lighthouse Validator Client
2.1 Install Lighthouse
Install and run Lighthouse by following the official guide at https://lighthouse-book.sigmaprime.io/installation.html or use Docker:
docker pull sigp/lighthouse:latest
2.2. Create Lighthouse Validator Key Directory
mkdir -p ~/.lighthouse/validators
2.3. Run Lighthouse Validator Client
Start the validator client and connect it to the Caplin CL:
lighthouse vc \
--network mainnet \
--beacon-nodes http://127.0.0.1:5555 \
--suggested-fee-recipient=<your_eth_address>
Flags Explanation:
--network mainnet: Specifies the Ethereum mainnet.--beacon-nodes: Points to the Caplin beacon API athttp://127.0.0.1:5555.--suggested-fee-recipient: Specifies your Ethereum address for block rewards.
2.4. Import Validator Keys
If you have existing validator keys, import them:
lighthouse account validator import --directory <path_to_validator_keys>
3. Block Production Behaviour
3.1. Payload Preparation Ahead of the Proposer Slot
Since v3.6, Caplin primes the execution layer one slot before the slot this node is due to propose, so the execution layer has already begun assembling a payload when the proposal is requested. There is no flag for this; it is on whenever all of the following hold:
- The Beacon API is running with the
validatornamespace enabled — for example--beacon.api=beacon,validator,...as in the command above. Withoutvalidator, preparation never starts. - A validator client has registered a fee recipient for the proposer index, which Lighthouse does through the standard
prepare_beacon_proposercall. A node with no registered validators never does the work. - Caplin is driving the in-process execution layer. Passing
--caplin.use-engine-apiswitches Caplin onto the Engine API and disables the Beacon API entirely — Erigon logsBeacon API is automatically disabledif you also passed--beacon.api. Staking through Caplin is not possible in that mode: there is novalidatornamespace, so block production and duties are unavailable, not just payload preparation.
Preparation looks at most one slot ahead, and it does not alter execution-layer fork choice — it only starts the builder early. To confirm it is running, look for these lines in the Erigon log:
PayloadPreparation: watching for proposals
PayloadPreparation: primed execution layer
Preparation is skipped for the Gloas (EIP-7732) fork, where builders gossip bids instead, and before Capella.
3.2. Fork-Choice Head Published Before the Head-State Copy
Since v3.6, Caplin publishes the head chosen by fork choice as soon as it is selected, rather than after the head beacon state has been copied. Beacon API endpoints that only need the head block identity — such as /eth/v1/beacon/blocks/head and /eth/v2/debug/beacon/heads — therefore reflect a new head sooner. Endpoints that read the head state are unchanged, and a node that is still syncing continues to return 503. There is no flag for this.
3.3. Default Block Graffiti
Since v3.6, when the validator client does not supply a graffiti, Caplin fills it with the proposing node's connected execution and consensus clients, following the Engine API client-identification standard. The value is a two-letter execution client code and the first four hex characters of its commit, followed by Caplin's own code CN and the first four hex characters of the Erigon commit — for example EGa53eCNa53e when Caplin is paired with Erigon. If the execution client does not answer engine_getClientVersionV1, or has not answered it yet, the graffiti carries the consensus half only (CN plus commit). The graffiti always names the locally connected execution client. An external builder's bid does not change it: the graffiti is written into the beacon body before the payload is chosen, and the winning bid replaces only the execution side of the block — so the value still identifies the proposing node's own clients, not whoever built the payload.
There is no CLI flag for graffiti. The only way to override it is per block, through the Beacon API: a validator client that sends a graffiti query parameter on a validator block-production endpoint — GET /eth/v2/validator/blocks/{slot} (deprecated), GET /eth/v3/validator/blocks/{slot} or GET /eth/v4/validator/blocks/{slot} — has its value used instead of the default. The parameter is read as a 32-byte hex value, as the Beacon API specification requires. It is not validated: a malformed or empty value is not rejected and does not fall back to the default — it silently produces an all-zero graffiti. A shorter hex value is left-padded with zeros, and a longer one is cropped from the left. Note that a validator client which sets graffiti by default — including its own client string — overrides Caplin's default; to get the client-pair graffiti, leave the validator client's graffiti unset.