Repository navigation
Open
Description
The validator client has only been run with a handful of keys. Nothing measures what it costs per slot, per epoch or at startup with thousands of them, which is where several of its designs would show it first.
This came up in the review of #707: PreferencesService takes its sent lock once per proposer duty instead of once per poll (crates/validator/src/preferences.rs). That is harmless at the few proposals an epoch holds, but it is one example of a per-key cost nobody has measured.
What grows with the number of keys
These are read from the code, not measured:
- Startup.
ValidatorStore::loaddecrypts the keystores one after another (keys/store.rs). With EIP-2335's default scrypt parameters each one takes a noticeable fraction of a second, so 10,000 keys could take a long time before the first duty. - Slashing protection. Each
commitre-renders the whole interchange file with every key's record, then writes it durably: a temporary file, an fsync, a rename and a directory fsync (slashing_protection/file.rswrite). A slot's attestations are batched into one commit, so the commit itself is one per slot rather than one per key. Its size still grows with the number of keys, and it sits in front of every attestation signature.time_slashing_protection_writealready records how long it takes. - Builder registrations (fulu and earlier, with
--builder-proposals).- The first epoch signs one BLS signature per key on the blocking pool, 64 per chunk.
- Every epoch then sends every registration in batches of 500.
- A per-slot keymanager change waits behind that send. Against a slow node, that is at most 12 s per 500 validators (
registration.rsmodule doc).
- Epoch refresh.
validator_indicesPOSTs every loaded pubkey every epoch, andprepare_beacon_proposersends one entry per resolved key. - Per-slot duties. Attestations, aggregation selection and sync committee messages are signed for every key with a duty in the slot.
Proposal
- A scale test or benchmark. It would drive the services against
MockBeaconNodewith, for example, 1,000 and 10,000 keys over a few epochs.- The keys would use the small-integer secrets from
test_state::secret_key_for, so no keystore has to be decrypted. - It would measure the duty path's time per slot, the slashing-protection write time, the registration send's length and memory.
- The keys would use the small-integer secrets from
- A separate startup measurement with real scrypt keystores.
- A devnet run with a large key set behind one validator client, to see the same costs against a real beacon node.
- Decide from the numbers whether anything needs changing first: parallel keystore decryption, or an incremental slashing-protection store in place of rewriting the whole file every commit.
Metadata
Metadata
Assignees
Labels
No labels
Activity