Skip to content

Run the validator client against remote beacon nodes with the new vc and bn commands - #943

Merged
Tumas merged 1 commit into
developfrom
feature/separate-vc
Oct 22, 2026
Merged

Tumas merged 1 commit into
developfrom
feature/separate-vc

Conversation

@Tumas

@Tumas Tumas commented Sep 29, 2026

Copy link
Copy Markdown
Member

grandine vc --beacon-node-urls ... runs the validator client alone against remote beacon nodes, grandine bn runs the beacon node alone, and the bare command runs the beacon node with the local validator when one is configured. Duties come from exactly one source: the built-in node or the remote nodes. vc refuses options that only the built-in beacon node acts on.

The validator no longer holds the fork choice controller. It works through a ChainSource, and every duty goes through the BeaconNodeApi trait, which the built-in node and the remote nodes both implement: attester, aggregation, sync committee, PTC, proposer, payload attestation, voluntary exit and doppelganger liveness duties, plus prepared proposers, validator registrations and proposer preferences. Attestation data returned by a remote node is validated for the reported index and target epoch before it is signed. Proposer preferences are published for the dependent root the duties are held under.

Remote nodes are polled for health and ranked by it, then by the newest head; an unreachable node is kept as the last choice. Requests have per-endpoint timeouts, a head stream tracks reorgs, and a slot head fallback covers a node that falls behind. Duties are published to every node by default, returning once one accepts; the payload envelope goes to the node that produced the block. In remote mode the validator is driven by clock ticks directly, and genesis is agreed with the nodes before it starts.

Resolves own validator indices from the finalized state, driven by events.

Register the validator client with the beacon nodes' builder via --use-builder pre-gloas, skipping validators without a fee recipient

Stop counting sync committee messages as validator liveness

Run the doppelganger check late in the slot
At the aggregate tick every node has ticked into the epoch and seen the slot's attestations

Leave the peer counts out of validator client logs

Identify the chain by its genesis validators root without loading the state; vc and the interchange commands use the predefined network's root, read from the embedded mainnet state or a constant for the testnets;

Run data column recovery on the reconstruction executor

Accept a slot's worth of aggregates in one publish request

Doppelganger protection no longer reads the local beacon state or the liveness tracker directly: it takes validator indices and a liveness query from the caller, so it works against remote beacon nodes, where only synced nodes are asked and a validator seen live by any of them counts as live. A key is activated only after a successful check, a failed query postpones activation instead of panicking, and a key whose index is unknown is not activated until its index resolves and a full check window has passed from that point.

@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 7 times, most recently from 74575be to ff3057f Compare October 1, 2026 10:03
@povi povi mentioned this pull request Oct 1, 2026
@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 3 times, most recently from a9394bf to 7776abd Compare October 1, 2026 15:15
@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 12 times, most recently from f461b08 to fe33b60 Compare October 9, 2026 11:20
@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 6 times, most recently from 9b798ad to 9cf0249 Compare October 14, 2026 11:29
@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 13 times, most recently from 924edf3 to 9fdedfd Compare October 21, 2026 11:25
@Tumas
Tumas requested review from a team and povi and removed request for a team October 21, 2026 11:31
@SifraiTeam
SifraiTeam force-pushed the feature/separate-vc branch 6 times, most recently from 9965360 to 9480a54 Compare October 22, 2026 13:23
…and bn commands

`grandine vc --beacon-node-urls ...` runs the validator client alone
against remote beacon nodes, `grandine bn` runs the beacon node alone,
and the bare command runs the beacon node with the local validator when
one is configured. Duties come from exactly one source: the built-in
node or the remote nodes. vc refuses options that only the built-in
beacon node acts on.

The validator no longer holds the fork choice controller. It works
through a ChainSource, and every duty goes through the BeaconNodeApi
trait, which the built-in node and the remote nodes both implement:
attester, aggregation, sync committee, PTC, proposer, payload
attestation, voluntary exit and doppelganger liveness duties, plus
prepared proposers, validator registrations and proposer preferences.
Attestation data returned by a remote node is validated for the
reported index and target epoch before it is signed. Proposer
preferences are published for the dependent root the duties are held
under.

Remote nodes are polled for health and ranked by it, then by the newest
head; an unreachable node is kept as the last choice. Requests have
per-endpoint timeouts, a head stream tracks reorgs, and a slot head
fallback covers a node that falls behind. Duties are published to every
node by default, returning once one accepts; the payload envelope goes
to the node that produced the block. In remote mode the validator is
driven by clock ticks directly, and genesis is agreed with the nodes
before it starts.

Signing no longer needs a beacon state: the signer takes the fork
information and the current epoch, and slashing protection takes the
epoch. Own validator indices are resolved from the finalized state,
driven by finalization events and by changes to the signer's keys. The
chain is identified by its genesis validators root without loading the
state; vc and the interchange commands use the predefined network's
root, read from the embedded mainnet state or a constant for the
testnets.

Doppelganger protection no longer reads the local beacon state or the
liveness tracker directly: it takes validator indices and a liveness
query from the caller, so it works against remote beacon nodes, where
only synced nodes are asked and a validator seen live by any of them
counts as live. The check runs late in the slot, at the aggregate tick,
when every node has ticked into the epoch and seen the slot's
attestations. A key is activated only after a successful check, a failed
query postpones activation instead of panicking, and a key whose index
is unknown is not activated until its index resolves and a full check
window has passed from that point. A key removed during its check window
starts a new one when it returns. A detected doppelganger stops the
application through a typed error rather than a panic, so it is not
restarted. --detect-doppelgangers needs --track-liveness only with the
built-in beacon node. Sync committee messages no longer count towards
validator liveness.

Register the validator client with the beacon nodes' builder via
--use-builder pre-Gloas, skipping validators without a fee recipient.

Also:
- Leave the peer counts out of validator client logs
- Run data column recovery on its own executor
- Accept a slot's worth of aggregates in one publish request
- Keep peers on subscribed sync committee subnets until the subscription
  expires
- Serve next epoch attester duties from the state at the current slot
  when the head lags, and accept next epoch duty requests sent as the
  clock enters a new epoch
- Let the builder publish a blinded block from Fulu on instead of
  unblinding it
- Reject and don't publish single attestations from validators outside
  the named committee
- Limit concurrent Web3Signer requests for whole-epoch batches
- Send the block event only after fork choice exposes the block's head
- Keep finalized blocks in the store until they are written to storage
- Fix the network dashboard
@Tumas
Tumas merged commit 8629806 into develop Oct 22, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant