mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 10:41:57 +03:00
commit vote example
This commit is contained in:
parent
491bc2271d
commit
ad139ec82d
2
examples/vote/.gitignore
vendored
Normal file
2
examples/vote/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
outputs/
|
||||||
|
build/
|
93
examples/vote/README.md
Normal file
93
examples/vote/README.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# Leo Vote
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`vote.leo` is a general vote program.
|
||||||
|
|
||||||
|
Anyone can propose new proposals, proposer can issue tickets to the voters, and the voter can vote without exposing privacy (with the help of Aleo's flexible privacy mechanism).
|
||||||
|
|
||||||
|
Proposal information and statistical voting results is public, while the correlation between the voter and the vote is private(protected by zk).
|
||||||
|
|
||||||
|
This example is inspired by the [aleo-vote](https://github.com/zkprivacy/aleo-vote) example written by the Aleo community.
|
||||||
|
|
||||||
|
## Noteworthy Features
|
||||||
|
|
||||||
|
mappings etc.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
|
||||||
|
To compile this Leo program, run:
|
||||||
|
```bash
|
||||||
|
leo build
|
||||||
|
```
|
||||||
|
|
||||||
|
Make changes to `vote/inputs/vote.in` before running each command.
|
||||||
|
|
||||||
|
### Propose
|
||||||
|
|
||||||
|
Anyone can propose new proposals publicly by calling `propose` function.
|
||||||
|
|
||||||
|
Run `propose`:
|
||||||
|
|
||||||
|
```
|
||||||
|
leo run propose
|
||||||
|
```
|
||||||
|
|
||||||
|
Output sample:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
owner: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2.private,
|
||||||
|
gates: 0u64.private,
|
||||||
|
id: 2805252584833208809872967597325381727971256629741137995614832105537063464740field.private,
|
||||||
|
info: {
|
||||||
|
title: 2077160157502449938194577302446444field.private,
|
||||||
|
content: 1452374294790018907888397545906607852827800436field.private,
|
||||||
|
proposer: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2.private
|
||||||
|
},
|
||||||
|
_nonce: 1639660347839832220966145410710039205878572956621820215177036061076060242021group.public
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create Ticket
|
||||||
|
|
||||||
|
Proposer can create new tickets for proposed proposals.
|
||||||
|
|
||||||
|
Ticket is a record with `owner` and `pid`, it can be used to vote for the specific proposal - `pid`, and can only be used(voted) by the ticket `owner`.
|
||||||
|
|
||||||
|
Run `new_ticket`:
|
||||||
|
|
||||||
|
```
|
||||||
|
aleo run new_ticket
|
||||||
|
```
|
||||||
|
|
||||||
|
Output sample:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
owner: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2.private,
|
||||||
|
gates: 0u64.private,
|
||||||
|
pid: 2264670486490520844857553240576860973319410481267184439818180411609250173817field.private,
|
||||||
|
_nonce: 1637267040221574073903539416642641433705357302885235345311606754421919550724group.public
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vote
|
||||||
|
|
||||||
|
Ticket owner can use the ticket to vote `agree` / `disagree` with the specific proposal - `pid`.
|
||||||
|
|
||||||
|
As the ticket record can be used as an input privately, the voter's privacy is protected by zk.
|
||||||
|
|
||||||
|
Run `agree`:
|
||||||
|
|
||||||
|
```
|
||||||
|
leo run agree
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `disagree`:
|
||||||
|
|
||||||
|
```
|
||||||
|
leo run disagree
|
||||||
|
```
|
27
examples/vote/inputs/vote.in
Normal file
27
examples/vote/inputs/vote.in
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// The program input for vote/src/main.leo
|
||||||
|
[propose]
|
||||||
|
info: ProposalInfo = ProposalInfo {
|
||||||
|
title: 2077160157502449938194577302446444field,
|
||||||
|
content: 1452374294790018907888397545906607852827800436field,
|
||||||
|
proposer: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2,
|
||||||
|
};
|
||||||
|
|
||||||
|
[new_ticket]
|
||||||
|
pid: field = 2264670486490520844857553240576860973319410481267184439818180411609250173817field;
|
||||||
|
voter: address = aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2;
|
||||||
|
|
||||||
|
[agree]
|
||||||
|
ticket: Ticket = Ticket {
|
||||||
|
owner: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2,
|
||||||
|
gates: 0u64,
|
||||||
|
pid: 2264670486490520844857553240576860973319410481267184439818180411609250173817field,
|
||||||
|
_nonce: 1637267040221574073903539416642641433705357302885235345311606754421919550724group
|
||||||
|
};
|
||||||
|
|
||||||
|
[disagree]
|
||||||
|
ticket: Ticket = Ticket {
|
||||||
|
owner: aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2,
|
||||||
|
gates: 0u64,
|
||||||
|
pid: 2264670486490520844857553240576860973319410481267184439818180411609250173817field,
|
||||||
|
_nonce: 1637267040221574073903539416642641433705357302885235345311606754421919550724group
|
||||||
|
};
|
10
examples/vote/program.json
Normal file
10
examples/vote/program.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"program": "vote.aleo",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "",
|
||||||
|
"development": {
|
||||||
|
"private_key": "APrivateKey1zkpBDEpwdFWqxe1NdB9fxZxiX9LahJ3CdqchSs7FGZVggNw",
|
||||||
|
"address": "aleo1kkk52quhnxgn2nfrcd9jqk7c9x27c23f2wvw7fyzcze56yahvcgszgttu2"
|
||||||
|
},
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
9
examples/vote/run.sh
Executable file
9
examples/vote/run.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# Build the Leo vote program.
|
||||||
|
(
|
||||||
|
leo build || exit
|
||||||
|
)
|
||||||
|
|
||||||
|
# Run the `propose` program function
|
||||||
|
(
|
||||||
|
leo run propose || exit
|
||||||
|
)
|
96
examples/vote/src/main.leo
Normal file
96
examples/vote/src/main.leo
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// The 'vote.leo' program.
|
||||||
|
|
||||||
|
// Proposal details
|
||||||
|
circuit ProposalInfo {
|
||||||
|
title: field,
|
||||||
|
content: field,
|
||||||
|
proposer: address,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proposal record records proposal info publicly
|
||||||
|
record Proposal {
|
||||||
|
owner: address,
|
||||||
|
gates: u64,
|
||||||
|
id: field, // todo: make public
|
||||||
|
info: ProposalInfo, // todo make public
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save proposal info in public storage.
|
||||||
|
mapping proposals: field => ProposalInfo;
|
||||||
|
|
||||||
|
// Privacy tickets to vote
|
||||||
|
record Ticket {
|
||||||
|
owner: address,
|
||||||
|
gates: u64,
|
||||||
|
pid: field,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the total tickets issued for each proposal
|
||||||
|
mapping tickets: field => u64;
|
||||||
|
|
||||||
|
mapping agree_votes: field => u64;
|
||||||
|
|
||||||
|
mapping disagree_votes: field => u64;
|
||||||
|
|
||||||
|
// Propose a new proposal to vote on.
|
||||||
|
@program
|
||||||
|
function propose(public info: ProposalInfo) -> Proposal {
|
||||||
|
// Authenticate proposer.
|
||||||
|
console.assert_eq(self.caller, info.proposer);
|
||||||
|
|
||||||
|
// Generate a new proposal id.
|
||||||
|
let id: field = BHP256::hash(info.title);
|
||||||
|
|
||||||
|
// Finalize the proposal id.
|
||||||
|
finalize(id);
|
||||||
|
|
||||||
|
// Return a new record for the proposal.
|
||||||
|
return Proposal {
|
||||||
|
owner: self.caller,
|
||||||
|
gates: 0u64,
|
||||||
|
id,
|
||||||
|
info,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Create a new proposal in the "tickets" mapping.
|
||||||
|
finalize propose(public id: field) {
|
||||||
|
increment(tickets, id, 0u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new ticket to vote with.
|
||||||
|
@program
|
||||||
|
function new_ticket(
|
||||||
|
public pid: field,
|
||||||
|
public voter: address,
|
||||||
|
) -> Ticket {
|
||||||
|
// Finalize the proposal id for the ticket.
|
||||||
|
finalize(pid);
|
||||||
|
|
||||||
|
return Ticket {
|
||||||
|
owner: voter,
|
||||||
|
gates: 0u64,
|
||||||
|
pid,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Create a new ticket on a proposal in the "tickets" mapping.
|
||||||
|
finalize new_ticket(public pid: field) {
|
||||||
|
increment(tickets, pid, 1u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vote to agree with a proposal.
|
||||||
|
@program
|
||||||
|
function agree(ticket: Ticket) {// Privately cast the vote.
|
||||||
|
finalize(ticket.pid);
|
||||||
|
}
|
||||||
|
finalize agree(public pid: field) {// Publicly increment the number of agree votes.
|
||||||
|
increment(agree_votes, pid, 1u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vote to disagree with a proposal.
|
||||||
|
@program
|
||||||
|
function disagree(ticket: Ticket) {// Privately cast the vote.
|
||||||
|
finalize(ticket.pid);
|
||||||
|
}
|
||||||
|
finalize disagree(pid: field) {// Publicly increment the number of disagree votes.
|
||||||
|
increment(disagree_votes, pid, 1u64);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user