fix(simplex): retry certificate assembly after quorum - #4526
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b5690a0. Configure here.
| if let Some(finalization) = finalization { | ||
| self.finalize.complete(); | ||
| return Some(Certificate::Finalization(finalization)); | ||
| } |
There was a problem hiding this comment.
Pending votes stall after failed assembly
Medium Severity
Certificate recovery now leaves a kind Incomplete after vote-count quorum when assemble returns None, but should_verify still stops once verified reaches quorum. Later network votes stay in pending and never join the set that verified_quorum clones, so a retry cannot pick up the extra shares the scheme still needs.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit b5690a0. Configure here.
|
The fix correctly removes the panic, but should_verify still gates on verified >= quorum (verifier.rs L100-107). After a failed assembly, new votes arriving later stay stuck in pending and can never flow into the verified set to trigger a retry. The fix also needs should_verify to keep returning true while kind is still Incomplete, so shares that missed the initial quorum cutoff can still complete assembly. |
… stall When Scheme::assemble returns None despite a participant-count quorum (e.g. weighted schemes where minority participants meet the count but not the share threshold), try_construct_certificate used to panic via .expect() — and after PR commonwarexyz#4526, silently stall because try_complete() set state to Complete with no certificate, causing all subsequent votes to be dropped. Fix: - Add assembly_failed: bool to Certification<V> - Loosen try_complete() guard to allow re-attempts after failed assembly - Add revert_complete(votes) that resets state from Complete back to Incomplete and sets assembly_failed = true - Update should_verify() to return true when assembly_failed is set and pending votes exist, bypassing the participant-count quorum gate - Clone votes before the offload closure in try_construct_certificate so they can be restored on failure; call revert_complete() on None Closes commonwarexyz#4409. Supersedes commonwarexyz#4526.
… stall When Scheme::assemble returns None despite a participant-count quorum (e.g. weighted schemes where minority participants meet the count but not the share threshold), try_construct_certificate used to panic via .expect() — and after PR commonwarexyz#4526, silently stall because try_complete() set state to Complete with no certificate, causing all subsequent votes to be dropped. Fix: - Add assembly_failed: bool to Certification<V> - Loosen try_complete() guard to allow re-attempts after failed assembly - Add revert_complete(votes) that resets state from Complete back to Incomplete and sets assembly_failed = true - Update should_verify() to return true when assembly_failed is set and pending votes exist, bypassing the participant-count quorum gate - Clone votes before the offload closure in try_construct_certificate so they can be restored on failure; call revert_complete() on None Closes commonwarexyz#4409. Supersedes commonwarexyz#4526.
… stall When Scheme::assemble returns None despite a participant-count quorum (e.g. weighted schemes where minority participants meet the count but not the share threshold), try_construct_certificate used to panic via .expect() — and after PR commonwarexyz#4526, silently stall because try_complete() set state to Complete with no certificate, causing all subsequent votes to be dropped. Fix: - Add assembly_failed: bool to Certification<V> - Loosen try_complete() guard to allow re-attempts after failed assembly - Add revert_complete(votes) that resets state from Complete back to Incomplete and sets assembly_failed = true - Update should_verify() to return true when assembly_failed is set and pending votes exist, bypassing the participant-count quorum gate - Clone votes before the offload closure in try_construct_certificate so they can be restored on failure; call revert_complete() on None Closes commonwarexyz#4409. Supersedes commonwarexyz#4526.
… stall When Scheme::assemble returns None despite a participant-count quorum (e.g. weighted schemes where minority participants meet the count but not the share threshold), try_construct_certificate used to panic via .expect() — and after PR commonwarexyz#4526, silently stall because try_complete() set state to Complete with no certificate, causing all subsequent votes to be dropped. Fix: - Add assembly_failed: bool to Certification<V> - Loosen try_complete() guard to allow re-attempts after failed assembly - Add revert_complete(votes) that resets state from Complete back to Incomplete and sets assembly_failed = true - Update should_verify() to return true when assembly_failed is set and pending votes exist, bypassing the participant-count quorum gate - Clone votes before the offload closure in try_construct_certificate so they can be restored on failure; call revert_complete() on None Closes commonwarexyz#4409. Supersedes commonwarexyz#4526.


Fixes #4409
Certificate recovery currently treats vote-count quorum as sufficient for certificate assembly. Some certificate schemes may still return
Nonefromassemble()at that point, which causes the batcher to panic and discard the verified votes.This keeps verified votes buffered until assembly actually succeeds. If assembly returns
None, later verified votes can trigger another recovery attempt.Changes:
Validation:
cargo test -p commonware-consensuscargo clippy -p commonware-consensus --all-targets -- -D warningsgit diff --check