plonky2-semaphore/src/access_set.rs
src/access_set.rsRaw
1use anyhow::Result;
2use plonky2::hash::merkle_tree::MerkleTree;
3use plonky2::hash::poseidon::PoseidonHash;
4use plonky2::iop::witness::PartialWitness;
5use plonky2::plonk::circuit_builder::CircuitBuilder;
6use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData};
7use plonky2::plonk::config::Hasher;
8use plonky2::plonk::proof::ProofWithPublicInputs;
9
10use crate::signal::{Digest, Signal, C, F};
11
12pub struct AccessSet(pub MerkleTree<F, PoseidonHash>);
13
14impl AccessSet {
15 // Verify the plonky2 proof of the given nullifier (in the signal structure) and topic.
16 pub fn verify_signal(
17 &self,
18 topic: Digest,
19 signal: Signal,
20 verifier_data: &VerifierCircuitData<F, C, 2>,
21 ) -> Result<()> {
22 let public_inputs: Vec<F> = self
23 .0
24 .cap
25 .0
26 .iter()
27 .flat_map(|h| h.elements)
28 .chain(signal.nullifier)
29 .chain(topic)
30 .collect();
31
32 verifier_data.verify(ProofWithPublicInputs {
33 proof: signal.proof,
34 public_inputs,
35 })
36 }
37
38 // Generate the plonky2 proof for the given key pair and topic.
39 pub fn make_signal(
40 &self,
41 private_key: Digest,
42 topic: Digest,
43 public_key_index: usize,
44 ) -> Result<(Signal, VerifierCircuitData<F, C, 2>)> {
45 let nullifier = PoseidonHash::hash_no_pad(&[private_key, topic].concat()).elements;
46 let config = CircuitConfig::standard_recursion_zk_config();
47 let mut builder = CircuitBuilder::new(config);
48 let mut pw = PartialWitness::new();
49
50 let targets = self.semaphore_circuit(&mut builder);
51 self.fill_semaphore_targets(&mut pw, private_key, topic, public_key_index, targets)?;
52
53 let data = builder.build();
54 let proof = data.prove(pw)?;
55
56 Ok((
57 Signal {
58 nullifier,
59 proof: proof.proof,
60 },
61 data.verifier_data(),
62 ))
63 }
64}