Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -846,8 +846,10 @@ transitions are in `ethlambda-types`, per the section above. Nothing above
aggregate when `verified_sync_aggregate` fails (see `docs/spec_deviations.md`).
`SlotClock` picks the
offsets by each slot's own fork, and `/eth/v1/config/spec` supplies them. It
still keeps no slashing-protection record; PTC votes have an in-memory
`(validator, slot)` dedup only, and envelopes are unguarded.
keeps EIP-3076 minimal-watermark slashing protection in
`--validators-dir/slashing_protection.json` (`crate::slashing_protection`),
durable before every block and attestation signature; PTC votes have an
in-memory `(validator, slot)` dedup only, and envelopes are unguarded.
`get_head_node` is one bottom-up walk for every fork, with
the current slot's fork selecting the payload rules and the boost gate, so a
follower on any network that schedules gloas (Sepolia does) pays work
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,13 +332,14 @@ payload envelope and the payload timeliness vote. It talks to a beacon node over
the standard Beacon API, so it works against `ethlambda beacon` (run with the
`--execution-*` flags) or any other conformant beacon node.

> **Warning:** the validator client keeps no slashing-protection record yet.
> Slashing protection is a work in progress and will be added soon. Until then,
> do not run the same keys in another client while this one runs, and treat a
> restart with the same care as a manual key move. Read
> [Spec deviations](./docs/spec_deviations.md#the-validator-client-keeps-no-slashing-protection-record)
> before using keys that hold real stake. The client repeats this warning at
> startup.
> **Slashing protection:** every block and attestation is checked against a
> durable per-validator record in `--validators-dir` before it is signed, and a
> second validator client pointed at the same directory refuses to start. A key
> with no record is refused at startup: pass `--init-slashing-protection` once,
> and only for keys that have signed nothing anywhere for at least two epochs.
> Importing history from another client is not supported yet, so never run
> these keys in another client at the same time. See
> [Spec deviations](./docs/spec_deviations.md#the-validator-client-keeps-eip-3076s-minimal-watermarks-not-full-history).

```sh
./target/release/ethlambda validator \
Expand Down
15 changes: 15 additions & 0 deletions bin/ethlambda/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ pub(crate) struct ValidatorOptions {
/// beyond localhost must front it with TLS.
#[arg(long, default_value = "false")]
pub(crate) enable_keymanager: bool,

/// Register every loaded key that has no slashing-protection record,
/// instead of refusing to start.
///
/// DANGEROUS. Use it only for keys that are brand new, or that have signed
/// nothing anywhere for at least two epochs. A key is registered as if it
/// had signed a block and an attestation at the current slot and epoch,
/// which closes the double-vote window for a key that signed a moment ago
/// elsewhere, but not a surround vote against older history. Keys that
/// already have a record keep it, so the flag never lowers one; remove it
/// once the keys are registered.
#[arg(long, default_value = "false")]
pub(crate) init_slashing_protection: bool,
}

impl ValidatorOptions {
Expand Down Expand Up @@ -154,6 +167,7 @@ pub(crate) async fn run(options: ValidatorOptions) -> eyre::Result<()> {
keymanager: options
.enable_keymanager
.then(|| std::net::SocketAddr::new(options.http_address, options.keymanager_port)),
init_slashing_protection: options.init_slashing_protection,
})
.await
.map_err(Into::into)
Expand All @@ -174,6 +188,7 @@ mod tests {
graffiti: graffiti.to_string(),
suggested_fee_recipient: None,
enable_keymanager: false,
init_slashing_protection: false,
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/net/rpc/src/beacon/validator_client_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,7 @@ mod gloas {
None,
),
),
ethlambda_validator::slashing_protection::SlashingProtection::in_memory(),
);
let duty = ProposerDutyDto {
pubkey: encode_hex(&pubkey.0),
Expand Down Expand Up @@ -1606,6 +1607,7 @@ mod gloas {
None,
),
),
ethlambda_validator::slashing_protection::SlashingProtection::in_memory(),
);
let duty = ProposerDutyDto {
pubkey: encode_hex(&pubkey.0),
Expand Down
9 changes: 5 additions & 4 deletions crates/validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ serde_yaml_ng.workspace = true
hex.workspace = true
thiserror.workspace = true
tracing.workspace = true
# `time` for the duty loop's sleep between slots. Declared here rather than
# relied on through workspace feature unification, so this crate still builds
# if it is ever compiled on its own.
tokio = { workspace = true, features = ["time", "macros"] }
# `time` for the duty loop's sleep between slots, `rt` for `spawn_blocking`,
# which keeps the slashing-protection record's disk flush off the executor.
# Declared here rather than relied on through workspace feature unification,
# so this crate still builds if it is ever compiled on its own.
tokio = { workspace = true, features = ["time", "macros", "rt"] }
reqwest = { workspace = true, features = ["json"] }

# BLS12-381. Same version and backend the state transition verifies with, so a
Expand Down
Loading
Loading