feat(aggregation): score interval-2 jobs like the block builder#526
feat(aggregation): score interval-2 jobs like the block builder#526MegaRedHand wants to merge 1 commit into
Conversation
🤖 Kimi Code ReviewOverall Assessment: High-quality PR. The refactoring correctly unifies scoring logic between block building and aggregation, fixes a critical chain-view bug for current-head attestations, and properly prevents XMSS double-inclusion. Good test coverage. Critical Consensus Correctness
Code Correctness & Edge Cases
Performance & Resource Management
Rust Best Practices
Code Structure
Minor Suggestions
Security Summary: No critical vulnerabilities introduced. The XMSS double-inclusion guard (Item 2) and chain-view fix (Item 1) are correctly implemented. The Approval: Approve with minor suggestion to handle duplicate validator IDs explicitly in Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code Review
I did not run tests locally: Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR adds value-based selection for interval-2 aggregation jobs. The main changes are:
Confidence Score: 4/5The interval-2 storage error path needs a fix before merging.
crates/blockchain/src/aggregation.rs
|
| Filename | Overview |
|---|---|
| crates/blockchain/src/aggregation.rs | Adds material resolution and greedy job selection, but a fallible block-root read can panic the actor. |
| crates/blockchain/src/block_builder.rs | Extracts shared coverage scoring while preserving proof-union scoring for block construction. |
| crates/blockchain/src/lib.rs | Routes interval-2 sessions through the new slot-aware aggregation selector. |
| crates/blockchain/Cargo.toml | Adds development dependencies used by the new aggregation tests. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Interval-2 aggregation trigger] --> B[Snapshot gossip and payload groups]
B --> C[Resolve raw signatures and child proofs]
C --> D[Build canonical chain view]
D --> E[Filter and score candidates]
E --> F{Candidate available and fewer than 3 jobs?}
F -- Yes --> G[Advance projected state]
G --> H[Add aggregation job]
H --> E
F -- No --> I[Run aggregation worker]
I --> J[Store produced payload]
J --> K[Delete represented gossip signatures]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Interval-2 aggregation trigger] --> B[Snapshot gossip and payload groups]
B --> C[Resolve raw signatures and child proofs]
C --> D[Build canonical chain view]
D --> E[Filter and score candidates]
E --> F{Candidate available and fewer than 3 jobs?}
F -- Yes --> G[Advance projected state]
G --> H[Add aggregation job]
H --> E
F -- No --> I[Run aggregation worker]
I --> J[Store produced payload]
J --> K[Delete represented gossip signatures]
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
crates/blockchain/src/aggregation.rs:299
**Block-Root Read Panics Actor**
When the storage backend fails while enumerating live block roots, this `expect` panics during the interval-2 actor path. A transient database read error can therefore terminate the node instead of skipping this optional aggregation session or returning an error.
Reviews (1): Last reviewed commit: "feat(aggregation): score interval-2 jobs..." | Re-trigger Greptile
| // against the current chain: aggregated attestations only reference | ||
| // existing blocks (head.slot / target.slot <= head_slot), so no | ||
| // empty-slot padding beyond the tip is needed. | ||
| let known_block_roots = store.get_block_roots().expect("block roots read works"); |
There was a problem hiding this comment.
When the storage backend fails while enumerating live block roots, this expect panics during the interval-2 actor path. A transient database read error can therefore terminate the node instead of skipping this optional aggregation session or returning an error.
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/blockchain/src/aggregation.rs
Line: 299
Comment:
**Block-Root Read Panics Actor**
When the storage backend fails while enumerating live block roots, this `expect` panics during the interval-2 actor path. A transient database read error can therefore terminate the node instead of skipping this optional aggregation session or returning an error.
How can I resolve this? If you propose a fix, please make it concise.2bb7ac7 to
0277f5c
Compare
0594893 to
26a262f
Compare
0277f5c to
607d19f
Compare
26a262f to
ee9e06e
Compare
The interval-2 session aggregated current-slot gossip groups in arbitrary order and ignored existing proofs, so it could not prioritize the groups whose aggregation most advances consensus. Rework snapshot_aggregation_inputs into a tiered greedy selector modeled on select_attestations: an up-front store pass resolves each candidate's material once (raw-first + trim), then a loop scores candidates by (current-slot-first, Finalize > Justify > Build) against an optimistically-projected state, emitting at most MAX_AGGREGATION_JOBS jobs. Candidates are filtered by the block builder's entry_passes_filters against a chain view covering [0, head_slot] (head root pushed onto the state's historical_block_hashes, which omits the head's own root), so prover time is spent only on aggregations a block could actually pack. Reuses the block builder's ProjectedState in full (from_head_state, advance, score_entry, and entry_passes_filters), so proposer and aggregator can never drift on the justify/finalize projection, candidate filtering, or tiering. The aggregator validates each candidate with projected.entry_passes_filters and scores its realized raw + child coverage with projected.score_entry. Deletes snapshot_current_slot_aggregation_inputs and build_raw_signature_job (subsumed). Builds on the block_builder refactor (ProjectedState owning projection + scoring).
ee9e06e to
630679e
Compare
What
Rework
snapshot_aggregation_inputsinto a tiered greedy selector modeled onthe block builder's
select_attestations: an up-front store pass resolves eachcandidate's aggregation material once (raw-first + trim), then a loop scores
candidates by (current-slot-first, Finalize > Justify > Build) against an
optimistically-projected state, emitting at most
MAX_AGGREGATION_JOBSjobs.Why
The interval-2 session aggregated current-slot gossip groups in arbitrary order
and ignored existing proofs, so it could not prioritize the groups whose
aggregation most advances consensus.
How
entry_passes_filtersagainst achain view covering
[0, head_slot](the head root is pushed onto the state'shistorical_block_hashes, which omits the head's own root), so prover time isspent only on aggregations a block could actually pack.
ProjectedState(from_head_state+advance) andTier/EntryScore/entry_passes_filtersvia a coverage-basedscore_from_coveragecore, so proposer and aggregator can never drift oneither the justify/finalize projection or the tiering.
snapshot_current_slot_aggregation_inputsandbuild_raw_signature_job(subsumed).Stacking
Stacked on #525 (the block builder refactor). Review/merge that first; GitHub
retargets this PR to
mainonce it lands.Checks
cargo fmtcleancargo clippy --all-targets -- -D warningscleancargo test -p ethlambda-blockchain --libgreen (incl. resolve_job / pick_best_candidate / snapshot tests)