Skip to content

kaiax/vrank: drop duplicate VRankCandidate before verifying it - #998

Open
hyunsooda wants to merge 1 commit into
kaiachain:devfrom
hyunsooda:fix/skip-verify-duplicate-vrank-candidate
Open

kaiax/vrank: drop duplicate VRankCandidate before verifying it#998
hyunsooda wants to merge 1 commit into
kaiachain:devfrom
hyunsooda:fix/skip-verify-duplicate-vrank-candidate

Conversation

@hyunsooda

@hyunsooda hyunsooda commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

The duplicate check for VRankCandidate sat after the BLS verification, so every replay paid for a pairing before being discarded — and a valid duplicate returns nil, so the peer is never dropped and can keep sending. It now runs right after the ECDSA recovery that produces the sender.

Types of changes

  • 🐛 Bug fix
  • ✨ Non-hardfork changes (node upgrade not required)
  • 💥 Hardfork / consensus-breaking changes
  • 🧪 Test improvements
  • 🧰 CI / build tool
  • ♻️ Chore / Refactor / Non-functional changes

Checklist

  • 📖 I have read the CONTRIBUTING GUIDELINES doc
  • 📝 I have signed in the PR comment I have read the CLA Document and I hereby sign the CLA in first time contribute after having read CLA
  • 🟢 Lint and unit tests pass locally with my changes ($ make test)

Related issues

Further comments

@hyunsooda hyunsooda self-assigned this Jul 28, 2026
ian0371
ian0371 previously approved these changes Jul 30, 2026
Only the first VRankCandidate per (block, round, sender) is kept, but the
duplicate check sat after the BLS verification, so every replay paid for a
pairing (~0.75ms) before being discarded. A ~200 byte packet therefore bought
that much CPU on each receiving validator, repeatable for as long as the peer
stayed connected: a valid duplicate returns nil, so node/cn never drops it.

Move the check up to right after the ECDSA recovery that produces the sender.
The stored message already passed both signature checks and a later one cannot
replace it, so re-verifying it decides nothing.

Constraint: the sender is only known after ECDSA recovery, so the check cannot
  move any earlier than that
Rejected: singleflight around the first verification | the race exists only for
  the first message of a view and is bounded by concurrentPerPeer=3
Rejected: cache of verified wire-message hashes | the (view, sender) check
  already subsumes byte-identical replays and saves the larger cost
Confidence: high
Scope-risk: narrow
Directive: this check must stay ahead of GetBlsPubkey/VerifySignature - the
  ordering is the fix, and collector state alone cannot detect a regression
Not-tested: a duplicate arriving concurrently with the first message on
  separate peer workers, which may still verify more than once
@hyunsooda
hyunsooda force-pushed the fix/skip-verify-duplicate-vrank-candidate branch from a08b59f to e49a4b9 Compare August 6, 2026 02:20
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.

4 participants