Simplify block production (leanSpec PR #464)#251
Conversation
…leanSpec PR #464) Rewrite build_block() to filter and select proofs directly from a payload map keyed by data_root, eliminating the round-trip of extracting individual attestations from aggregated payloads, filtering them, then re-aggregating. This matches the simplified approach in leanSpec. Key changes: - Add PayloadBuffer::grouped_by_data_root() for proof deduplication - Replace aggregate_attestations_by_data() + select_aggregated_proofs() with extend_proofs_greedily() greedy set-cover selection - Simplify produce_block_with_signatures() to resolve AttestationData per data_root instead of reconstructing per-validator attestations - Route own aggregation output directly to known_payloads (immediately usable for block building) instead of going through new -> known
🤖 Codex Code Review
I did not run the test suite: Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewHere is the review: Review: Simplify block production (leanSpec PR #464)The refactoring is well-motivated and the logic is substantially cleaner. The core ideas are sound. A few observations below. Non-determinism in
|
Motivation
leanSpec PR #464 ("simplify block production") rewrites
build_block()to work directly with aggregated payloads keyed byAttestationDatainstead of individualAttestationobjects. This eliminates an unnecessary round-trip: the old approach extracted individual attestations from aggregated payloads, filtered them, then re-aggregated. The new approach filters and selects proofs directly from the payload map.Spec PR: leanEthereum/leanSpec#464
Description
Storage layer (
crates/storage/src/store.rs)PayloadBuffer::grouped_by_data_root()— New method that groups buffer entries bydata_root(the tree hash root ofAttestationData), deduplicating proofs by comparing their participant bitfield bytes. ReturnsHashMap<H256, Vec<AggregatedSignatureProof>>.Store::known_payloads_by_data_root()— Public wrapper exposing the grouped payloads to the blockchain crate.AggregatedSignatureProofto the import list.Blockchain layer (
crates/blockchain/src/store.rs)New:
extend_proofs_greedily()Greedy set-cover algorithm that selects proofs maximizing new validator coverage for a given attestation data entry. Each selected proof produces one
AggregatedAttestationin the block body. This replaces bothaggregate_attestations_by_data()andselect_aggregated_proofs().Rewritten:
build_block()Before: Took
&[Attestation](individual per-validator attestations) and aHashMap<SignatureKey, Vec<AggregatedSignatureProof>>keyed by(validator_id, data_root). Used a fixed-point loop to collect individual attestations, then calledaggregate_attestations_by_data()to group them, thenselect_aggregated_proofs()to find proofs. Returned(Block, State, Vec<AggregatedSignatureProof>).After: Takes
HashMap<H256, (AttestationData, Vec<AggregatedSignatureProof>)>keyed bydata_root. Sorts entries bytarget.slotfor deterministic order, filters by known block roots and source checkpoint match, then callsextend_proofs_greedily()directly. Handles genesis edge case (slot 0 justified root = parent_root). Loops when justification advances to unlock attestation data with new source checkpoints. Returns(Block, Vec<AggregatedSignatureProof>).Simplified:
produce_block_with_signatures()Before: Called
iter_known_aggregated_payloads(), thenextract_latest_attestations()to reconstruct per-validatorAttestationobjects, then re-keyed the payloads bySignatureKeyforbuild_block().After: Calls
known_payloads_by_data_root()to get deduplicated proofs grouped by data_root, resolvesAttestationDatafor each viaget_attestation_data_by_root(), and passes the result directly tobuild_block().Routing change:
aggregate_committee_signatures()Own aggregation output now goes directly to
known_payloads(immediately usable for block building and fork choice) instead ofnew_payloads. Gossip-received aggregated attestations still go throughnew -> knownpromotion at intervals 0/4.Deleted
aggregate_attestations_by_data()— Functionality absorbed intoextend_proofs_greedily()select_aggregated_proofs()— Functionality absorbed intoextend_proofs_greedily()Backward Compatibility
produce_block_with_signatures()same signature and return type.on_gossip_attestation,on_gossip_aggregated_attestation,on_block_coreunchanged.extract_latest_attestationsand related methods unchanged.How to Test
For full validation:
make run-devnetwith--is-aggregator: verify blocks contain attestations, justified_slot and finalized_slot advance.claude/skills/test-pr-devnet/scripts/test-branch.sh