Skip to content

Caplin Liveness Checks Previous Epoch #20979

@MysticRyuujin

Description

@MysticRyuujin

System information

Erigon version: erigontech/erigon:v3.4.0

Consensus Layer: Caplin

Chain/Network: Mainnet

Expected behaviour

Correctly report liveness of validator index

Actual behaviour

Caplin reports validator(s) as live, when they are not

Steps to reproduce the behaviour

Query /eth/v1/validator/liveness and compare outputs from other CL clients

Issue was identified while trying to use Vero

Related Issue: serenita-org/vero#315

Here's a sample of the output from Vero's logs, redacted with fake validator index numbers:

2026-05-04 14:27:35,001 - BeaconNode           - DEBUG: Making POST request to http://nimbus:5052/eth/v1/validator/liveness/445522
2026-05-04 14:27:35,002 - BeaconNode           - DEBUG: Making POST request to http://lighthouse:5052/eth/v1/validator/liveness/445522
2026-05-04 14:27:35,004 - BeaconNode           - DEBUG: Making POST request to http://teku:5052/eth/v1/validator/liveness/445522
2026-05-04 14:27:35,005 - BeaconNode           - DEBUG: Making POST request to http://caplin:5052/eth/v1/validator/liveness/445522
2026-05-04 14:27:36,042 - DoppelgangerDetector - DEBUG: Liveness response from nimbus: [ValidatorLiveness(index='1', is_live=False), ValidatorLiveness(index='2', is_live=False), ValidatorLiveness(index='3', is_live=False)]
2026-05-04 14:27:36,043 - DoppelgangerDetector - DEBUG: Liveness response from lighthouse: [ValidatorLiveness(index='1', is_live=False), ValidatorLiveness(index='2', is_live=False), ValidatorLiveness(index='3', is_live=False)]
2026-05-04 14:27:36,043 - DoppelgangerDetector - DEBUG: Liveness response from teku: [ValidatorLiveness(index='1', is_live=False), ValidatorLiveness(index='2', is_live=False), ValidatorLiveness(index='3', is_live=False)]
2026-05-04 14:27:36,043 - DoppelgangerDetector - DEBUG: Liveness response from caplin: [ValidatorLiveness(index='3', is_live=True), ValidatorLiveness(index='1', is_live=True), ValidatorLiveness(index='2', is_live=True)]

As you can see 3 CL clients report the validators as not being live, while Caplin reports them as being live.

From Vero's developer issue comment:

Based on this it looks like Caplin also takes previous epoch (N-1) participation into account when responding to API requests for liveness data for epoch N. I don't think that is correct behavior.

This breaks Doppelganger Protection

Metadata

Metadata

Assignees

Labels

CaplinCaplin: Consensus Layer, Beacon API

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions