# 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);
}
```