Repository navigation
Run the validator client against remote beacon nodes with the new vc and bn commands - #943
Merged
Merged
Conversation
SifraiTeam
force-pushed
the
feature/separate-vc
branch
7 times, most recently
from
October 1, 2026 10:03
74575be to
ff3057f
Compare
SifraiTeam
force-pushed
the
feature/separate-vc
branch
3 times, most recently
from
October 1, 2026 15:15
a9394bf to
7776abd
Compare
SifraiTeam
force-pushed
the
feature/separate-vc
branch
12 times, most recently
from
October 9, 2026 11:20
f461b08 to
fe33b60
Compare
SifraiTeam
force-pushed
the
feature/separate-vc
branch
6 times, most recently
from
October 14, 2026 11:29
9b798ad to
9cf0249
Compare
SifraiTeam
force-pushed
the
feature/separate-vc
branch
13 times, most recently
from
October 21, 2026 11:25
924edf3 to
9fdedfd
Compare
SifraiTeam
force-pushed
the
feature/separate-vc
branch
6 times, most recently
from
October 22, 2026 13:23
9965360 to
9480a54
Compare
…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
SifraiTeam
force-pushed
the
feature/separate-vc
branch
from
October 22, 2026 13:33
9480a54 to
5656252
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
grandine vc --beacon-node-urls ...runs the validator client alone against remote beacon nodes,grandine bnruns 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.