Skip to content
Open
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
68 changes: 37 additions & 31 deletions crates/blockchain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down