Skip to content
Merged
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
32 changes: 14 additions & 18 deletions crates/blockchain/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,17 +825,23 @@ pub fn produce_block_with_signatures(
)?
};

// Invariant (leanSpec #595): the produced block must not lag the store's
// justified checkpoint. Otherwise peers processing this block would never
// see justification advance, degrading liveness: the fixed-point loop in
// `build_block` is expected to incorporate pool attestations that close
// any divergence inherited from a minority fork.
// leanSpec #595: ideally the produced block should not lag the store's
// justified checkpoint, since peers processing it would not see
// justification advance, degrading liveness. The fixed-point loop in
// `build_block` is expected to incorporate pool attestations that close any
// divergence inherited from a minority fork, but it may not always
// converge. We still publish the block in that case (halting block
// production freezes the chain, which is worse) and only log the divergence.
let store_justified_slot = store.latest_justified().slot;
if post_checkpoints.justified.slot < store_justified_slot {
return Err(StoreError::JustifiedDivergenceNotClosed {
block_justified_slot: post_checkpoints.justified.slot,
warn!(
%slot,
proposer = validator_index,
block_justified_slot = post_checkpoints.justified.slot,
store_justified_slot,
});
"Produced block justified slot is behind store justified slot; \
fixed-point attestation loop did not converge"
);
}
Comment on lines 835 to 845

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Lagging Justification Still Publishes

When post_checkpoints.justified.slot stays behind store.latest_justified().slot, this path now publishes the block without changing the block or surfacing the divergence to the caller. The local import path only advances the store checkpoint on a higher justified slot, so repeated proposals in this state can keep producing blocks that do not close justification and leave finality stalled instead of making the failure actionable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/blockchain/src/store.rs
Line: 835-845

Comment:
**Lagging Justification Still Publishes**

When `post_checkpoints.justified.slot` stays behind `store.latest_justified().slot`, this path now publishes the block without changing the block or surfacing the divergence to the caller. The local import path only advances the store checkpoint on a higher justified slot, so repeated proposals in this state can keep producing blocks that do not close justification and leave finality stalled instead of making the failure actionable.

How can I resolve this? If you propose a fix, please make it concise.


metrics::observe_block_aggregated_payloads(signatures.len());
Expand Down Expand Up @@ -942,16 +948,6 @@ pub enum StoreError {

#[error("Block contains {count} distinct AttestationData entries; maximum is {max}")]
TooManyAttestationData { count: usize, max: usize },

#[error(
"Produced block justified slot {block_justified_slot} \
is behind store justified slot {store_justified_slot}; \
fixed-point attestation loop did not converge"
)]
JustifiedDivergenceNotClosed {
block_justified_slot: u64,
store_justified_slot: u64,
},
}

/// Full verification of a signed block's merged Type-2 proof.
Expand Down