# zk Voting with ECDSA sig verification and storage proofs WIP circuit [here](https://github.com/noir-lang/noir-starter/blob/jc/scratchpad/scratchpad/circuits/src/main.nr) ## Membership inclusion ### Storage Proofs - verifying token ownership requires storage proofs - snapshot at a given block w/ specific block header - zk program verifies a storage proof on that header ```solidity struct Proposal { uint snapshotBlock; bytes32 blockHeader; bytes32 ipfsHash; uint deadline; uint forVotes; uint againstVotes; } mapping (uint proposalId => Proposal) public proposals; ``` - use this library to build a merkle tree on chain with sybil protection provided by token ownership - https://github.com/hananbeer/protomerkle - program would verify inclusion in the set (storage proof) - nullifier would be `hash(pub_key, proposal_id)` ### Manual setup - otherwise there could be a setup phase where a user generates a private key by signing a message with their ethereum account. for this, there would also need to be a secret value added to prevent links between accounts used in multiple ## Voting ### Signature verification - public key - signature - message_hash - proposal_id - vote - nullifier is a hash of: - proposal id - public_key_x - returned by circuit (must be provided for valid proof) - vote is excluded otherwise people could vote in both directions ## Circuit ```rust! fn main(pub_key_x : [u8; 32], pub_key_y : [u8; 32], signature: [u8; 64], message_hash: pub [u8; 32], proposalId: Field, vote: Field, block_header : [u8; 32]) { let isValid = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, message_hash); assert(isValid == 1); // https://github.com/colinnielsen/ecrecover-noir/blob/main/src/secp256k1/helpers.nr let eth_address = ecrecover(pub_key_x, pub_key_y, signature, message_hash); // storage proof; TBD storage_proof(block_header, eth_address, token_contract, storage_slot); let mut new_array: [Field; 33] = [0;33]; new_array[0] = proposalId; for i in 1..new_array.len() { new_array[i] = pub_key_x[i] as Field; } let nullifier = std::hash::pedersen(new_array); } ```