Skip to content

fix: emit nothing for a proof-less vote and drop blocks the stage already holds - #46

Merged
adust09 merged 1 commit into
developfrom
fix/43-45-proofless-votes-and-dedup-20260911-1620
Sep 11, 2026
Merged

adust09 merged 1 commit into
developfrom
fix/43-45-proofless-votes-and-dedup-20260911-1620

Conversation

@adust09

@adust09 adust09 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Two defects found in the three-node devnet5 run behind #42, both now fixed with the failing case pinned by a test.

#43 — a vote with no proof no longer becomes an empty attestation

seed_block_votes files every vote a block carries into the counted pool with an empty proof set, on purpose (a block's merged proof is never split back per vote; leanSpec does the same). leanSpec's build_block emits one attestation per selected proof, so such a vote is marked processed and contributes nothing. Verity's select_votes instead pushed every eligible vote into the body, giving one attestation with no voters and an empty component list; the proposer's fold then handed leanVM nothing to aggregate and the slot's proposal was lost:

WARN block proof could not be built slot=39 error=cannot aggregate: aggregation failed: Nothing to aggregate: aggregated public keys is empty

select_votes now keeps a processed set apart from the selected groups: a vote whose coverage selection is empty is done with, counts against the distinct-vote budget, and emits nothing — leanSpec's shape. Two tests cover it: the proof-less vote alone, and a proof-less vote beside one that has a proof.

#45 — the verification stage drops what it already holds

The stage verified, and the chain task re-committed, every copy of a block that reached it: gossip plus a sync fetch, or two peers answering the same request. In the run, slot=25 and slot=37 were imported four times each (~90 ms of proof verification and a 230 KB proof write per copy). Now:

  • a decoded block whose root the current snapshot holds is dropped before the registry lookup;
  • an item identical to one already parked is not parked again (the first copy raised the gap);
  • chain.rs::import returns before the commit for a root the store already has — the window between the stage's snapshot and the import's own;
  • StageCounters::duplicates counts both, for verity-metrics to pick up.

Two stage tests exercise the first two paths over a genesis snapshot. The peer-churn half of #45 (ethlambda's QUIC drops while proving on the shared host) is a test-environment property and is not addressed here.

Validation

  • cargo fmt --all --check, cargo clippy --locked --workspace --all-targets -- -D warnings, cargo test --locked --workspace, cargo deny --locked check — all green.

Closes #43. Closes #45.

🤖 Generated with Claude Code

Two defects from the three-node devnet5 run behind #42.

build_block turned a block-carried vote — filed into the counted pool
with an empty proof set by seed_block_votes, as leanSpec does — into a
body attestation with no voters and an empty component list, and the
proposer's fold then gave leanVM nothing to aggregate, losing the slot's
proposal. leanSpec's builder emits one attestation per selected proof, so
a proof-less vote is processed and contributes nothing; select_votes now
keeps a processed set apart from the selected groups and does the same.

The verification stage verified, and the chain task re-committed, every
copy of a block that reached it (gossip plus sync fetches: up to four
imports of one slot in the run). A block the snapshot holds is dropped
before the registry lookup, an item already parked is not parked twice,
the import returns before the commit for a known root, and a duplicates
counter records both.

Closes #43. Closes #45.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@adust09
adust09 merged commit 7912736 into develop Sep 11, 2026
7 checks passed
@adust09
adust09 deleted the fix/43-45-proofless-votes-and-dedup-20260911-1620 branch September 11, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant