Skip to content

test: add test vector for block production with merging aggregates#897

Merged
tcoratger merged 4 commits into
leanEthereum:mainfrom
unnawut:builder-recursive-fold-vector
Jun 12, 2026
Merged

test: add test vector for block production with merging aggregates#897
tcoratger merged 4 commits into
leanEthereum:mainfrom
unnawut:builder-recursive-fold-vector

Conversation

@unnawut

@unnawut unnawut commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

🗒️ Description

Add a test vector that asserts if a block producer has 2 aggregates of the same message, they get merged successfully for block inclusion.

Since proof bytes are not deterministic, this vector checks that all attesters are accounted for in the produced block.

I was also trying to add split and merge but seems like it needs a leanVM commit bump so I'll defer that to later.

@unnawut unnawut added this to the pq-devnet-5 milestone Jun 9, 2026
@unnawut unnawut requested a review from tcoratger June 9, 2026 12:38
@tcoratger

Copy link
Copy Markdown
Collaborator

Thanks a lot, can you just rebase after #895 and follow the new doc writer conventions for the documentation of the test vectors just for uniformity? :)

Also I haven't checked in details but would be nice to ensure that this test doesn't already exist with the new coverage added in the PR.

@unnawut unnawut force-pushed the builder-recursive-fold-vector branch from a8a9f9e to 2d82838 Compare June 10, 2026 06:18
@unnawut unnawut marked this pull request as draft June 10, 2026 06:36
@unnawut

unnawut commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Accidentally pushed. I want to do a bit of touch up before marking for review again

@unnawut unnawut force-pushed the builder-recursive-fold-vector branch 4 times, most recently from 62810fc to 3219764 Compare June 10, 2026 07:22
…roofs

The block builder's collapse-by-data branch in build_block merges
multiple single-message aggregates for the same AttestationData via
SingleMessageAggregate.aggregate(children=..., raw_xmss=[]).  This is
the only proposal-time path that constructs a recursive single-message
aggregate, and no existing fork-choice vector reached it because the
local aggregator absorbs same-data proofs before block build time.

Gossiping two aggregated proofs with overlapping participant sets at
slot 2 interval 3 (past the aggregate phase) bypasses the local
aggregator, so both proofs migrate side by side into the known pool at
slot 2 interval 4.  The greedy picker takes both because the second
still adds one uncovered validator on top of the first, exercising
the merge branch on overlapping children rather than the unrealistic
fully disjoint shape.
@unnawut unnawut force-pushed the builder-recursive-fold-vector branch from 3219764 to 269529e Compare June 10, 2026 07:45
@unnawut unnawut marked this pull request as ready for review June 10, 2026 07:46
@unnawut

unnawut commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Also I haven't checked in details but would be nice to ensure that this test doesn't already exist with the new coverage added in the PR.

@tcoratger I checked and yep there's test_multiple_attestations_same_target_merge_into_one that's very similar, but it merges the leaf signatures, not a recursion. So I think this new one is still relevant because it's forcing 2 proof generation and then recurse them on the next block.

I've moved my new test into the same file as yours though (test_signature_aggregation.py) so they stay close together.

@tcoratger tcoratger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for adding this! 🙏 I went through it carefully and the scenario is really nicely constructed. The TickStep to slot 1 / interval 3 is a neat touch: it pushes the gossips past the aggregate phase so the two overlapping proofs land in the known pool unmerged, which is exactly what forces the recursive in-block fold — so this genuinely covers a different path from the leaf-merge sibling. 👍

Just a few small things below, mostly around the test-vector docstring conventions, plus one question about crypto coverage. Nothing blocking — feel free to push back on any of them. 🚀

Comment thread tests/consensus/lstar/fork_choice/test_signature_aggregation.py
Comment thread tests/consensus/lstar/fork_choice/test_signature_aggregation.py Outdated
Comment thread tests/consensus/lstar/fork_choice/test_signature_aggregation.py Outdated
Comment thread tests/consensus/lstar/fork_choice/test_signature_aggregation.py Outdated
@unnawut

unnawut commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

@tcoratger Applied your comments and re-reviewed. Please have another look! I'm still not too familiar with Given/When/Then format so feel free to guide me more

…old vector

Assert head identity (head_root_label) alongside head_slot so the Then
"head is block_2" claim is verified by root, not just slot.

Docstring: split the phase-glossing parenthetical and the two-fact head
bullet into one-fact-per-line bullets, and drop the Given gossip bullet
that duplicated the Timing section, per the consensus test-vector
documentation standard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tcoratger tcoratger merged commit 1937162 into leanEthereum:main Jun 12, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants