In smart-contracts/ink/lib.rs:230-233, record_vote writes at :230, then on_quorum runs at :232, and clear_request only runs at :233 on success.
If the closure returns Err, the vote is persisted on a request that won't be cleared until expiry, and the validator can't re-vote in the meantime (AlreadyVoted).
Low-frequency in practice — on_quorum closures mostly re-check state that was already checked — but real, and the window grows with any future closure that can fail on post-quorum invariants.
Direction: either run on_quorum before recording the vote, or clear the request on error as well as success.
In smart-contracts/ink/lib.rs:230-233,
record_votewrites at:230, thenon_quorumruns at:232, andclear_requestonly runs at:233on success.If the closure returns
Err, the vote is persisted on a request that won't be cleared until expiry, and the validator can't re-vote in the meantime (AlreadyVoted).Low-frequency in practice —
on_quorumclosures mostly re-check state that was already checked — but real, and the window grows with any future closure that can fail on post-quorum invariants.Direction: either run
on_quorumbefore recording the vote, or clear the request on error as well as success.