Skip to content

Commit

Permalink
feat(rln): Add custom iden3 graph data support for RLN (#286)
Browse files Browse the repository at this point in the history
Brought back functionality that was removed during the migration to
iden3

- Modify circuit module to include graph data loading and calculation
- Update RLN struct to store graph data
- Adjust proof generation and FFI methods to use graph data
- Update benchmarks and tests to use sample size instead of measurement
time
- Add new methods for graph data retrieval and handling
  • Loading branch information
seemenkina authored Feb 27, 2025
1 parent 5c60ec7 commit de9c0d5
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 22 deletions.
6 changes: 4 additions & 2 deletions rln-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ fn main() -> Result<()> {
}) => {
let mut resources: Vec<Vec<u8>> = Vec::new();
#[cfg(feature = "arkzkey")]
let filenames = ["rln_final.arkzkey", "verification_key.arkvkey"];
let filenames = ["rln_final.arkzkey", "verification_key.arkvkey", "graph.bin"];
#[cfg(not(feature = "arkzkey"))]
let filenames = ["rln_final.zkey", "verification_key.arkvkey"];
let filenames = ["rln_final.zkey", "verification_key.arkvkey", "graph.bin"];
for filename in filenames {
let fullpath = resources_path.join(Path::new(filename));
let mut file = File::open(&fullpath)?;
Expand All @@ -74,6 +74,7 @@ fn main() -> Result<()> {
tree_height,
resources[0].clone(),
resources[1].clone(),
resources[2].clone(),
Cursor::new(tree_config.to_string().as_bytes()),
)?)
} else {
Expand All @@ -82,6 +83,7 @@ fn main() -> Result<()> {
tree_height,
resources[0].clone(),
resources[1].clone(),
resources[2].clone(),
Cursor::new(json!({}).to_string()),
)?)
};
Expand Down
2 changes: 1 addition & 1 deletion rln/benches/circuit_loading_arkzkey_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn compressed_bench(c: &mut Criterion) {

criterion_group! {
name = benches;
config = Criterion::default().measurement_time(std::time::Duration::from_secs(250));
config = Criterion::default().sample_size(10);
targets = uncompressed_bench, compressed_bench
}
criterion_main!(benches);
2 changes: 1 addition & 1 deletion rln/benches/circuit_loading_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn zkey_load_benchmark(c: &mut Criterion) {

criterion_group! {
name = benches;
config = Criterion::default().measurement_time(std::time::Duration::from_secs(250));
config = Criterion::default().sample_size(10);
targets = zkey_load_benchmark
}
criterion_main!(benches);
15 changes: 11 additions & 4 deletions rln/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ pub fn zkey_from_raw(zkey_data: &[u8]) -> Result<(ProvingKey<Curve>, ConstraintM
Ok(proving_key_and_matrices)
}

pub fn calculate_rln_witness<I: IntoIterator<Item = (String, Vec<BigInt>)>>(inputs: I) -> Vec<Fr> {
calc_witness(inputs, GRAPH_BYTES)
}

// Loads the proving key
pub fn zkey_from_folder() -> &'static (ProvingKey<Curve>, ConstraintMatrices<Fr>) {
&ZKEY
Expand Down Expand Up @@ -121,6 +117,17 @@ pub fn check_vk_from_zkey(verifying_key: VerifyingKey<Curve>) -> Result<()> {
}
}

pub fn calculate_rln_witness<I: IntoIterator<Item = (String, Vec<BigInt>)>>(
inputs: I,
graph_data: &[u8],
) -> Vec<Fr> {
calc_witness(inputs, graph_data)
}

pub fn graph_from_folder() -> &'static [u8] {
GRAPH_BYTES
}

////////////////////////////////////////////////////////
// Functions and structs from [arkz-key](https://github.com/zkmopro/ark-zkey/blob/main/src/lib.rs#L106)
// without print and allow to choose between compressed and uncompressed arkzkey
Expand Down
9 changes: 8 additions & 1 deletion rln/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,15 @@ pub extern "C" fn new_with_params(
tree_height: usize,
zkey_buffer: *const Buffer,
vk_buffer: *const Buffer,
graph_data: *const Buffer,
tree_config: *const Buffer,
ctx: *mut *mut RLN,
) -> bool {
match RLN::new_with_params(
tree_height,
zkey_buffer.process().to_vec(),
vk_buffer.process().to_vec(),
graph_data.process().to_vec(),
tree_config.process(),
) {
Ok(rln) => {
Expand All @@ -256,9 +258,14 @@ pub extern "C" fn new_with_params(
pub extern "C" fn new_with_params(
zkey_buffer: *const Buffer,
vk_buffer: *const Buffer,
graph_buffer: *const Buffer,
ctx: *mut *mut RLN,
) -> bool {
match RLN::new_with_params(zkey_buffer.process().to_vec(), vk_buffer.process().to_vec()) {
match RLN::new_with_params(
zkey_buffer.process().to_vec(),
vk_buffer.process().to_vec(),
graph_buffer.process().to_vec(),
) {
Ok(rln) => {
unsafe { *ctx = Box::into_raw(Box::new(rln)) };
true
Expand Down
3 changes: 2 additions & 1 deletion rln/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ pub fn inputs_for_witness_calculation(
pub fn generate_proof(
proving_key: &(ProvingKey<Curve>, ConstraintMatrices<Fr>),
rln_witness: &RLNWitnessInput,
graph_data: &[u8],
) -> Result<ArkProof<Curve>, ProofError> {
let inputs = inputs_for_witness_calculation(rln_witness)?
.into_iter()
Expand All @@ -635,7 +636,7 @@ pub fn generate_proof(
// If in debug mode, we measure and later print time take to compute witness
#[cfg(test)]
let now = Instant::now();
let full_assignment = calculate_rln_witness(inputs);
let full_assignment = calculate_rln_witness(inputs, graph_data);

#[cfg(test)]
println!("witness generation took: {:.2?}", now.elapsed());
Expand Down
26 changes: 18 additions & 8 deletions rln/src/public.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/// This is the main public API for RLN module. It is used by the FFI, and should be
/// used by tests etc. as well
use crate::circuit::{
vk_from_folder, vk_from_raw, zkey_from_folder, zkey_from_raw, Curve, Fr, TEST_TREE_HEIGHT,
graph_from_folder, vk_from_folder, vk_from_raw, zkey_from_folder, zkey_from_raw, Curve, Fr,
TEST_TREE_HEIGHT,
};
use crate::hashers::{hash_to_field, poseidon_hash as utils_poseidon_hash};
use crate::poseidon_tree::PoseidonTree;
Expand Down Expand Up @@ -31,6 +32,7 @@ pub const RLN_IDENTIFIER: &[u8] = b"zerokit/rln/010203040506070809";
pub struct RLN {
proving_key: (ProvingKey<Curve>, ConstraintMatrices<Fr>),
pub(crate) verification_key: VerifyingKey<Curve>,
pub(crate) graph_data: Vec<u8>,
#[cfg(not(feature = "stateless"))]
pub(crate) tree: PoseidonTree,
}
Expand Down Expand Up @@ -62,8 +64,8 @@ impl RLN {
let tree_config = rln_config["tree_config"].to_string();

let proving_key = zkey_from_folder();

let verification_key = vk_from_folder();
let graph_data = graph_from_folder();

let tree_config: <PoseidonTree as ZerokitMerkleTree>::Config = if tree_config.is_empty() {
<PoseidonTree as ZerokitMerkleTree>::Config::default()
Expand All @@ -81,6 +83,7 @@ impl RLN {
Ok(RLN {
proving_key: proving_key.to_owned(),
verification_key: verification_key.to_owned(),
graph_data: graph_data.to_vec(),
#[cfg(not(feature = "stateless"))]
tree,
})
Expand All @@ -99,10 +102,12 @@ impl RLN {
pub fn new() -> Result<RLN> {
let proving_key = zkey_from_folder();
let verification_key = vk_from_folder();
let graph_data = graph_from_folder();

Ok(RLN {
proving_key: proving_key.to_owned(),
verification_key: verification_key.to_owned(),
graph_data: graph_data.to_vec(),
})
}

Expand All @@ -123,7 +128,7 @@ impl RLN {
/// let resources_folder = "./resources/tree_height_20/";
///
/// let mut resources: Vec<Vec<u8>> = Vec::new();
/// for filename in ["rln_final.zkey", "verification_key.arkvkey"] {
/// for filename in ["rln_final.zkey", "verification_key.arkvkey", "graph.bin"] {
/// let fullpath = format!("{resources_folder}{filename}");
/// let mut file = File::open(&fullpath).expect("no file found");
/// let metadata = std::fs::metadata(&fullpath).expect("unable to read metadata");
Expand All @@ -139,6 +144,7 @@ impl RLN {
/// tree_height,
/// resources[0].clone(),
/// resources[1].clone(),
/// resources[2].clone(),
/// tree_config_buffer,
/// );
/// ```
Expand All @@ -147,6 +153,7 @@ impl RLN {
tree_height: usize,
zkey_vec: Vec<u8>,
vk_vec: Vec<u8>,
graph_data: Vec<u8>,
mut tree_config_input: R,
) -> Result<RLN> {
let proving_key = zkey_from_raw(&zkey_vec)?;
Expand All @@ -172,6 +179,7 @@ impl RLN {
Ok(RLN {
proving_key,
verification_key,
graph_data,
#[cfg(not(feature = "stateless"))]
tree,
})
Expand All @@ -191,7 +199,7 @@ impl RLN {
/// let resources_folder = "./resources/tree_height_20/";
///
/// let mut resources: Vec<Vec<u8>> = Vec::new();
/// for filename in ["rln_final.zkey", "verification_key.arkvkey"] {
/// for filename in ["rln_final.zkey", "verification_key.arkvkey", "graph.bin"] {
/// let fullpath = format!("{resources_folder}{filename}");
/// let mut file = File::open(&fullpath).expect("no file found");
/// let metadata = std::fs::metadata(&fullpath).expect("unable to read metadata");
Expand All @@ -203,16 +211,18 @@ impl RLN {
/// let mut rln = RLN::new_with_params(
/// resources[0].clone(),
/// resources[1].clone(),
/// resources[2].clone(),
/// );
/// ```
#[cfg(feature = "stateless")]
pub fn new_with_params(zkey_vec: Vec<u8>, vk_vec: Vec<u8>) -> Result<RLN> {
pub fn new_with_params(zkey_vec: Vec<u8>, vk_vec: Vec<u8>, graph_data: Vec<u8>) -> Result<RLN> {
let proving_key = zkey_from_raw(&zkey_vec)?;
let verification_key = vk_from_raw(&vk_vec, &zkey_vec)?;

Ok(RLN {
proving_key,
verification_key,
graph_data,
})
}

Expand Down Expand Up @@ -701,7 +711,7 @@ impl RLN {
input_data.read_to_end(&mut serialized)?;
let (rln_witness, _) = deserialize_witness(&serialized)?;

let proof = generate_proof(&self.proving_key, &rln_witness)?;
let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?;

// Note: we export a serialization of ark-groth16::Proof not semaphore::Proof
proof.serialize_compressed(&mut output_data)?;
Expand Down Expand Up @@ -824,7 +834,7 @@ impl RLN {
let (rln_witness, _) = proof_inputs_to_rln_witness(&mut self.tree, &witness_byte)?;
let proof_values = proof_values_from_witness(&rln_witness)?;

let proof = generate_proof(&self.proving_key, &rln_witness)?;
let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?;

// Note: we export a serialization of ark-groth16::Proof not semaphore::Proof
// This proof is compressed, i.e. 128 bytes long
Expand All @@ -848,7 +858,7 @@ impl RLN {
let (rln_witness, _) = deserialize_witness(&witness_byte)?;
let proof_values = proof_values_from_witness(&rln_witness)?;

let proof = generate_proof(&self.proving_key, &rln_witness)?;
let proof = generate_proof(&self.proving_key, &rln_witness, &self.graph_data)?;

// Note: we export a serialization of ark-groth16::Proof not semaphore::Proof
// This proof is compressed, i.e. 128 bytes long
Expand Down
11 changes: 11 additions & 0 deletions rln/tests/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,16 @@ mod test {
let zkey_data = &Buffer::from(&zkey_buffer[..]);
let vk_data = &Buffer::from(&vk_buffer[..]);

let graph_data = "./resources/tree_height_20/graph.bin";
let mut graph_file = File::open(&graph_data).expect("no file found");
let metadata = std::fs::metadata(&graph_data).expect("unable to read metadata");
let mut graph_buffer = vec![0; metadata.len() as usize];
graph_file
.read_exact(&mut graph_buffer)
.expect("buffer overflow");

let graph_data = &Buffer::from(&graph_buffer[..]);

// Creating a RLN instance passing the raw data
let mut rln_pointer_raw_bytes = MaybeUninit::<*mut RLN>::uninit();
let tree_config = "".to_string();
Expand All @@ -436,6 +446,7 @@ mod test {
TEST_TREE_HEIGHT,
zkey_data,
vk_data,
graph_data,
tree_config_buffer,
rln_pointer_raw_bytes.as_mut_ptr(),
);
Expand Down
9 changes: 5 additions & 4 deletions rln/tests/protocol.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(test)]
mod test {
use ark_ff::BigInt;
use rln::circuit::zkey_from_folder;
use rln::circuit::{graph_from_folder, zkey_from_folder};
use rln::circuit::{vk_from_folder, Fr, TEST_TREE_HEIGHT};
use rln::hashers::{hash_to_field, poseidon_hash};
use rln::poseidon_tree::PoseidonTree;
Expand Down Expand Up @@ -129,15 +129,15 @@ mod test {
// We generate all relevant keys
let proving_key = zkey_from_folder();
let verification_key = vk_from_folder();

let graph_data = graph_from_folder();
// We compute witness from the json input
let rln_witness = get_test_witness();
let rln_witness_json = rln_witness_to_json(&rln_witness).unwrap();
let rln_witness_deser = rln_witness_from_json(rln_witness_json).unwrap();
assert_eq!(rln_witness_deser, rln_witness);

// Let's generate a zkSNARK proof
let proof = generate_proof(&proving_key, &rln_witness_deser).unwrap();
let proof = generate_proof(&proving_key, &rln_witness_deser, &graph_data).unwrap();
let proof_values = proof_values_from_witness(&rln_witness_deser).unwrap();

// Let's verify the proof
Expand All @@ -157,9 +157,10 @@ mod test {
// We generate all relevant keys
let proving_key = zkey_from_folder();
let verification_key = vk_from_folder();
let graph_data = graph_from_folder();

// Let's generate a zkSNARK proof
let proof = generate_proof(&proving_key, &rln_witness_deser).unwrap();
let proof = generate_proof(&proving_key, &rln_witness_deser, &graph_data).unwrap();

let proof_values = proof_values_from_witness(&rln_witness_deser).unwrap();

Expand Down

0 comments on commit de9c0d5

Please sign in to comment.