-
Notifications
You must be signed in to change notification settings - Fork 186
Maci Threat Modeling - DRAFT #2788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a6d9996
ca1b3eb
2127714
ca9131c
17f4ba8
2dc0954
515200c
66aebdf
5927a24
8940d49
e28071e
d813f86
92a1053
ac154e5
1488dcb
e039c5f
d8616ac
9d43c44
32e68e9
1a9af5d
a1ccc81
a5b1171
b1a980f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,254 @@ | ||||||||
| # MACI Data Flows — System-Level Specification | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 1. Purpose | ||||||||
|
|
||||||||
| This document describes the **data flows in the MACI protocol** as explicitly defined in its published documentation. | ||||||||
| It covers how information moves between on-chain and off-chain components — from user signup and vote submission to coordinator tallying and proof publication. | ||||||||
|
|
||||||||
| All flows below are factual summaries of official MACI docs; any implementation detail not present in the docs is clearly marked as **unspecified**. | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 2. Roles and Components | ||||||||
|
|
||||||||
| | Role | Responsibility | Documentation Source | | ||||||||
| |------|----------------|----------------------| | ||||||||
| | **User (Voter)** | Signs up, joins polls, submits encrypted votes. | Workflow: “Users, who vote on polls” | | ||||||||
| | **Coordinator** | Deploys contracts and polls, decrypts and tallies votes, generates zk-SNARK proofs, publishes results. | Workflow; Coordinator Service | | ||||||||
| | **Relayer (Off-chain)** | Allows gasless voting, batches messages, uploads to IPFS, submits message hashes on-chain. | Off-chain Relayer | | ||||||||
| | **Smart Contracts (including Verifier contracts)** | Manage user signups and polls, record encrypted votes, and verify zk-SNARK proofs for message processing and tally correctness. | Workflow, Technical References | | ||||||||
| | **IPFS / Off-chain Storage** | Holds encrypted message batches submitted by the relayer. | Off-chain Relayer | | ||||||||
| | **zkSNARK Circuits** | Define proofs for `processMessages` and `tallyVotes`. | Technical References | | ||||||||
| | **Ethereum / L2** | Provides canonical ledger for state commitments and proof verification. | General docs | | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 3. Poll Lifecycle and Data Flow Overview | ||||||||
|
|
||||||||
| Each **Poll** progresses through **three stages**: | ||||||||
| 1. **Open** — users can sign up, join, and vote. | ||||||||
| 2. **Closed** — voting ends; coordinator processes messages. | ||||||||
| 3. **Finalized** — coordinator tallies results and publishes verified proofs. | ||||||||
|
|
||||||||
| MACI’s workflow is a data-driven state machine where messages flow between **users**, **relayer**, **on-chain contracts**, **off-chain coordinator**, and **verifiers**. | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 4. Detailed Data Flows | ||||||||
|
|
||||||||
| ### A. Setup and Deployment | ||||||||
|
|
||||||||
| **Coordinator → Blockchain** | ||||||||
|
|
||||||||
| 1. Download **trusted setup parameters** for proof verification (Groth16 keys). | ||||||||
| _Source: Trusted Setup docs._ | ||||||||
|
|
||||||||
| 2. Deploy `MACI.sol` and dependent contracts (`PollFactory`, `Gatekeeper`, `Verifier`, etc.). | ||||||||
| - Sets gatekeeper policy (who can sign up). | ||||||||
| - Defines state tree depth (max voters). | ||||||||
| - Specifies voting mode (e.g., quadratic funding). | ||||||||
| _Source: Coordinator Service._ | ||||||||
|
|
||||||||
| 3. Deploy a **Poll** via `MACI.deployPoll()`. | ||||||||
| - Poll parameters include: gatekeeper, start/end dates, vote options, and voting mode. | ||||||||
| _Source: Workflow → Poll Lifecycle._ | ||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### B. User Sign Up | ||||||||
|
|
||||||||
| **User/Wallet → MACI.sol** | ||||||||
|
|
||||||||
| 1. Generate MACI keypair (distinct from Ethereum key). | ||||||||
| 2. Call `signUp()` on the MACI contract with the **public key**. | ||||||||
| - This key becomes the voter’s MACI identity. | ||||||||
| - The gatekeeper policy enforces Sybil resistance (e.g., NFT, EAS attestation, proof-of-personhood). | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I am not sure if this distinction should go in this section or maybe in Data artifacts created:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @NicoSerranoP is this condition potentially breaking linkability? aka, do we leak participation info for the user's onchain identity? and if so, is this a weakness - correlating poll participation with other onchain activity, or correlating participation across different polls (user X has participated in polls x,y and z?. Is this a potential threat/vulnerability/weakness? Maybe we could consider extending the privacy/linkability invariant statingt that linkability of maci key to users EOA is not covered and also add a known weakness section (unless we do not consider it a weakness?). What about possible mitigations? Use relayer for signup ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes, i agree it makes sense to add this as a step artifact |
||||||||
| _Source: Workflow → “Sign up.”_ | ||||||||
|
|
||||||||
| **Data artifacts created:** | ||||||||
| - `signUp()` event (public). | ||||||||
| - User’s MACI public key (on-chain state tree leaf). | ||||||||
| - Associated private key (off-chain only, user-held). | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### C. Poll Joining | ||||||||
|
|
||||||||
| **User/Wallet → Poll.sol** | ||||||||
|
|
||||||||
| 1. Call poll’s **join** function, providing: | ||||||||
| - ZK proof of knowledge of a MACI public key in the state tree, a new key to vote on the poll and a nullifier without revealing which keys they are | ||||||||
| - Any poll-specific gatekeeper credentials. | ||||||||
| _Source: Workflow → “Poll Joining.” & https://maci.pse.dev/blog/anonymous-poll-joining#why-poll-joining_ | ||||||||
|
|
||||||||
| 2. On success, user is registered to vote in that poll instance. | ||||||||
|
|
||||||||
| **Data artifacts created:** | ||||||||
| - On-chain proof of poll eligibility. | ||||||||
| - Internal state tree update linking user MACI public key to poll. | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### D. Vote Command and Message Creation | ||||||||
|
|
||||||||
| **User/Wallet (local)** | ||||||||
|
|
||||||||
| 1. Build a **command** (fields per docs): | ||||||||
| - `maciPublicKey`, `voteOption`, `voteWeight`, `nonce`, `pollId`, `salt` | ||||||||
| _Source: Workflow → “Vote.”_ | ||||||||
|
|
||||||||
| 2. **Sign** the command with the MACI private key. | ||||||||
| 3. **Encrypt** the command and signature with a shared key between user and coordinator. | ||||||||
| - Each user–coordinator pair uses a distinct encryption key (Elliptic-Curve Diffie–Hellman (ECDH) shared key created by using user MACI private key and coordinator MACI public key). | ||||||||
| - This ensures only the coordinator can decrypt the message. | ||||||||
| _Source: Workflow → “Before sending their vote on-chain…”_ | ||||||||
|
|
||||||||
| 4. Resulting ciphertext = **Message**. | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### E. Message Submission (Two Paths) | ||||||||
|
|
||||||||
| #### Path 1 — On-chain (direct) | ||||||||
|
|
||||||||
| **User/Wallet → Poll.sol** | ||||||||
| - Call `publishMessage()` with encrypted message. | ||||||||
| - Message stored directly on-chain. | ||||||||
| _Source: Workflow → “Vote on a poll.”_ | ||||||||
|
|
||||||||
| #### Path 2 — Off-chain Relayer (privacy/gasless) | ||||||||
|
|
||||||||
| **User/Wallet → Relayer** | ||||||||
| 1. Send encrypted message off-chain. | ||||||||
| 2. Relayer verifies user authorization via ZK proof (user must know pre-image to a state leaf). | ||||||||
| 3. Relayer batches messages and uploads them to IPFS. | ||||||||
| 4. Relayer submits **batch hash + IPFS CID** to `Poll.sol`. | ||||||||
| _Source: Off-chain Relayer/Core Concepts:Offchain Voting._ | ||||||||
|
|
||||||||
| > ⚠️ If batch hashes are submitted without valid IPFS storage, polls cannot be finalized. | ||||||||
| > _Source: Off-chain Relayer._ | ||||||||
|
|
||||||||
| **Data artifacts created:** | ||||||||
| - IPFS batch (off-chain) | ||||||||
| - On-chain reference (CID + hash) | ||||||||
|
|
||||||||
| --- | ||||||||
| ### F. Key change (optional, per user) | ||||||||
|
|
||||||||
| 1. User can change their MACI public key at any time (e.g. a briber buys his vote) | ||||||||
| 2. User creates a new encrypted message with a new vote and a reference to the new MACI public key | ||||||||
| 3. User signs this message with his current public key | ||||||||
| 4. User publishes the message using any path | ||||||||
|
|
||||||||
| **Data artifacts created:** | ||||||||
|
|
||||||||
| - Encrypted message with a reference to the user's new MACI public key | ||||||||
| - New private key (off-chain only, user-held). | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
AronisAt79 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| ### G. Poll Closing | ||||||||
|
|
||||||||
| **Blockchain → Coordinator** | ||||||||
|
|
||||||||
| 1. Once poll duration elapses, Poll transitions from **Open → Closed**. | ||||||||
| 2. No further messages accepted. | ||||||||
| 3. Coordinator begins off-chain processing. | ||||||||
| _Source: Workflow → “Closed.”_ | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### H. Message Processing | ||||||||
|
|
||||||||
| **Coordinator (local)** | ||||||||
|
|
||||||||
| 1. Fetch all IPFS batches using on-chain CIDs. | ||||||||
| 2. Decrypt and validate each message. | ||||||||
| 3. Apply valid messages to the **state tree**, ignoring superseded votes (only the latest per voter counts). | ||||||||
| _Source: Workflow → “Process Messages.”_ | ||||||||
|
|
||||||||
| 4. Create ZK proof showing: | ||||||||
| - Correct decryption of messages. | ||||||||
| - Correct state tree transitions. | ||||||||
|
|
||||||||
| **Coordinator → Blockchain** | ||||||||
| 5. Call `MessageProcessor.processMessages()` with: | ||||||||
| - State tree hash | ||||||||
| - zk-SNARK proof | ||||||||
|
|
||||||||
| **Verifier Contract** | ||||||||
| 6. Verifies proof validity. | ||||||||
| - If returns `true`, the processed batch is confirmed correct. | ||||||||
| - Repeat until all messages are processed. | ||||||||
| _Source: Workflow → “Process Messages.”_ | ||||||||
|
|
||||||||
| **Data artifacts:** | ||||||||
| - Updated state tree (off-chain) | ||||||||
| - Batch proofs (on-chain) | ||||||||
| - Message proofs (verifier output) | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### I. Tally Results | ||||||||
|
|
||||||||
| **Coordinator (local)** | ||||||||
|
|
||||||||
| 1. Compute tally from valid votes in state tree. | ||||||||
| 2. Generate ZK proof that tally corresponds to valid votes. | ||||||||
| _Source: Workflow → “Tally Results.”_ | ||||||||
|
|
||||||||
| **Coordinator → Blockchain** | ||||||||
| 3. Call `Tally.tallyVotes()` with: | ||||||||
| - Tally hash | ||||||||
| - zk-SNARK proof | ||||||||
|
|
||||||||
| **Verifier Contract** | ||||||||
| 4. Validates tally proof. | ||||||||
| - If valid, Poll moves to **Finalized** state. | ||||||||
|
|
||||||||
| **Data artifacts:** | ||||||||
| - Tally proof + hash | ||||||||
| - On-chain event `PollFinalized` | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ### J. Finalization and Verification | ||||||||
|
|
||||||||
| **Blockchain (public)** | ||||||||
|
|
||||||||
| - The poll’s final state, tally hash, and ZK proof are now visible. | ||||||||
| - Any user can verify that the results were correctly computed from valid encrypted votes. | ||||||||
| - Individual votes remain private. | ||||||||
| _Source: Workflow → “Finalized.”_ | ||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 5. Trust Boundaries (per flow segment) | ||||||||
|
|
||||||||
| | Flow Segment | Trust Boundary | Possible Weakness | | ||||||||
| |---------------|----------------|-------------------| | ||||||||
| | User ↔ Wallet | Key generation & signing | Key leakage compromises user’s MACI identity | | ||||||||
| | Wallet ↔ Relayer | Off-chain submission | Relayer may log metadata or fail to upload IPFS batches | | ||||||||
AronisAt79 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| | Wallet ↔ Poll contract | Message publishing | Using same wallet to join poll (gatekeeping) and publish vote may link address to encrypted vote | | ||||||||
| | Relayer ↔ IPFS | Data persistence | Missing batches block finalization | | ||||||||
| | Coordinator ↔ Blockchain | Proof publication | Coordinator may halt, preventing results from being published | | ||||||||
| | Coordinator ↔ Verifier | Proof correctness | Circuit mismatch or setup corruption may invalidate verification | | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @NicoSerranoP similar to #2788 (comment), i believe we do not need to frame this as a boundary. i feel it would be more appropriate to classify a briber as an adversary for which we have already defined an invariant (l2) |
||||||||
|
|
||||||||
| --- | ||||||||
|
|
||||||||
| ## 6. Failure and Liveness Scenarios (as documented) | ||||||||
|
|
||||||||
| | Failure Mode | Effect | Source | | ||||||||
| |---------------|--------|--------| | ||||||||
| | Coordinator halts / offline | Poll never finalized; results not published. | Workflow → “Trust assumptions” | | ||||||||
| | Coordinator decrypts votes | Privacy loss but not integrity failure. | Workflow → “Trust assumptions” | | ||||||||
| | Relayer pushes invalid IPFS hash | Poll cannot be finalized. | Off-chain Relayer | | ||||||||
| | zk-SNARK setup compromised | Fake proofs accepted. | Trusted Setup | | ||||||||
| | L1/L2 censorship | Delays proof publication; no permanent forgery. | General assumption | | ||||||||
AronisAt79 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| | User sells his MACI keypair | Briber will always be able to vote as the user. | Key change data flow → “Trust assumptions” | | ||||||||
|
|
||||||||
| --- | ||||||||
Uh oh!
There was an error while loading. Please reload this page.