feat: add support for masking on frontend#1140
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
WalkthroughAdds vote-masking end-to-end: client support (eligible-voter type, enclave API, random selection, masking/voting flows and UI), a utility for random voter selection, and server-side model/route/repo changes to persist and expose eligible token holders; indexer now stores eligible addresses during indexing. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DailyPoll as DailyPoll Component
participant VoteHook as useVoteCasting
participant Enclave as EnclaveServer
participant Utils as VoterUtils
participant Repo as ServerRepo
rect rgba(200,220,240,0.16)
Note over User,DailyPoll: Regular vote (no masking)
User->>DailyPoll: Click "Cast Vote" (isMasking=false)
DailyPoll->>VoteHook: castVoteWithProof(round_id, isMasking=false)
VoteHook->>VoteHook: handleVote() → sign, encrypt, gen_proof
VoteHook->>Enclave: broadcastVote / existing endpoints
Enclave-->>VoteHook: ack
VoteHook-->>DailyPoll: success
end
rect rgba(240,220,200,0.16)
Note over User,DailyPoll: Masking vote
User->>DailyPoll: Click "Mask vote" (isMasking=true)
DailyPoll->>VoteHook: castVoteWithProof(round_id, isMasking=true)
VoteHook->>Enclave: getEligibleVoters(round_id)
Enclave-->>VoteHook: EligibleVoter[]
VoteHook->>Utils: getRandomVoterToMask(EligibleVoter[])
Utils-->>VoteHook: selected EligibleVoter
VoteHook->>VoteHook: handleMask(selected) → sign masked, encrypt, gen_proof (isAMask)
VoteHook->>Enclave: broadcast masked vote
Enclave-->>VoteHook: ack
Note right of Repo: eligible addresses persisted earlier by indexer
VoteHook-->>DailyPoll: mask success
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (6)
examples/CRISP/client/src/utils/voters.ts (1)
14-18: Consider adding validation for empty voter array.The function assumes a non-empty
votersarray. If an empty array is passed, line 15 will perform a modulo operation with 0, potentially causing unexpected behavior.While the calling code in
useVoteCasting.ts(line 106) does check for empty arrays, adding a defensive check here would make this utility more robust for reuse.🔎 Proposed fix
export const getRandomVoterToMask = (voters: ElegibleVoter[]): ElegibleVoter => { + if (voters.length === 0) { + throw new Error('Voters array cannot be empty') + } const randomIndex = crypto.getRandomValues(new Uint32Array(1))[0] % voters.length return voters[randomIndex] }examples/CRISP/server/src/server/repo.rs (3)
7-12: Redundant import:TokenHolderis already available viasuper::models.Line 7 imports
TokenHolderfromcrate::server::models, but line 11 already imports fromsuper::models(which is the same module). You can remove the standalone import and addTokenHolderto the existing import group:🔎 Suggested consolidation
-use crate::server::models::TokenHolder; - use super::{ database::generate_emoji, - models::{CurrentRound, E3Crisp, E3StateLite, WebResultRequest}, + models::{CurrentRound, E3Crisp, E3StateLite, TokenHolder, WebResultRequest}, };
316-330: Remove stale placeholder comment.Line 318 contains
// Placeholder for future implementationbut the method is fully implemented. This comment is misleading and should be removed.🔎 Suggested fix
pub async fn set_elegible_addresses(&mut self, holders: Vec<TokenHolder>) -> Result<()> { let key = self.crisp_key(); - // Placeholder for future implementation self.store
146-146: Typo: "elegible" should be "eligible".The field name
elegible_addressescontains a typo. The correct spelling is "eligible". This typo is consistent across the PR (field names, method names, API endpoints), so fixing it would require coordinated changes. Consider addressing this before the API becomes established.examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (2)
47-54: Consider using a discriminated union or throwing for error handling.The
VoteDatainterface with an optionalerrorfield creates an awkward pattern where the caller must check for the error after receiving the result. Consider either:
- Throwing an error (and catching in
castVoteWithProof)- Using a discriminated union type for success/failure
The current approach works but the type doesn't enforce checking the error field before accessing other properties.
121-127: Type-unsafe cast: empty string to`0x${string}`.Casting an empty string to
`0x${string}`is incorrect since an empty string doesn't satisfy the0xprefix constraint. While this may work at runtime if the proof generation handles masks specially, consider using a more explicit sentinel value:🔎 Suggested fix
return { vote: { yes: 0n, no: 0n }, slotAddress: randomVoterToMask.address, balance: BigInt(randomVoterToMask.balance), signature: '', - messageHash: '' as `0x${string}`, + messageHash: '0x' as `0x${string}`, // Empty hash for mask votes }Similarly on line 167:
- messageHash: '' as `0x${string}`, + messageHash: '0x' as `0x${string}`,
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
examples/CRISP/client/src/hooks/enclave/useEnclaveServer.tsexamples/CRISP/client/src/hooks/voting/useVoteCasting.tsexamples/CRISP/client/src/model/vote.model.tsexamples/CRISP/client/src/pages/Landing/components/DailyPoll.tsxexamples/CRISP/client/src/utils/voters.tsexamples/CRISP/server/src/server/indexer.rsexamples/CRISP/server/src/server/models.rsexamples/CRISP/server/src/server/repo.rsexamples/CRISP/server/src/server/routes/state.rsexamples/CRISP/server/src/server/token_holders/etherscan.rsexamples/CRISP/server/src/server/token_holders/hashes.rs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ctrlc03
Repo: gnosisguild/enclave PR: 1109
File: examples/CRISP/server/src/server/routes/state.rs:33-37
Timestamp: 2025-12-19T11:35:43.204Z
Learning: In the CRISP voting system (examples/CRISP), ciphertext data and slot states are public and stored on-chain in the CRISPProgram smart contract. The server endpoints `/previous-ciphertext` and `/is-slot-empty` expose public blockchain data that can already be accessed by anyone through the contract's external view functions (getSlotIndex, isSlotEmptyByAddress) or by reading contract state directly. Authentication is not needed for these endpoints since they only expose data that is already publicly available on the blockchain.
📚 Learning: 2024-11-05T06:48:58.177Z
Learnt from: ryardley
Repo: gnosisguild/enclave PR: 173
File: packages/ciphernode/config/src/app_config.rs:13-21
Timestamp: 2024-11-05T06:48:58.177Z
Learning: In the `packages/ciphernode/config/src/app_config.rs` file, for the `Contract` enum, the team prefers to use `String` type for `address` fields, relying on parsing to handle validation, instead of using the `Address` type.
Applied to files:
examples/CRISP/server/src/server/models.rs
📚 Learning: 2024-10-08T19:45:18.209Z
Learnt from: ryardley
Repo: gnosisguild/enclave PR: 107
File: packages/ciphernode/sortition/src/distance.rs:1-1
Timestamp: 2024-10-08T19:45:18.209Z
Learning: In `packages/ciphernode/core/src/events.rs`, the import statements use the correct and updated `alloy::primitives` module.
Applied to files:
examples/CRISP/server/src/server/token_holders/hashes.rsexamples/CRISP/server/src/server/repo.rsexamples/CRISP/server/src/server/token_holders/etherscan.rs
🧬 Code graph analysis (4)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (4)
examples/CRISP/client/src/model/vote.model.ts (1)
Vote(59-62)examples/CRISP/client/src/hooks/enclave/useEnclaveServer.ts (1)
useEnclaveServer(34-56)examples/CRISP/client/src/utils/voters.ts (1)
getRandomVoterToMask(14-18)examples/CRISP/client/src/model/poll.model.ts (1)
Poll(32-36)
examples/CRISP/client/src/hooks/enclave/useEnclaveServer.ts (1)
examples/CRISP/client/src/model/vote.model.ts (1)
ElegibleVoter(64-67)
examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (1)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (1)
useVoteCasting(56-317)
examples/CRISP/client/src/utils/voters.ts (1)
examples/CRISP/client/src/model/vote.model.ts (1)
ElegibleVoter(64-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: build_sdk
- GitHub Check: build_crisp_sdk
- GitHub Check: rust_unit
- GitHub Check: build_enclave_cli
- GitHub Check: build_ciphernode_image
- GitHub Check: integration_prebuild
- GitHub Check: rust_integration
- GitHub Check: test_net
- GitHub Check: Build & Push Image
🔇 Additional comments (11)
examples/CRISP/server/src/server/token_holders/hashes.rs (1)
14-14: LGTM: Import path refactored to use centralized TokenHolder type.The import path has been updated to reference
TokenHolderfrom the centralizedmodelsmodule, which is consistent with the type relocation described in the PR changes.examples/CRISP/server/src/server/models.rs (1)
246-252: LGTM: TokenHolder struct is well-designed.The
TokenHolderstruct appropriately usesStringfor the balance field to preserve precision for large numbers, as noted in the doc comment. The derives are appropriate for this data structure.examples/CRISP/server/src/server/routes/state.rs (1)
326-344: Handler implementation looks correct (except for spelling).The implementation follows the established pattern for other endpoint handlers in this file with appropriate error handling and logging. The function name contains the same spelling error as the route path ("elegible" vs "eligible").
Note: Based on the retrieved learnings, this endpoint exposes data derived from public blockchain state (token holders), so authentication is not strictly required.
examples/CRISP/server/src/server/indexer.rs (1)
121-123: LGTM: Eligible addresses storage is correctly implemented.The repository mutation is appropriately placed before token holder hash computation, with proper error handling. The
clone()is necessary sincetoken_holdersis used again on line 126.Note: The method name contains the same spelling error ("elegible" vs "eligible") found throughout this PR.
examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (3)
33-33: LGTM: Improved state naming for clarity.Renaming
isLoadingtoisCastingVotemakes the loading state more explicit. AddingisMaskingenables proper UI state management for the new masking functionality.
67-74: LGTM: castVote function correctly handles masking parameter.The updated function signature properly passes the
isMaskingparameter tocastVoteWithProof, which handles the case wherepollSelectedcan be null during masking operations.
140-153: LGTM: Button implementation correctly handles masking workflow.The two buttons properly implement mutual exclusion:
- The vote button is disabled when masking is in progress
- The mask button is disabled when voting is in progress
- The mask button correctly doesn't require a poll selection (
noPollSelectednot in its disabled condition)The UI appropriately reflects the current operation state.
examples/CRISP/client/src/hooks/enclave/useEnclaveServer.ts (1)
31-31: LGTM: Endpoint implementation follows established patterns.The new
getElegibleVotersmethod correctly follows the same implementation pattern as other endpoint methods in this hook, with proper typing and API call structure.Note: The method and endpoint names contain the same spelling error ("elegible" vs "eligible") flagged in other files.
Also applies to: 43-44, 54-54
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (2)
105-128: Masking implementation looks correct.The
handleMaskfunction properly:
- Fetches eligible voters from the server
- Validates the response is non-empty
- Selects a random voter using cryptographically secure randomness
- Returns appropriate zero-value vote data for masking
The error handling for the API call correctly bubbles up to the outer catch block.
178-305: Well-structured masking/voting flow.The
castVoteWithProoffunction correctly:
- Guards
pollSelectedonly for non-mask votes- Separates masking and voting state flags
- Skips
markVotedInRoundfor masks (users can still vote after masking)- Provides differentiated success messages
- Properly resets both flags in the
finallyblockexamples/CRISP/server/src/server/token_holders/etherscan.rs (1)
12-18: Clean refactor:TokenHoldercentralized in models module.The import changes correctly:
- Remove
Serializefrom serde import since it's no longer needed locally- Import
TokenHolderfromcrate::server::modelswhere it's now centrally definedThis improves maintainability by having a single source of truth for the
TokenHoldertype.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (1)
98-103: Bug: resetVotingState doesn't reset isMasking flag.The
resetVotingStatefunction only resetsisVotingbut notisMasking. This could leave the UI in an inconsistent state if masking is cancelled or fails.🔎 Proposed fix
const resetVotingState = useCallback(() => { setVotingStep('idle') setLastActiveStep(null) setStepMessage('') setIsVoting(false) + setIsMasking(false) }, [])
♻️ Duplicate comments (1)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (1)
161-173: Duplicate toast notifications remain.The previously flagged issue with duplicate toast notifications is still present. When signature fails:
- Line 163 shows a toast
- Line 206-208 throws the error
- Lines 291-298 catch and show another toast
This results in two notifications for a single failure.
🧹 Nitpick comments (2)
examples/CRISP/client/src/utils/voters.ts (2)
15-15: Address modulo bias in random selection.Using modulo (
%) on random values introduces bias when the range doesn't evenly divide the random value space. For cryptographic randomness and fair selection, consider using rejection sampling.🔎 Proposed fix using rejection sampling
- const randomIndex = crypto.getRandomValues(new Uint32Array(1))[0] % voters.length + const max = Math.floor(0xFFFFFFFF / voters.length) * voters.length + let randomValue + do { + randomValue = crypto.getRandomValues(new Uint32Array(1))[0] + } while (randomValue >= max) + const randomIndex = randomValue % voters.length
17-17: Remove console.log or use proper logging.Production code should avoid
console.logstatements. Consider removing this or using a proper logging framework. Additionally, the message says "at index:" but logs the address instead of the index.🔎 Proposed fix
- console.log(`Selected random voter at index: ${voters[randomIndex].address}`) + // Remove or replace with proper loggingIf logging is needed:
- console.log(`Selected random voter at index: ${voters[randomIndex].address}`) + console.log(`Selected random voter at index ${randomIndex}: ${voters[randomIndex].address}`)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
examples/CRISP/client/src/hooks/voting/useVoteCasting.tsexamples/CRISP/client/src/pages/Landing/components/DailyPoll.tsxexamples/CRISP/client/src/utils/voters.ts
🧰 Additional context used
🧬 Code graph analysis (1)
examples/CRISP/client/src/utils/voters.ts (1)
examples/CRISP/client/src/model/vote.model.ts (1)
ElegibleVoter(64-67)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: build_sdk
- GitHub Check: build_enclave_cli
- GitHub Check: build_e3_support_dev
- GitHub Check: build_crisp_sdk
- GitHub Check: build_ciphernode_image
- GitHub Check: integration_prebuild
- GitHub Check: test_net
- GitHub Check: rust_unit
- GitHub Check: rust_integration
- GitHub Check: Build & Push Image
🔇 Additional comments (3)
examples/CRISP/client/src/pages/Landing/components/DailyPoll.tsx (1)
33-33: Well-structured masking UI integration.The masking flow is cleanly integrated with proper state management:
- Separate
isMaskingandisVotingflags provide clear UI feedback- The
castVotefunction correctly handles both masking and voting flows- Loading states and button disabling logic are comprehensive
- The new "Mask vote" button is properly wired
Also applies to: 67-74, 122-123, 142-153
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (2)
105-128: Verify masking vote data structure.The
handleMaskfunction returns aVoteDataobject with:
vote: { yes: 0n, no: 0n }(both zero)- Empty
signatureandmessageHashslotAddressset to a random eligible voter's addressPlease confirm this is the intended structure for masking operations, particularly the zero vote values and empty signature fields.
178-305: Well-refactored voting flow with clear separation of concerns.The refactoring successfully separates masking and voting logic:
handleMaskandhandleVoteare modular and focused- Error handling is comprehensive with proper state cleanup
- The
VoteDatainterface provides a clean contract between functions- User feedback differentiates between masking and voting operations
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
examples/CRISP/server/src/server/models.rs (1)
226-226: Spelling issue has been resolved.The past review flagged "elegible" as a typo, but the field is now correctly spelled as
eligible_addresses.examples/CRISP/server/src/server/routes/state.rs (1)
36-39: Spelling issue has been resolved.The past review flagged the route path as containing a typo ("/elegible-addresses"), but it is now correctly spelled as
/eligible-addresses.
🧹 Nitpick comments (3)
examples/CRISP/server/src/server/repo.rs (1)
316-335: Remove stale placeholder comment.The implementation is complete and follows the established patterns in the codebase. However, line 318 contains a misleading comment stating "Placeholder for future implementation" when the function is already fully implemented.
🔎 Proposed fix
pub async fn set_eligible_addresses(&mut self, holders: Vec<TokenHolder>) -> Result<()> { let key = self.crisp_key(); - // Placeholder for future implementation self.storeexamples/CRISP/client/src/hooks/voting/useVoteCasting.ts (2)
109-140: Restructure try-catch to cover all fallible operations.The try-catch block at lines 120-139 only wraps
getRandomVoterToMask, butgetEligibleVoters(line 114) and the empty-check (lines 116-118) can also fail. While these errors will be caught by the outer try-catch, the inconsistent error handling structure is confusing.🔎 Recommended fix
const handleMask = useCallback(async (): Promise<VoteData> => { if (!user || !roundState) { throw new Error('Cannot mask vote: Missing user or round state.') } + try { const eligibleVoters = await getEligibleVoters(roundState.id) if (!eligibleVoters || eligibleVoters.length === 0) { throw new Error('No eligible voters available for masking') } - try { const randomVoterToMask = getRandomVoterToMask(eligibleVoters) return { vote: { yes: 0n, no: 0n }, slotAddress: randomVoterToMask.address, balance: BigInt(randomVoterToMask.balance), signature: '', messageHash: '' as `0x${string}`, } - } catch (error) { + } catch (error) { return { vote: { yes: 0n, no: 0n }, slotAddress: '', balance: 0n, signature: '', messageHash: '' as `0x${string}`, error: (error as Error).message, } - } + } }, [user, roundState, getEligibleVoters])
173-184: Consider removing premature state reset on signature failure.When signature fails,
resetVotingState()at line 175 immediately resets the voting state to 'idle'. The error is then returned, thrown at line 217, caught at line 302, and the state is set to 'error' at line 303. This creates a brief UI flicker where the state transitions from 'signing' → 'idle' → 'error'.Additionally, the finally block at lines 311-312 redundantly sets
isVotingandisMaskingto false (already done byresetVotingStateat line 175).Note: The duplicate toast issue from the previous review appears to be resolved ✓—the toast has been removed from this function and is only shown once in the catch block.
💡 Optional: Let finally block handle cleanup
} catch (error) { console.log('User rejected signature or signing failed', error) - resetVotingState() return { signature: '', messageHash: '' as `0x${string}`, vote: { yes: 0n, no: 0n }, slotAddress: '', balance: 0n, error: 'User rejected signature or signing failed', } }This allows the error to propagate naturally and the finally block will handle cleanup, avoiding the intermediate 'idle' state.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
examples/CRISP/client/src/components/Cards/PollCardResult.tsxexamples/CRISP/client/src/hooks/enclave/useEnclaveServer.tsexamples/CRISP/client/src/hooks/voting/useVoteCasting.tsexamples/CRISP/client/src/model/vote.model.tsexamples/CRISP/client/src/utils/voters.tsexamples/CRISP/server/src/server/indexer.rsexamples/CRISP/server/src/server/models.rsexamples/CRISP/server/src/server/repo.rsexamples/CRISP/server/src/server/routes/state.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- examples/CRISP/server/src/server/indexer.rs
- examples/CRISP/client/src/utils/voters.ts
- examples/CRISP/client/src/model/vote.model.ts
- examples/CRISP/client/src/hooks/enclave/useEnclaveServer.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-05T06:48:58.177Z
Learnt from: ryardley
Repo: gnosisguild/enclave PR: 173
File: packages/ciphernode/config/src/app_config.rs:13-21
Timestamp: 2024-11-05T06:48:58.177Z
Learning: In the `packages/ciphernode/config/src/app_config.rs` file, for the `Contract` enum, the team prefers to use `String` type for `address` fields, relying on parsing to handle validation, instead of using the `Address` type.
Applied to files:
examples/CRISP/server/src/server/models.rsexamples/CRISP/server/src/server/routes/state.rs
🧬 Code graph analysis (2)
examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (5)
examples/CRISP/client/src/model/vote.model.ts (1)
Vote(59-62)examples/CRISP/packages/crisp-sdk/src/types.ts (1)
Vote(70-79)examples/CRISP/client/src/hooks/enclave/useEnclaveServer.ts (1)
useEnclaveServer(34-56)examples/CRISP/client/src/utils/voters.ts (1)
getRandomVoterToMask(14-22)examples/CRISP/client/src/model/poll.model.ts (1)
Poll(32-36)
examples/CRISP/server/src/server/routes/state.rs (2)
examples/CRISP/server/src/server/repo.rs (2)
store(38-40)store(81-83)crates/evm-helpers/src/event_listener.rs (1)
addresses(100-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: test_net
- GitHub Check: rust_integration
- GitHub Check: build_ciphernode_image
- GitHub Check: build_sdk
- GitHub Check: build_enclave_cli
- GitHub Check: build_crisp_sdk
- GitHub Check: integration_prebuild
- GitHub Check: Build & Push Image
- GitHub Check: rust_unit
🔇 Additional comments (7)
examples/CRISP/server/src/server/models.rs (1)
246-252: LGTM!The
TokenHolderstruct is well-designed with appropriate derives and clear documentation. UsingStringfor bothaddressandbalancealigns with team preferences and preserves precision for large numbers.examples/CRISP/server/src/server/repo.rs (2)
7-7: LGTM!The import correctly references the
TokenHoldertype from the models module.
146-146: LGTM!Initializing
eligible_addressesas an empty vector is consistent with the initialization pattern of other vector fields in the struct.examples/CRISP/server/src/server/routes/state.rs (1)
329-346: LGTM!The
handle_get_eligible_addresseshandler is well-implemented and follows the established patterns in this file. Error handling is consistent with other handlers, and the implementation correctly retrieves and returns eligible addresses as JSON.examples/CRISP/client/src/hooks/voting/useVoteCasting.ts (3)
318-327: LGTM: Clean API for masking and voting states.The hook now correctly exports
isVotingandisMaskingstates, allowing consumers to differentiate between masking and voting operations. The return object provides all necessary state and functions for the voting/masking workflow.
160-161: Add inline documentation clarifying the intentional one-person-one-vote semantics.The hardcoded
balance = 1non line 160 implements one-person-one-vote semantics. This is intentional: the SDK validation atvote.ts:213enforcesvote.yes ≤ balanceandvote.no ≤ balance, so a balance of1nconstrains each vote to0nor1nper option. The masking function (line 126) uses the actual voter's balance to preserve the masked voter's profile for privacy. This design choice is valid but should be documented with an inline comment explaining why balance is hardcoded for votes versus using the actual balance for masks. Consider:// One person, one vote: balance = 1n ensures each voter has exactly 1 vote weight. // (Masks use actual balance to preserve anonymity of the masked voter's profile.) const balance = 1n
123-129: The masking proof generation is correctly implemented. WhenisMasking=true, the worker callsgenerateMaskVoteProof()which uses hardcoded constants (MASK_SIGNATUREandSIGNATURE_MESSAGE_HASH) instead of the empty signature and message hash passed fromuseVoteCasting. The empty values are intentionally not used in the masking flow—only theslotAddressandbalancefrom the masked voter data are relevant for generating a masking proof.Likely an incorrect or invalid review comment.
fix #1128
Summary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.