feat(blockchain): cap attestations packed per built block - #486
Conversation
Add --max-attestations-per-block (default 3) to bound how many distinct AttestationData entries a proposer packs into a block it builds. This is a proposer-side self-limit only: the consensus cap for accepting peers' blocks stays at MAX_ATTESTATIONS_DATA, and the configured value is clamped to it so we never build a block that peers would reject. Group the new knob with the existing enable_proposer_aggregation flag into a ProposerConfig struct, since build_block otherwise exceeds clippy's argument limit.
🤖 Kimi Code ReviewThe PR is well-structured and correct. The proposer-side self-limit is safely implemented and cannot affect consensus. Code Quality & Correctness
Testing
Minor Observations
Security Assessment
Verdict: Approved. The implementation correctly adds a proposer-side configuration without touching consensus validation logic. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code ReviewFindings
The rest of the plumbing from CLI to I could not run the targeted Rust test locally because Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR adds a proposer-side cap for attestations packed into locally built blocks. The main changes are:
Confidence Score: 4/5The changed flow is mostly safe, but the new CLI option allows a zero value that disables attestation packing.
bin/ethlambda/src/cli.rs
|
| Filename | Overview |
|---|---|
| bin/ethlambda/src/cli.rs | Adds the new CLI flag, but leaves the lower bound unconstrained. |
| bin/ethlambda/src/main.rs | Passes the parsed attestation cap into blockchain startup. |
| crates/blockchain/src/lib.rs | Stores the proposer cap and forwards it when proposing blocks. |
| crates/blockchain/src/store.rs | Builds ProposerConfig and passes it into block construction. |
| crates/blockchain/src/block_builder.rs | Applies the configured cap to attestation selection and adds regression coverage. |
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
bin/ethlambda/src/cli.rs:108-109
**Zero Limit Drops Attestations**
When the node is started with `--max-attestations-per-block 0`, this unconstrained `usize` reaches `select_attestations` and makes the new loop bound `0..0`. The proposer then signs and publishes a valid block with no attestations even when eligible payloads exist, silently removing all local attestation contribution from that slot.
```suggestion
#[arg(long, default_value = "3", value_parser = clap::value_parser!(usize).range(1..))]
pub(crate) max_attestations_per_block: usize,
```
Reviews (1): Last reviewed commit: "feat(blockchain): cap attestations packe..." | Re-trigger Greptile
🤖 Claude Code ReviewReview:
|
Hold the proposer policy as a single ProposerConfig field on BlockChainServer and thread it through produce_block_with_signatures, instead of carrying enable_proposer_aggregation and max_attestations_per_block as loose fields reassembled at the call site. spawn stays the CLI-to-actor seam and keeps taking the raw primitives. ProposerConfig becomes pub since the public produce_block_with_signatures now takes it.
Now that ProposerConfig is public, BlockChain::spawn takes it directly instead of the two raw primitives, and main.rs assembles it from the CLI options. Drops spawn to six arguments and keeps the proposer policy as one object end to end.
Summary
Adds a
--max-attestations-per-blockCLI flag (default 3) that bounds how many distinctAttestationDataentries a proposer packs into a block it builds.This is a proposer-side self-limit only. The consensus cap for accepting peers' blocks is unchanged (
store.rsstill rejects> MAX_ATTESTATIONS_DATA), so interop is preserved: other clients may still legally send up toMAX_ATTESTATIONS_DATAentries and we accept them. The configured value is clamped toMAX_ATTESTATIONS_DATAduring selection, so we never build a block that peers would reject.Since compaction collapses proofs to one entry per
AttestationData, the limit equals the number of attestations in the built block (default 3).Changes
bin/ethlambda/src/cli.rs--max-attestations-per-blockflag (default 3)bin/ethlambda/src/main.rsBlockChain::spawncrates/blockchain/src/lib.rsspawnparam,BlockChainServerfield, pass at proposal timecrates/blockchain/src/store.rsproduce_block_with_signaturesbuilds aProposerConfigcrates/blockchain/src/block_builder.rsProposerConfigstruct; selection loop capped atN.min(MAX_ATTESTATIONS_DATA); new regression testProposerConfiggroups the new limit with the existingenable_proposer_aggregationflag: without it,build_blockexceeds clippy'stoo_many_arguments(8/7) limit.Testing
cargo clippy -p ethlambda-blockchain -p ethlambda --all-targets -- -D warnings— cleancargo fmt --all -- --check— cleancargo test -p ethlambda-blockchain --lib— 40/40 pass, including the newbuild_block_respects_configured_attestation_limit(proves the limit binds belowMAX_ATTESTATIONS_DATA)Spec-test suites (
forkchoice_spectests, etc.) were not run locally: they require theleanSpec/fixturesdirectory, which is not present in this worktree. They are unaffected by this change.