1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 | k = 14;
field = "pallas";
constant "VoteInput" {
EcFixedPointBase NULLIFIER_K,
EcFixedPoint VALUE_COMMIT_RANDOM,
EcFixedPointShort VALUE_COMMIT_VALUE,
}
witness "VoteInput" {
Base coin_secret,
Base coin_value,
Base coin_gov_token_id,
Base coin_spend_hook,
Base coin_user_data,
Base coin_blind,
Base proposal_bulla,
Scalar value_blind,
Base gov_token_blind,
Uint32 leaf_pos,
MerklePath coin_path,
SparseMerklePath null_path,
Base signature_secret,
}
circuit "VoteInput" {
pub = ec_mul_base(coin_secret, NULLIFIER_K);
pub_x = ec_get_x(pub);
pub_y = ec_get_y(pub);
coin = poseidon_hash(
pub_x,
pub_y,
coin_value,
coin_gov_token_id,
coin_spend_hook,
coin_user_data,
coin_blind,
);
# We need this to detect whether the above coin was already spent.
# Use a SMT, and show that at this position, the leaf is ZERO
ZERO = witness_base(0);
nullifier = poseidon_hash(coin_secret, coin);
null_tree_root = sparse_merkle_root(
nullifier, # Position
null_path, # Path to root
ZERO, # Leaf value
);
constrain_instance(null_tree_root);
# Include some secret information in vote nullifier to defeat correlation
# attacks. We reveal the proposal_bulla in vote-main.zk as well.
vote_nullifier = poseidon_hash(nullifier, coin_secret, proposal_bulla);
constrain_instance(proposal_bulla);
constrain_instance(vote_nullifier);
vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
coin_value_commit = ec_add(vcv, vcr);
constrain_instance(ec_get_x(coin_value_commit));
constrain_instance(ec_get_y(coin_value_commit));
token_commit = poseidon_hash(coin_gov_token_id, gov_token_blind);
constrain_instance(token_commit);
# Merkle root
merkle_coin_root = merkle_root(leaf_pos, coin_path, coin);
constrain_instance(merkle_coin_root);
signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
constrain_instance(ec_get_x(signature_public));
constrain_instance(ec_get_y(signature_public));
}
|