mirror of
https://github.com/vacp2p/zerokit.git
synced 2026-01-09 21:58:06 -05:00
feat(rln): Add custom iden3 graph data support for RLN (#286)
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
This commit is contained in:
committed by
GitHub
parent
5c60ec7cce
commit
de9c0d5072
@@ -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)?;
|
||||
@@ -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 {
|
||||
@@ -82,6 +83,7 @@ fn main() -> Result<()> {
|
||||
tree_height,
|
||||
resources[0].clone(),
|
||||
resources[1].clone(),
|
||||
resources[2].clone(),
|
||||
Cursor::new(json!({}).to_string()),
|
||||
)?)
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -230,6 +230,7 @@ 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 {
|
||||
@@ -237,6 +238,7 @@ pub extern "C" fn 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) => {
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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,
|
||||
})
|
||||
@@ -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(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
@@ -139,6 +144,7 @@ impl RLN {
|
||||
/// tree_height,
|
||||
/// resources[0].clone(),
|
||||
/// resources[1].clone(),
|
||||
/// resources[2].clone(),
|
||||
/// tree_config_buffer,
|
||||
/// );
|
||||
/// ```
|
||||
@@ -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)?;
|
||||
@@ -172,6 +179,7 @@ impl RLN {
|
||||
Ok(RLN {
|
||||
proving_key,
|
||||
verification_key,
|
||||
graph_data,
|
||||
#[cfg(not(feature = "stateless"))]
|
||||
tree,
|
||||
})
|
||||
@@ -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");
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
@@ -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(),
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
@@ -129,7 +129,7 @@ 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();
|
||||
@@ -137,7 +137,7 @@ mod test {
|
||||
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
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user