mirror of
https://github.com/arnaucube/plonky2-semaphore.git
synced 2026-01-15 10:11:28 +01:00
Add inline comments describing the usage of methods
and update the Semaphore link to the current one.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Plonky2 implementation of the [Semaphore protocol](http://semaphore.appliedzkp.org/)
|
# Plonky2 implementation of the [Semaphore protocol](https://semaphore.pse.dev)
|
||||||
|
|
||||||
Used as an example in the ZKHack Plonky2 presentation.
|
Used as an example in the ZKHack Plonky2 presentation.
|
||||||
|
|
||||||
@@ -6,4 +6,4 @@ Used as an example in the ZKHack Plonky2 presentation.
|
|||||||
```bash
|
```bash
|
||||||
rustup override set nightly # Requires nightly Rust
|
rustup override set nightly # Requires nightly Rust
|
||||||
cargo test --release
|
cargo test --release
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crate::signal::{Digest, Signal, C, F};
|
|||||||
pub struct AccessSet(pub MerkleTree<F, PoseidonHash>);
|
pub struct AccessSet(pub MerkleTree<F, PoseidonHash>);
|
||||||
|
|
||||||
impl AccessSet {
|
impl AccessSet {
|
||||||
|
// Verify the plonky2 proof of the given nullifier (in the signal structure) and topic.
|
||||||
pub fn verify_signal(
|
pub fn verify_signal(
|
||||||
&self,
|
&self,
|
||||||
topic: Digest,
|
topic: Digest,
|
||||||
@@ -34,6 +35,7 @@ impl AccessSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate the plonky2 proof for the given key pair and topic.
|
||||||
pub fn make_signal(
|
pub fn make_signal(
|
||||||
&self,
|
&self,
|
||||||
private_key: Digest,
|
private_key: Digest,
|
||||||
|
|||||||
@@ -24,6 +24,19 @@ impl AccessSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn semaphore_circuit(&self, builder: &mut CircuitBuilder<F, 2>) -> SemaphoreTargets {
|
pub fn semaphore_circuit(&self, builder: &mut CircuitBuilder<F, 2>) -> SemaphoreTargets {
|
||||||
|
// To create the circuit 'values', we call the `add_virtual_target` and it's variants (ie.
|
||||||
|
// `add_virtual_target_arr`, or `add_virtual_hash` which internally calls it for the 4
|
||||||
|
// field values that conform the hash.
|
||||||
|
// The method `add_virtual_target` keeps an incremental index for each new virtual target
|
||||||
|
// created, and returns a new `VirtualTarget`, used for intermediate values in witness
|
||||||
|
// generation (which when needed can be copied to specific witness location (Wire)).
|
||||||
|
//
|
||||||
|
// The `register_public_input` and it's variants, append to the CircuitBuilder's
|
||||||
|
// `public_inputs` vector the given Target (either VirtualTarget or Wire).
|
||||||
|
//
|
||||||
|
// Notice that when created, the targets are not given any value, and they will be set later
|
||||||
|
// at the method `fill_semaphore_targets`.
|
||||||
|
|
||||||
// Register public inputs.
|
// Register public inputs.
|
||||||
let merkle_root = builder.add_virtual_hash();
|
let merkle_root = builder.add_virtual_hash();
|
||||||
builder.register_public_inputs(&merkle_root.elements);
|
builder.register_public_inputs(&merkle_root.elements);
|
||||||
@@ -65,6 +78,8 @@ impl AccessSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill the semaphore targets that we defined at the method `semaphore_circuit` with the given
|
||||||
|
// values.
|
||||||
pub fn fill_semaphore_targets(
|
pub fn fill_semaphore_targets(
|
||||||
&self,
|
&self,
|
||||||
pw: &mut PartialWitness<F>,
|
pw: &mut PartialWitness<F>,
|
||||||
|
|||||||
@@ -39,8 +39,13 @@ impl AccessSet {
|
|||||||
.chain(topic1)
|
.chain(topic1)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// `add_virtual_proof_with_pis` is an extended version of the `add_virtual_target`, but
|
||||||
|
// that takes care of adding all the values of the proof and the public inputs (pis).
|
||||||
let proof_target0 = builder.add_virtual_proof_with_pis(&verifier_data.common);
|
let proof_target0 = builder.add_virtual_proof_with_pis(&verifier_data.common);
|
||||||
|
// set the public inputs
|
||||||
builder.register_public_inputs(&proof_target0.public_inputs);
|
builder.register_public_inputs(&proof_target0.public_inputs);
|
||||||
|
// `set_proof_with_pis_target` is an extended version of the `set_target`, but that takes
|
||||||
|
// care of adding all the values of the proof and the public inputs.
|
||||||
pw.set_proof_with_pis_target(
|
pw.set_proof_with_pis_target(
|
||||||
&proof_target0,
|
&proof_target0,
|
||||||
&ProofWithPublicInputs {
|
&ProofWithPublicInputs {
|
||||||
@@ -48,10 +53,12 @@ impl AccessSet {
|
|||||||
public_inputs: public_inputs0,
|
public_inputs: public_inputs0,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
// add & set the verifier data
|
||||||
let vd_target =
|
let vd_target =
|
||||||
builder.add_virtual_verifier_data(verifier_data.common.config.fri_config.cap_height);
|
builder.add_virtual_verifier_data(verifier_data.common.config.fri_config.cap_height);
|
||||||
pw.set_verifier_data_target(&vd_target, &verifier_data.verifier_only)?;
|
pw.set_verifier_data_target(&vd_target, &verifier_data.verifier_only)?;
|
||||||
|
|
||||||
|
// now, the same as we did with the proof0, with the proof1 related values:
|
||||||
let proof_target1 = builder.add_virtual_proof_with_pis(&verifier_data.common);
|
let proof_target1 = builder.add_virtual_proof_with_pis(&verifier_data.common);
|
||||||
builder.register_public_inputs(&proof_target1.public_inputs);
|
builder.register_public_inputs(&proof_target1.public_inputs);
|
||||||
pw.set_proof_with_pis_target(
|
pw.set_proof_with_pis_target(
|
||||||
@@ -95,7 +102,6 @@ mod tests {
|
|||||||
use plonky2::hash::poseidon::PoseidonHash;
|
use plonky2::hash::poseidon::PoseidonHash;
|
||||||
use plonky2::plonk::config::Hasher;
|
use plonky2::plonk::config::Hasher;
|
||||||
use plonky2::plonk::proof::ProofWithPublicInputs;
|
use plonky2::plonk::proof::ProofWithPublicInputs;
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
use crate::access_set::AccessSet;
|
use crate::access_set::AccessSet;
|
||||||
use crate::signal::{Digest, F};
|
use crate::signal::{Digest, F};
|
||||||
@@ -117,24 +123,18 @@ mod tests {
|
|||||||
// first proof
|
// first proof
|
||||||
let i0 = 12;
|
let i0 = 12;
|
||||||
let topic0 = F::rand_array();
|
let topic0 = F::rand_array();
|
||||||
let start = Instant::now();
|
|
||||||
let (signal0, vd0) = access_set.make_signal(private_keys[i0], topic0, i0)?;
|
let (signal0, vd0) = access_set.make_signal(private_keys[i0], topic0, i0)?;
|
||||||
println!("generate proof: {:?}", start.elapsed());
|
|
||||||
access_set.verify_signal(topic0, signal0.clone(), &vd0)?;
|
access_set.verify_signal(topic0, signal0.clone(), &vd0)?;
|
||||||
|
|
||||||
// second proof
|
// second proof
|
||||||
let i1 = 42;
|
let i1 = 42;
|
||||||
let topic1 = F::rand_array();
|
let topic1 = F::rand_array();
|
||||||
let start = Instant::now();
|
|
||||||
let (signal1, vd1) = access_set.make_signal(private_keys[i1], topic1, i1)?;
|
let (signal1, vd1) = access_set.make_signal(private_keys[i1], topic1, i1)?;
|
||||||
println!("generate proof: {:?}", start.elapsed());
|
|
||||||
access_set.verify_signal(topic1, signal1.clone(), &vd1)?;
|
access_set.verify_signal(topic1, signal1.clone(), &vd1)?;
|
||||||
|
|
||||||
// generate recursive proof
|
// generate recursive proof
|
||||||
let start = Instant::now();
|
|
||||||
let (nullifier0, nullifier1, recursive_proof, vd2) =
|
let (nullifier0, nullifier1, recursive_proof, vd2) =
|
||||||
access_set.aggregate_signals(topic0, signal0, topic1, signal1, &vd0)?;
|
access_set.aggregate_signals(topic0, signal0, topic1, signal1, &vd0)?;
|
||||||
println!("aggregate_signals (recursive prove): {:?}", start.elapsed());
|
|
||||||
|
|
||||||
// verify recursive proof
|
// verify recursive proof
|
||||||
let public_inputs: Vec<F> = access_set
|
let public_inputs: Vec<F> = access_set
|
||||||
@@ -150,12 +150,10 @@ mod tests {
|
|||||||
.chain(topic1)
|
.chain(topic1)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
vd2.verify(ProofWithPublicInputs {
|
vd2.verify(ProofWithPublicInputs {
|
||||||
proof: recursive_proof,
|
proof: recursive_proof,
|
||||||
public_inputs,
|
public_inputs,
|
||||||
})?;
|
})?;
|
||||||
println!("verify recursive proof: {:?}", start.elapsed());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ mod tests {
|
|||||||
let i = 12;
|
let i = 12;
|
||||||
let topic = F::rand_array();
|
let topic = F::rand_array();
|
||||||
|
|
||||||
|
// generate the plonky2 proof for the given key
|
||||||
let (signal, vd) = access_set.make_signal(private_keys[i], topic, i)?;
|
let (signal, vd) = access_set.make_signal(private_keys[i], topic, i)?;
|
||||||
|
// verify the plonky2 proof (contained in `signal`)
|
||||||
access_set.verify_signal(topic, signal, &vd)
|
access_set.verify_signal(topic, signal, &vd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user