Feat/protocol voting - #2
Merged
Merged
Conversation
…tion
First piece of protocol voting (coinholder polling). Pure, testable core with no
wallet/network dependency:
- poll_hash(bytes): hex SHA-256 of the ballot definition as published (hashes raw
bytes, never a re-serialized copy, so it matches the publisher's hash).
- VoteEntry { Abstain | Choice(idx) | FreeForm(s) } serializing to the exact v1
wire shapes (null / number / string).
- validate_votes: enforces one answer per question, in-range indices, and
free-form only where allowed (a malformed memo counts as all-abstain on-chain).
- encode_vote_memo: builds the v1 memo JSON and refuses over the 512-byte limit.
- BallotQuestion: lenient parse to drive the UI and derive QuestionShape, kept
independent of the still-finalizing ballot schema.
Casting will reuse the existing shielded-send + FROST path. 7 unit tests pass.
Open decision: v1 weights by a TRANSPARENT-balance snapshot; a shielded FROST
treasury needs the shielded-weighting poll variant to carry weight.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
prepare_vote validates the votes, computes the ballot poll-hash, encodes the Vote Cast Memo v1, and builds a shielded payment carrying that memo to the poll's reception Z-address — returning the same DraftTransaction a normal send does, so the existing FROST signing + broadcast path casts the vote unchanged. Per the NU7/Zodl shielded-polling design (ValarDragon et al.), vote WEIGHT is derived by the poll's tally from a shielded-balance snapshot at a cutoff height, not from the amount delivered with the vote — so amount_zatoshis is the minimal the poll requires (dust), and the group just holds its balance through the snapshot window. Validation runs before anything is built, since a malformed memo is counted as all-abstain on-chain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Completes the coinholder-poll voting feature with manual ballot entry: - BallotDefinition parse + question_shapes in the voting core (lenient, unknown fields ignored); 9 voting unit tests pass. - wallet_prepare_vote command: parses the pasted ballot for validation shapes, maps UI VoteInput -> VoteEntry, and returns a DraftTransaction whose memo is the encoded vote. Casting reuses wallet_send unchanged (recipient = poll reception address, memo = the vote), so no new signing/broadcast plumbing. - New "Vote" tab: paste ballot JSON + reception address, answer each question (fixed choice / free-form where allowed / abstain), then review + sign via the existing FROST ceremony. Review panel labels it "Cast vote" and explains weight comes from the poll's snapshot, not the dust amount sent. - TODO: automated/programmatic poll source (fetch + render + results) as a follow-up; the casting core is already source-agnostic. cargo test (voting) + full backend build + tsc + vite build all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Enabling ZEC protocol voting