Skip to content
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
372f9bc
chore: update minimal_config to latest spec
barnabasbusa Aug 20, 2025
cfac954
Merge branch 'unstable' into patch-3
barnabasbusa Aug 26, 2025
b5441a5
and slot component duration fn
eserilev Aug 26, 2025
63720c5
slot duration ms changes
eserilev Aug 26, 2025
8828d9d
cleanup
eserilev Aug 26, 2025
56f930a
Merge
eserilev Aug 26, 2025
17488cb
fixes
eserilev Aug 26, 2025
6bf8265
v1.6.0-alpha.5 test
eserilev Aug 26, 2025
6c4c9b6
Merge branch 'patch-3' into slot_duration_ms
eserilev Aug 26, 2025
aadc881
Resolve merge conflicts
eserilev Sep 25, 2025
5e76d27
Fix ci
eserilev Sep 25, 2025
5889b38
FMT
eserilev Sep 25, 2025
561040d
Merge conflicts
eserilev Oct 4, 2025
9dc3b8e
smol fixes
eserilev Oct 4, 2025
623705d
Smol fixes
eserilev Oct 4, 2025
55b9fee
Temp test fixes
eserilev Oct 6, 2025
389c536
Fix EF Tests
eserilev Oct 6, 2025
ea60804
Fix doppleganger test
eserilev Oct 6, 2025
f03a3c3
Fix test
eserilev Oct 7, 2025
d4c0407
Fix test
eserilev Oct 7, 2025
70aaeac
Fix doppleganger
eserilev Oct 7, 2025
a4a4410
Refactor
eserilev Oct 8, 2025
7241ceb
Refactor
eserilev Oct 8, 2025
7a88f4a
Fmt
eserilev Oct 8, 2025
d505a75
Fmt
eserilev Oct 8, 2025
7e0a964
Fix
eserilev Oct 8, 2025
78feefd
Refactor
eserilev Oct 8, 2025
c408057
Clean up
eserilev Oct 8, 2025
2ef43e7
Remove TODOs
eserilev Oct 8, 2025
429569e
Update more configs
eserilev Oct 9, 2025
3e67bec
Merge branch 'unstable' of https://github.com/sigp/lighthouse into sl…
eserilev Oct 14, 2025
d094781
Merge branch 'slot_duration_ms' of https://github.com/eserilev/lighth…
eserilev Oct 14, 2025
716f2ef
Fix test
eserilev Oct 14, 2025
d497942
Resolve merge conflicts
eserilev Nov 26, 2025
71e9d22
Fix basic sim bug
eserilev Nov 26, 2025
c01abed
Make slot duration calc panic safe
eserilev Nov 26, 2025
a45b987
Add TODO
eserilev Nov 26, 2025
2ce0a1a
Fix comment
eserilev Nov 26, 2025
4e2e3f4
Fix comment
eserilev Nov 26, 2025
85744e9
Add a test
eserilev Dec 3, 2025
460d534
Merge conflicts
eserilev Dec 3, 2025
6467a16
rerun
eserilev Dec 3, 2025
2888b4c
rerun
eserilev Dec 3, 2025
d2ee85c
fix
eserilev Dec 3, 2025
f40f651
Merge conflicts
eserilev Dec 8, 2025
61bfe48
Resolve merge conflicts
eserilev Jan 1, 2026
489021a
Default slot duration ms to seconds_per_slot if its missing
eserilev Jan 14, 2026
2096376
Fix
eserilev Jan 20, 2026
1cd0d1e
Fix
eserilev Jan 20, 2026
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
10 changes: 6 additions & 4 deletions account_manager/src/validator/exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<
let client = BeaconNodeHttpClient::new(
SensitiveUrl::parse(&server_url)
.map_err(|e| format!("Failed to parse beacon http server: {:?}", e))?,
Timeouts::set_all(Duration::from_secs(env.eth2_config.spec.seconds_per_slot)),
Timeouts::set_all(env.eth2_config.spec.get_slot_duration()),
);

let eth2_network_config = env
Expand Down Expand Up @@ -230,7 +230,7 @@ async fn publish_voluntary_exit<E: EthSpec>(
loop {
// Sleep for a slot duration and then check if voluntary exit was processed
// by checking the validator status.
sleep(Duration::from_secs(spec.seconds_per_slot)).await;
sleep(spec.get_slot_duration()).await;

let validator_data = get_validator_data(client, &keypair.pk).await?;
match validator_data.status {
Expand All @@ -251,7 +251,9 @@ async fn publish_voluntary_exit<E: EthSpec>(
eprintln!("Please keep your validator running till exit epoch");
eprintln!(
"Exit epoch in approximately {} secs",
(exit_epoch - current_epoch) * spec.seconds_per_slot * E::slots_per_epoch()
(exit_epoch - current_epoch)
* spec.get_slot_duration().as_secs()
* E::slots_per_epoch()
);
break;
}
Expand Down Expand Up @@ -350,7 +352,7 @@ fn get_current_epoch<E: EthSpec>(genesis_time: u64, spec: &ChainSpec) -> Option<
let slot_clock = SystemTimeSlotClock::new(
spec.genesis_slot,
Duration::from_secs(genesis_time),
Duration::from_secs(spec.seconds_per_slot),
spec.get_slot_duration(),
);
slot_clock.now().map(|s| s.epoch(E::slots_per_epoch()))
}
Expand Down
3 changes: 2 additions & 1 deletion beacon_node/beacon_chain/src/beacon_block_streamer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,8 @@ mod tests {
.execution_block_generator()
.move_to_terminal_block()
.expect("should move to terminal block");
let timestamp = harness.get_timestamp_at_slot() + harness.spec.seconds_per_slot;
let timestamp =
harness.get_timestamp_at_slot() + harness.spec.get_slot_duration().as_secs();
harness
.execution_block_generator()
.modify_last_block(|block| {
Expand Down
15 changes: 10 additions & 5 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4630,7 +4630,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// 1. It seems we have time to propagate and still receive the proposer boost.
// 2. The current head block was seen late.
// 3. The `get_proposer_head` conditions from fork choice pass.
let proposing_on_time = slot_delay < self.config.re_org_cutoff(self.spec.seconds_per_slot);
let proposing_on_time =
slot_delay < self.config.re_org_cutoff(self.spec.get_slot_duration());
if !proposing_on_time {
debug!(reason = "not proposing on time", "Not attempting re-org");
return None;
Expand Down Expand Up @@ -4920,7 +4921,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.and_then(|slot_start| {
let now = self.slot_clock.now_duration()?;
let slot_delay = now.saturating_sub(slot_start);
Some(slot_delay <= self.config.re_org_cutoff(self.spec.seconds_per_slot))
Some(slot_delay <= self.config.re_org_cutoff(self.spec.get_slot_duration()))
})
.unwrap_or(false)
} else {
Expand Down Expand Up @@ -5035,9 +5036,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.start_of(slot)
.unwrap_or_else(|| Duration::from_secs(0)),
);
block_delays
.observed
.is_some_and(|delay| delay >= self.slot_clock.unagg_attestation_production_delay())
block_delays.observed.is_some_and(|delay| {
delay
>= self
.spec
.get_unaggregated_attestation_due()
.unwrap_or_else(|_| Duration::from_secs(0))
})
}

/// Produce a block for some `slot` upon the given `state`.
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/src/bellatrix_readiness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
if let Some(bellatrix_epoch) = self.spec.bellatrix_fork_epoch {
let bellatrix_slot = bellatrix_epoch.start_slot(T::EthSpec::slots_per_epoch());
let bellatrix_readiness_preparation_slots =
BELLATRIX_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot;
BELLATRIX_READINESS_PREPARATION_SECONDS / self.spec.get_slot_duration().as_secs();

if self.execution_layer.is_some() {
// The user has already configured an execution layer, start checking for readiness
Expand Down
7 changes: 6 additions & 1 deletion beacon_node/beacon_chain/src/canonical_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.as_utf8_lossy(),
&self.slot_clock,
self.event_handler.as_ref(),
&self.spec,
);

if is_epoch_transition || reorg_distance.is_some() {
Expand Down Expand Up @@ -1329,6 +1330,7 @@ fn observe_head_block_delays<E: EthSpec, S: SlotClock>(
head_block_graffiti: String,
slot_clock: &S,
event_handler: Option<&ServerSentEventHandler<E>>,
spec: &ChainSpec,
) {
let Some(block_time_set_as_head) = slot_clock.now_duration() else {
// Practically unreachable: the slot clock's time should not be before the UNIX epoch.
Expand Down Expand Up @@ -1458,7 +1460,10 @@ fn observe_head_block_delays<E: EthSpec, S: SlotClock>(

// Determine whether the block has been set as head too late for proper attestation
// production.
let late_head = attestable_delay >= slot_clock.unagg_attestation_production_delay();
let late_head = attestable_delay
>= spec
.get_unaggregated_attestation_due()
.unwrap_or(block_delay_total);

// If the block was enshrined as head too late for attestations to be created for it,
// log a debug warning and increment a metric.
Expand Down
6 changes: 2 additions & 4 deletions beacon_node/beacon_chain/src/chain_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,9 @@ impl Default for ChainConfig {

impl ChainConfig {
/// The latest delay from the start of the slot at which to attempt a 1-slot re-org.
pub fn re_org_cutoff(&self, seconds_per_slot: u64) -> Duration {
pub fn re_org_cutoff(&self, slot_duration: Duration) -> Duration {
self.re_org_cutoff_millis
.map(Duration::from_millis)
.unwrap_or_else(|| {
Duration::from_secs(seconds_per_slot) / DEFAULT_RE_ORG_CUTOFF_DENOMINATOR
})
.unwrap_or_else(|| slot_duration / DEFAULT_RE_ORG_CUTOFF_DENOMINATOR)
}
}
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/src/data_availability_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ mod test {
let slot_clock = TestingSlotClock::new(
Slot::new(0),
Duration::from_secs(0),
Duration::from_secs(spec.seconds_per_slot),
spec.get_slot_duration(),
);
let kzg = get_kzg(&spec);
let store = Arc::new(HotColdDB::open_ephemeral(<_>::default(), spec.clone()).unwrap());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ impl<T: BeaconChainTypes> VerifiedLightClientFinalityUpdate<T> {
.slot_clock
.start_of(rcv_finality_update.signature_slot())
.ok_or(Error::SigSlotStartIsNone)?;
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);
let one_third_slot_duration = chain
.spec
.get_sync_message_due()
.map_err(|_| Error::Ignore)?;
if seen_timestamp + chain.spec.maximum_gossip_clock_disparity()
< start_time + one_third_slot_duration
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
.slot_clock
.start_of(rcv_optimistic_update.signature_slot())
.ok_or(Error::SigSlotStartIsNone)?;
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);

let one_third_slot_duration = chain
.spec
.get_sync_message_due()
.map_err(|_| Error::Ignore)?;

if seen_timestamp + chain.spec.maximum_gossip_clock_disparity()
< start_time + one_third_slot_duration
{
Expand Down
33 changes: 21 additions & 12 deletions beacon_node/beacon_chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,21 +503,26 @@ where
.expect("cannot recalculate fork times without spec");
mock.server.execution_block_generator().shanghai_time =
spec.capella_fork_epoch.map(|epoch| {
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
genesis_time
+ spec.get_slot_duration().as_secs() * E::slots_per_epoch() * epoch.as_u64()
});
mock.server.execution_block_generator().cancun_time = spec.deneb_fork_epoch.map(|epoch| {
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
genesis_time
+ spec.get_slot_duration().as_secs() * E::slots_per_epoch() * epoch.as_u64()
});
mock.server.execution_block_generator().prague_time =
spec.electra_fork_epoch.map(|epoch| {
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
genesis_time
+ spec.get_slot_duration().as_secs() * E::slots_per_epoch() * epoch.as_u64()
});
mock.server.execution_block_generator().osaka_time = spec.fulu_fork_epoch.map(|epoch| {
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
genesis_time
+ spec.get_slot_duration().as_secs() * E::slots_per_epoch() * epoch.as_u64()
});
mock.server.execution_block_generator().amsterdam_time =
spec.gloas_fork_epoch.map(|epoch| {
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
genesis_time
+ spec.get_slot_duration().as_secs() * E::slots_per_epoch() * epoch.as_u64()
});

self
Expand Down Expand Up @@ -562,7 +567,6 @@ where
let (shutdown_tx, shutdown_receiver) = futures::channel::mpsc::channel(1);

let spec = self.spec.expect("cannot build without spec");
let seconds_per_slot = spec.seconds_per_slot;
let validator_keypairs = self
.validator_keypairs
.expect("cannot build without validator keypairs");
Expand Down Expand Up @@ -607,7 +611,7 @@ where
builder.slot_clock(testing_slot_clock)
} else if builder.get_slot_clock().is_none() {
builder
.testing_slot_clock(Duration::from_secs(seconds_per_slot))
.testing_slot_clock(spec.get_slot_duration())
.expect("should configure testing slot clock")
} else {
builder
Expand All @@ -634,19 +638,24 @@ pub fn mock_execution_layer_from_parts<E: EthSpec>(
task_executor: TaskExecutor,
) -> MockExecutionLayer<E> {
let shanghai_time = spec.capella_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});
let cancun_time = spec.deneb_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});
let prague_time = spec.electra_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});
let osaka_time = spec.fulu_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});
let amsterdam_time = spec.gloas_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});

let kzg = get_kzg(&spec);
Expand Down
Loading