🎯 Problem to be solved
Charon currently ignores the VC's proposer config: prepare_beacon_proposer is a no-op (core/validatorapi/router.go, submitProposalPreparations) and register_validator is ignored (core/validatorapi/validatorapi.go, SubmitValidatorRegistrations). Charon injects the lock's fee recipient itself. As a result the VC-side fee recipient / gas limit are unmanaged and irrelevant today — CDVN VCs set none, and Teku even hardcodes --validators-proposer-default-fee-recipient 0x0000…0000.
Post-gloas the VC signs fee_recipient and target_gas_limit into SignedProposerPreferences (#4691), so its local config becomes load-bearing and must match the lock cluster-wide or the partial signatures won't aggregate. This issue: give Charon a way to push the cluster-canonical fee recipient + gas limit (lock FeeRecipientAddresses / TargetGasLimit) into the VCs.
This has independent, pre-gloas value — it makes VCs hold the correct fee recipient rather than relying on Charon's override — so it can land before the gloas duty.
Sub-task of the gloas epic #4324.
🛠️ Proposed solution
Findings
- No standard config file exists. The ecosystem is standardizing an API instead — keymanager-APIs#87 (
/eth/v1/validator/config, closed/contentious, not ratified), explicitly to kill the "different config dialect per client" burden it names for dappnode/eth-docker.
- Per-client config surfaces:
- Prysm / Teku / Lodestar — one central
proposer_config JSON: --proposer-settings-file / --validators-proposer-config / --proposerSettingsFile.
- Nimbus — per-validator files
<validators-dir>/<pubkey>/suggested_fee_recipient.hex + suggested_gas_limit.json.
- Lighthouse (not in CDVN) —
validator_definitions.yml (keystore-entangled; standalone fee-recipient file removed) or keymanager API.
- Dynamic reload (matters for coordinated
gas_limit bumps, which are applied staggered across operators):
- Keymanager API is dynamic on all clients (and the client persists the change to its own config file).
- File hot-reload only on Teku (
--Xvalidators-proposer-config-refresh-enabled, per epoch) and Nimbus (per-validator files read live). Prysm, Lodestar, Lighthouse require a restart to pick up a file change.
Recommendation
Keymanager-API-primary — uniform across all clients, dynamic (no restart), durable (client persists it), and aligned with where the standard is heading — with optional file generation as a boot-time seed for operators who don't want to enable keymanager (documented as static / restart-to-change on Prysm/Lodestar/Lighthouse). Final mechanism choice is the first task below.
Tasks
🔗 References
🎯 Problem to be solved
Charon currently ignores the VC's proposer config:
prepare_beacon_proposeris a no-op (core/validatorapi/router.go,submitProposalPreparations) andregister_validatoris ignored (core/validatorapi/validatorapi.go,SubmitValidatorRegistrations). Charon injects the lock's fee recipient itself. As a result the VC-side fee recipient / gas limit are unmanaged and irrelevant today — CDVN VCs set none, and Teku even hardcodes--validators-proposer-default-fee-recipient 0x0000…0000.Post-gloas the VC signs
fee_recipientandtarget_gas_limitintoSignedProposerPreferences(#4691), so its local config becomes load-bearing and must match the lock cluster-wide or the partial signatures won't aggregate. This issue: give Charon a way to push the cluster-canonical fee recipient + gas limit (lockFeeRecipientAddresses/TargetGasLimit) into the VCs.This has independent, pre-gloas value — it makes VCs hold the correct fee recipient rather than relying on Charon's override — so it can land before the gloas duty.
Sub-task of the gloas epic #4324.
🛠️ Proposed solution
Findings
/eth/v1/validator/config, closed/contentious, not ratified), explicitly to kill the "different config dialect per client" burden it names for dappnode/eth-docker.proposer_configJSON:--proposer-settings-file/--validators-proposer-config/--proposerSettingsFile.<validators-dir>/<pubkey>/suggested_fee_recipient.hex+suggested_gas_limit.json.validator_definitions.yml(keystore-entangled; standalone fee-recipient file removed) or keymanager API.gas_limitbumps, which are applied staggered across operators):--Xvalidators-proposer-config-refresh-enabled, per epoch) and Nimbus (per-validator files read live). Prysm, Lodestar, Lighthouse require a restart to pick up a file change.Recommendation
Keymanager-API-primary — uniform across all clients, dynamic (no restart), durable (client persists it), and aligned with where the standard is heading — with optional file generation as a boot-time seed for operators who don't want to enable keymanager (documented as static / restart-to-change on Prysm/Lodestar/Lighthouse). Final mechanism choice is the first task below.
Tasks
pubkey → {fee_recipient (FeeRecipientAddresses), gas_limit (TargetGasLimit, with registration / 30M fallback)}POST /eth/v1/validator/{pubkey}/feerecipient+.../gas_limiton each configured VC; token config; reconcile on lock changeproposer_config.jsonin.charon/(create-if-missing + reconcile-on-lock-change); adapter (in CDVNrun.sh) to materialize Nimbus per-validator files from the same JSONcharonsubcommand to edit / sync the config across the cluster for user-error prevention — note a file edit needs a VC restart on Prysm/Lodestar/Lighthouse; keymanager path avoids this/eth/v1/validator/config) for future consolidation🔗 References
/eth/v1/validator/configproposal