Skip to content

chore: crisp fixes#1274

Merged
hmzakhalid merged 4 commits into
mainfrom
chore/crisp-compatibility-fixes
Feb 10, 2026
Merged

chore: crisp fixes#1274
hmzakhalid merged 4 commits into
mainfrom
chore/crisp-compatibility-fixes

Conversation

@ctrlc03

@ctrlc03 ctrlc03 commented Feb 6, 2026

Copy link
Copy Markdown
Collaborator

Small fixes in CRISP

Summary by CodeRabbit

  • New Features

    • Voting now supports multi-option elections with tallies as arrays.
    • Ballot decoding returns per-option big-integer counts with a bit-size cap.
  • Improvements

    • Dynamic handling of any number of options across client and server.
    • Unified tally representation replaced separate yes/no fields.
  • Bug Fixes

    • Enhanced transaction retry payload for committee finalization to include an additional condition code.
  • Tests

    • Integration timing window reduced for more stable test runs.

@vercel

vercel Bot commented Feb 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crisp Ready Ready Preview, Comment Feb 10, 2026 10:22am
enclave-docs Ready Ready Preview, Comment Feb 10, 2026 10:22am

Request Review

@coderabbitai

coderabbitai Bot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds multi-option tally support across CRISP (decoder, models, repo, indexer, client), renames a mock token deployment key, removes an unused import, and appends a ThresholdNotMet error code to the EVM registry finalizeCommittee retry payload.

Changes

Cohort / File(s) Summary
Multi-option voting (CRISP)
examples/CRISP/crates/crisp-utils/src/lib.rs, examples/CRISP/server/src/server/indexer.rs, examples/CRISP/server/src/server/models.rs, examples/CRISP/server/src/server/repo.rs, examples/CRISP/client/src/model/poll.model.ts, examples/CRISP/client/src/utils/methods.ts
Introduce MAX_VOTE_BITS; change decode_tally to decode_tally(tally_bytes, num_choices) -> Vec<BigUint>; add get_num_options(); change set_votes to accept Vec<BigUint>; replace per-option fields with tally: Vec<...> and update client access.
EVM Registry update
crates/evm/src/ciphernode_registry_sol.rs
Include extra error/condition code 0x59fa4a93 (ThresholdNotMet) in the finalize_committee_on_registry retry RPC payload parameters.
Deployment rename
examples/CRISP/packages/crisp-contracts/deploy/crisp.ts
Store mock token deployment args under MockVotingToken instead of MockCRISPToken.
Import cleanup
examples/CRISP/server/src/server/token_holders/etherscan.rs
Remove unused CONFIG import; minor formatting tweak.

Sequence Diagram(s)

sequenceDiagram
  participant EventSource as EventEmitter
  participant Indexer as Indexer
  participant Decoder as TallyDecoder
  participant Repo as CrispRepository
  participant Storage as DB

  EventSource->>Indexer: plaintextOutput event
  Indexer->>Repo: get_num_options()
  Repo-->>Indexer: num_choices
  Indexer->>Decoder: decode_tally(plaintextOutput, num_choices)
  Decoder-->>Indexer: Vec<BigUint> (vote counts)
  Indexer->>Repo: set_votes(Vec<BigUint>)
  Repo->>Storage: persist tally
  Repo-->>Indexer: ack
  Indexer->>Indexer: mark finished / log results
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested Reviewers

  • cedoor
  • hmzakhalid

Poem

🐰 I hopped through bits and packed them tight,
From halves to arrays in morning light.
BigUint nibblers count each cheer,
Tallies grow and hopged near and dear,
A tiny thump for ThresholdNotMet delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title 'chore: crisp fixes' is vague and generic, using non-descriptive language that fails to convey meaningful information about the substantial changes across multiple files and systems. Consider a more specific title that captures the main refactoring effort, such as 'refactor: generalize CRISP tally handling from binary to multi-choice voting' or similar, to better reflect the significant API changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/crisp-compatibility-fixes

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
examples/CRISP/server/src/server/models.rs (1)

160-168: Inconsistency: tally is now dynamic but emojis are still hardcoded to 2 options.

tally: Vec<String> supports N choices, yet option_1_emoji / option_2_emoji remain fixed to exactly two. Same for emojis: [String; 2] in E3, E3Crisp, and E3StateLite. If multi-option support is extended beyond the current 2-choice client, these fields will need to become dynamic too.

Not blocking since the client intentionally only supports 2-choice polls today. Based on learnings from ctrlc03 in PR #1262: "The CRISP client application in examples/CRISP/client is intentionally designed to only support 2-choice polls."

examples/CRISP/crates/crisp-utils/src/lib.rs (2)

151-161: Weak assertion: test only verifies "not equal" without checking specific behavior.

The test test_decode_tally_with_wrong_num_options asserts that results differ from the 2-choice expected values, but doesn't validate what the 3-choice decode actually produces or that an error is returned. Consider asserting a specific (deterministic) wrong result, or—if the intent is to catch misuse—validating that the function returns an error when values.len() % num_choices != 0 (once that check is added per the earlier review comment).


14-19: Remove unused VoteCounts struct.

The VoteCounts struct (lines 14-19) is no longer used since decode_tally returns Vec<BigUint> directly. Delete the struct definition.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
examples/CRISP/crates/crisp-utils/src/lib.rs (1)

21-33: ⚠️ Potential issue | 🟡 Minor

Stale doc comment — still describes the old yes/no decoding.

The doc comment references "yes votes in the first half and no votes in the second half" and a VoteCounts return type. Update it to reflect the new num_choices-based segmented decoding and Vec<BigUint> return.

🤖 Fix all issues with AI agents
In `@examples/CRISP/crates/crisp-utils/src/lib.rs`:
- Line 42: The division using let segment_size = values.len() / num_choices; can
silently drop trailing bytes when values.len() is not divisible by num_choices;
change the logic to validate divisibility first (check values.len() %
num_choices == 0) and return a meaningful error (or propagate one) instead of
proceeding, then compute segment_size only after the check; update the
surrounding function signature (e.g., return Result<...>) or error-handling path
that contains segment_size, values, and num_choices so callers receive a clear
error when the tally byte length is not evenly divisible.
🧹 Nitpick comments (2)
examples/CRISP/crates/crisp-utils/src/lib.rs (2)

80-90: Weak test: test_decode_tally_with_wrong_num_options only asserts inequality.

This test verifies the results differ from the 2-option case but doesn't validate what the correct behavior should be. With the divisibility check suggested above, this should instead assert that calling decode_tally with a mismatched num_choices returns an Err.

Proposed test update (assuming divisibility validation is added)
     #[test]
     fn test_decode_tally_with_wrong_num_options() {
-        // Expected: yes = 10000000000, no = 30000000000
         let tally_hex = "00000000000000000000000000000000..."; // same hex
 
         let bytes = hex::decode(tally_hex.strip_prefix("0x").unwrap_or(tally_hex)).unwrap();
-        let result = decode_tally(&bytes, 3).unwrap();
-
-        assert!(result[0] != BigUint::from(10000000000u64));
-        assert!(result[1] != BigUint::from(30000000000u64));
+        let result = decode_tally(&bytes, 3);
+        assert!(result.is_err(), "Expected error for indivisible tally length");
     }

14-19: Remove unused VoteCounts struct.

The VoteCounts struct (lines 14-19) is no longer used since decode_tally now returns Vec<BigUint>. Remove the struct definition and the stale doc comment referencing it (line 33).

Comment thread examples/CRISP/crates/crisp-utils/src/lib.rs
Comment thread examples/CRISP/crates/crisp-utils/src/lib.rs
cedoor
cedoor previously approved these changes Feb 9, 2026

@cedoor cedoor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

@hmzakhalid hmzakhalid enabled auto-merge (squash) February 10, 2026 10:22
@hmzakhalid hmzakhalid merged commit d43c577 into main Feb 10, 2026
26 of 27 checks passed
@ctrlc03 ctrlc03 deleted the chore/crisp-compatibility-fixes branch February 10, 2026 13:57
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.

3 participants