diff --git a/crates/blockchain/src/lib.rs b/crates/blockchain/src/lib.rs index 168282ba..e2a32b1d 100644 --- a/crates/blockchain/src/lib.rs +++ b/crates/blockchain/src/lib.rs @@ -230,20 +230,7 @@ impl BlockChainServer { let is_aggregator = self.aggregator.is_enabled(); metrics::set_is_aggregator(is_aggregator); - // At interval 0, check if we will propose (but don't build the block yet). - // Tick forkchoice first to accept attestations, then build the block - // using the freshly-accepted attestations. - let scheduled_proposer = (interval == 0 && slot > 0) - .then(|| self.get_our_proposer(slot)) - .flatten(); - let proposer_validator_id = - scheduled_proposer.filter(|_| self.sync_status.duties_allowed()); - - if let Some(validator_id) = scheduled_proposer - && proposer_validator_id.is_none() - { - info!(%slot, %validator_id, "Skipping block proposal while syncing"); - } + // ==== interval 4 (pre-tick) ==== // Snapshot the pre-merge `new_payloads` set at the end-of-slot promote // (interval 4), so the post-block report for this round sees its @@ -262,29 +249,26 @@ impl BlockChainServer { self.pre_merge_coverage = Some(snapshot); } + let scheduled_proposer = (interval == 0 && slot > 0) + .then(|| self.get_our_proposer(slot)) + .flatten(); + let is_proposer = scheduled_proposer.is_some(); + // Tick the store first - this accepts attestations at interval 0 if we have a proposal - store::on_tick( - &mut self.store, - timestamp_ms, - proposer_validator_id.is_some(), - ); + store::on_tick(&mut self.store, timestamp_ms, is_proposer); - if interval == 2 { - if is_aggregator { - coverage::emit_agg_start_new_coverage( - &self.store, - self.attestation_committee_count, - ); - self.start_aggregation_session(slot, ctx).await; + // ==== interval 0 ==== + + // Now build and publish the block (after attestations have been accepted) + if let Some(validator_id) = scheduled_proposer { + if self.sync_status.duties_allowed() { + self.propose_block(slot, validator_id); } else { - metrics::inc_aggregator_skipped_not_aggregator(); + info!(%slot, %validator_id, "Skipping block proposal while syncing"); } } - // Now build and publish the block (after attestations have been accepted) - if let Some(validator_id) = proposer_validator_id { - self.propose_block(slot, validator_id); - } + // ==== interval 1 ==== // Produce attestations at interval 1 (all validators including proposer). // Reuse the same snapshot so self-delivery decisions match the rest @@ -309,6 +293,28 @@ impl BlockChainServer { } } + // ==== interval 2 ==== + + if interval == 2 { + if is_aggregator { + coverage::emit_agg_start_new_coverage( + &self.store, + self.attestation_committee_count, + ); + self.start_aggregation_session(slot, ctx).await; + } else { + metrics::inc_aggregator_skipped_not_aggregator(); + } + } + + // ==== interval 3 ==== + + // Interval 3 (safe-target update) is handled inside `store::on_tick`. + + // ==== interval 4 ==== + + // Handled by the pre-tick snapshot above. + // Update safe target slot metric (updated by store.on_tick at interval 3) metrics::update_safe_target_slot(self.store.safe_target_slot()); // Update head slot metric (head may change when attestations are promoted at intervals 0/4)