vote_commitment_tree/
lib.rs1mod anchor;
29pub mod client;
30mod hash;
31pub mod kv_shard_store;
32pub mod memory_server;
33mod path;
34pub mod serde;
35pub mod server;
36pub mod sync_api;
37
38pub use anchor::Anchor;
41pub use client::{SyncError, TreeClient};
42pub use hash::{MerkleHashVote, TREE_DEPTH};
43pub use path::{MerklePath, MERKLE_PATH_BYTES};
44pub use server::{AppendFromKvError, MemoryTreeServer, SyncableServer, TreeServer};
45pub use sync_api::TreeSyncApi;
46
47use pasta_curves::Fp;
50
51pub const DOMAIN_VC: u64 = 1;
53
54#[inline]
56pub fn poseidon_hash(left: Fp, right: Fp) -> Fp {
57 imt_tree::poseidon_hash(left, right)
58}
59
60pub fn poseidon_hash_6(a: Fp, b: Fp, c: Fp, d: Fp, e: Fp, f: Fp) -> Fp {
62 use halo2_gadgets::poseidon::primitives::{self as poseidon, ConstantLength, P128Pow5T3};
63
64 poseidon::Hash::<_, P128Pow5T3, ConstantLength<6>, 3, 2>::init().hash([a, b, c, d, e, f])
65}
66
67pub fn vote_commitment_hash(
76 voting_round_id: Fp,
77 shares_hash: Fp,
78 proposal_id: Fp,
79 vote_decision: Fp,
80) -> Fp {
81 use halo2_gadgets::poseidon::primitives::{self as poseidon, ConstantLength, P128Pow5T3};
82
83 poseidon::Hash::<_, P128Pow5T3, ConstantLength<5>, 3, 2>::init().hash([
84 Fp::from(DOMAIN_VC),
85 voting_round_id,
86 shares_hash,
87 proposal_id,
88 vote_decision,
89 ])
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_vote_commitment_hash_basic() {
98 let round = Fp::from(99u64);
100 let a = vote_commitment_hash(round, Fp::from(1u64), Fp::from(2u64), Fp::from(0u64));
101 let b = vote_commitment_hash(round, Fp::from(1u64), Fp::from(2u64), Fp::from(1u64));
102 assert_ne!(a, b);
103 }
104
105 #[test]
106 fn test_vote_commitment_hash_deterministic() {
107 let round = Fp::from(99u64);
108 let h1 = vote_commitment_hash(round, Fp::from(42u64), Fp::from(3u64), Fp::from(1u64));
109 let h2 = vote_commitment_hash(round, Fp::from(42u64), Fp::from(3u64), Fp::from(1u64));
110 assert_eq!(h1, h2);
111 }
112
113 #[test]
114 fn test_vote_commitment_hash_cross_validates_with_orchard() {
115 use voting_circuits::vote_proof;
116
117 let voting_round_id = Fp::from(0xCAFEu64);
118 let shares_hash = Fp::from(0xDEAD_BEEFu64);
119 let proposal_id = Fp::from(5u64);
120 let vote_decision = Fp::from(1u64);
121
122 let ours = vote_commitment_hash(voting_round_id, shares_hash, proposal_id, vote_decision);
123 let theirs = vote_proof::vote_commitment_hash(
124 voting_round_id,
125 shares_hash,
126 proposal_id,
127 vote_decision,
128 );
129 assert_eq!(
130 ours, theirs,
131 "vote_commitment_hash must match orchard circuit helper"
132 );
133 }
134
135 #[test]
136 fn test_domain_vc_matches_orchard() {
137 assert_eq!(DOMAIN_VC, voting_circuits::vote_proof::DOMAIN_VC);
138 }
139}