Simplify signature verification and document gossip counter safety#255
Simplify signature verification and document gossip counter safety#255pablodeymo merged 1 commit intomainfrom
Conversation
Combine validator ID collection, bounds checking, and public key lookup into a single pass in verify_all_signatures, eliminating an intermediate Vec allocation and a redundant iteration on the block verification hot path. Add a comment on gossip_signatures_count documenting that its read-then-write pattern in insert_gossip_signature is safe only because Store mutations are single-threaded (BlockChain actor). If concurrent writes are introduced, the counter update must be made atomic.
🤖 Claude Code ReviewThe PR is small and clean. Here's the review: PR Review: Simplify signature verification and document gossip counter safetyOverall: LGTM. Two focused improvements — a hot-path optimization and a safety comment. Both changes are correct and well-motivated. Change 1 — Single-pass validator bounds check + pubkey collection (
|
🤖 Codex Code ReviewNo findings. The functional change in store.rs looks correct: it still rejects out-of-bounds validator IDs before indexing The change in store.rs is comment-only. I could not run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR makes two small, independent improvements identified during a codebase review: a performance micro-optimisation in the hot-path signature verifier and a clarifying safety comment on a counter field.
The original
Confidence Score: 5/5Safe to merge — both changes are non-behavioural: a semantically equivalent iterator refactor and a documentation-only addition. No logic changes: the single-pass refactor produces the same errors in the same order and removes an allocation with no observable side effects. The comment addition has no runtime impact. No P0/P1 findings. No files require special attention.
|
| Filename | Overview |
|---|---|
| crates/blockchain/src/store.rs | Combines bounds check and public key collection into a single iterator pass in verify_signatures, removing one intermediate Vec<u64> allocation and one full iteration per attestation; logic is semantically identical to the original. |
| crates/storage/src/store.rs | Adds a documentation comment to the gossip_signatures_count field explaining its single-threaded safety assumption and the TOCTOU risk if concurrent writes are introduced; no behavioral change. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[verify_signatures called] --> B[For each attestation + proof pair]
B --> C{aggregation_bits == participants?}
C -- No --> D[Err: ParticipantsMismatch]
C -- Yes --> E[validator_indices iterator]
E --> F["For each vid (single pass)"]
F --> G{vid >= num_validators?}
G -- Yes --> H[Err: InvalidValidatorIndex]
G -- No --> I[validators vid .get_pubkey]
I --> J{Pubkey decoded?}
J -- No --> K[Err: PubkeyDecodingFailed]
J -- Yes --> L[Collect into public_keys Vec]
L --> M{More indices?}
M -- Yes --> F
M -- No --> N[verify_aggregated_signature]
N --> O{Valid?}
O -- No --> P[Err: AggregateVerificationFailed]
O -- Yes --> Q{More attestations?}
Q -- Yes --> B
Q -- No --> R[Verify proposer signature]
R --> S[Ok]
Reviews (1): Last reviewed commit: "Simplify signature verification and docu..." | Re-trigger Greptile
Resolve conflict in crates/storage/src/store.rs: keep in-memory gossip_signatures field (from this PR) over the gossip_signatures_count safety comment added in #255, since the AtomicUsize counter is no longer needed when gossip signatures live in-memory.
Motivation
Two findings from a full codebase review:
Redundant iteration in signature verification --
verify_all_signaturescollected all validator IDs into aVec, iterated it for bounds checking, then iterated it again to collect public keys. This runs on every block verification (hot path), allocating an unnecessary intermediateVec<u64>per attestation.Undocumented safety assumption on
gossip_signatures_count-- TheAtomicUsizecounter tracksGossipSignaturestable entries for Prometheus metrics. Theinsert_gossip_signaturemethod uses a read-then-write pattern (check if key exists, then conditionally increment) that has a TOCTOU gap. This is safe today because all Store mutations run on the BlockChain actor's single thread, but theArc<AtomicUsize>wrapping suggests the Store is designed to be shared -- making the assumption non-obvious to future contributors.Description
verify_all_signatures, removing oneVecallocation and one full iteration per attestationgossip_signatures_countfield documenting the single-threaded safety assumption and the risk if concurrent writes are ever introducedHow to Test
make test-- no behavioral change, all tests passmake lint-- clippy clean