diff --git a/rln-cli/src/examples/relay.rs b/rln-cli/src/examples/relay.rs index 46bb092..43974f9 100644 --- a/rln-cli/src/examples/relay.rs +++ b/rln-cli/src/examples/relay.rs @@ -8,9 +8,9 @@ use color_eyre::{eyre::eyre, Result}; use rln::{ circuit::{Fr, TEST_TREE_HEIGHT}, hashers::{hash_to_field, poseidon_hash}, - protocol::{deserialize_field_element, keygen, prepare_verify_input}, + protocol::{keygen, prepare_prove_input, prepare_verify_input}, public::RLN, - utils::{bytes_le_to_fr, fr_to_bytes_le, generate_input_buffer, normalize_usize}, + utils::{bytes_le_to_fr, fr_to_bytes_le, generate_input_buffer}, }; const MESSAGE_LIMIT: u32 = 1; @@ -118,26 +118,14 @@ impl RLNSystem { None => return Err(eyre!("user index {user_index} not found")), }; - let mut input_buffer = Cursor::new(Vec::new()); - self.rln.get_leaf(user_index, &mut input_buffer)?; - let stored_rate_commitment = deserialize_field_element(input_buffer.into_inner()); - - let expected_rate_commitment = - poseidon_hash(&[identity.id_commitment, Fr::from(MESSAGE_LIMIT)]); - - if stored_rate_commitment != expected_rate_commitment { - return Err(eyre!("user mismatch in merkle tree")); - } - - let mut serialized = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity.identity_secret_hash)); - serialized.append(&mut normalize_usize(user_index)); - serialized.append(&mut fr_to_bytes_le(&Fr::from(MESSAGE_LIMIT))); - serialized.append(&mut fr_to_bytes_le(&Fr::from(message_id))); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.as_bytes().to_vec()); - + let serialized = prepare_prove_input( + identity.identity_secret_hash, + user_index, + Fr::from(MESSAGE_LIMIT), + Fr::from(message_id), + external_nullifier, + signal.as_bytes(), + ); let mut input_buffer = Cursor::new(serialized); let mut output_buffer = Cursor::new(Vec::new()); self.rln diff --git a/rln/src/protocol.rs b/rln/src/protocol.rs index 1738c93..d5b975c 100644 --- a/rln/src/protocol.rs +++ b/rln/src/protocol.rs @@ -100,18 +100,26 @@ pub fn deserialize_identity_tuple(serialized: Vec) -> (Fr, Fr, Fr, Fr) { /// # Errors /// /// Returns an error if `rln_witness.message_id` is not within `rln_witness.user_message_limit`. +/// input data is [ identity_secret<32> | user_message_limit<32> | message_id<32> | path_elements[<32>] | identity_path_index<8> | x<32> | external_nullifier<32> ] pub fn serialize_witness(rln_witness: &RLNWitnessInput) -> Result> { + // Check if message_id is within user_message_limit message_id_range_check(&rln_witness.message_id, &rln_witness.user_message_limit)?; - let mut serialized: Vec = Vec::new(); - - serialized.append(&mut fr_to_bytes_le(&rln_witness.identity_secret)); - serialized.append(&mut fr_to_bytes_le(&rln_witness.user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&rln_witness.message_id)); - serialized.append(&mut vec_fr_to_bytes_le(&rln_witness.path_elements)?); - serialized.append(&mut vec_u8_to_bytes_le(&rln_witness.identity_path_index)?); - serialized.append(&mut fr_to_bytes_le(&rln_witness.x)); - serialized.append(&mut fr_to_bytes_le(&rln_witness.external_nullifier)); + // Calculate capacity for Vec: + // - 5 fixed field elements: identity_secret, user_message_limit, message_id, x, external_nullifier + // - variable number of path elements + // - identity_path_index (variable size) + let mut serialized: Vec = Vec::with_capacity( + fr_byte_size() * (5 + rln_witness.path_elements.len()) + + rln_witness.identity_path_index.len(), + ); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_witness.identity_secret)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_witness.user_message_limit)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_witness.message_id)); + serialized.extend_from_slice(&vec_fr_to_bytes_le(&rln_witness.path_elements)?); + serialized.extend_from_slice(&vec_u8_to_bytes_le(&rln_witness.identity_path_index)?); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_witness.x)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_witness.external_nullifier)); Ok(serialized) } @@ -306,14 +314,17 @@ pub fn proof_values_from_witness(rln_witness: &RLNWitnessInput) -> Result | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] pub fn serialize_proof_values(rln_proof_values: &RLNProofValues) -> Vec { - let mut serialized: Vec = Vec::new(); + // Calculate capacity for Vec: + // 5 field elements: root, external_nullifier, x, y, nullifier + let mut serialized = Vec::with_capacity(fr_byte_size() * 5); - serialized.append(&mut fr_to_bytes_le(&rln_proof_values.root)); - serialized.append(&mut fr_to_bytes_le(&rln_proof_values.external_nullifier)); - serialized.append(&mut fr_to_bytes_le(&rln_proof_values.x)); - serialized.append(&mut fr_to_bytes_le(&rln_proof_values.y)); - serialized.append(&mut fr_to_bytes_le(&rln_proof_values.nullifier)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_proof_values.root)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_proof_values.external_nullifier)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_proof_values.x)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_proof_values.y)); + serialized.extend_from_slice(&fr_to_bytes_le(&rln_proof_values.nullifier)); serialized } @@ -350,30 +361,43 @@ pub fn deserialize_proof_values(serialized: &[u8]) -> (RLNProofValues, usize) { ) } +// input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] pub fn prepare_prove_input( identity_secret: Fr, id_index: usize, + user_message_limit: Fr, + message_id: Fr, external_nullifier: Fr, signal: &[u8], ) -> Vec { - let mut serialized: Vec = Vec::new(); + // Calculate capacity for Vec: + // - 4 field elements: identity_secret, user_message_limit, message_id, external_nullifier + // - 16 bytes for two normalized usize values (id_index<8> + signal_len<8>) + // - variable length signal data + let mut serialized = Vec::with_capacity(fr_byte_size() * 4 + 16 + signal.len()); // length of 4 fr elements + 16 bytes (id_index + len) + signal length - serialized.append(&mut fr_to_bytes_le(&identity_secret)); - serialized.append(&mut normalize_usize(id_index)); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + serialized.extend_from_slice(&fr_to_bytes_le(&identity_secret)); + serialized.extend_from_slice(&normalize_usize(id_index)); + serialized.extend_from_slice(&fr_to_bytes_le(&user_message_limit)); + serialized.extend_from_slice(&fr_to_bytes_le(&message_id)); + serialized.extend_from_slice(&fr_to_bytes_le(&external_nullifier)); + serialized.extend_from_slice(&normalize_usize(signal.len())); + serialized.extend_from_slice(signal); serialized } -#[allow(clippy::redundant_clone)] +// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] pub fn prepare_verify_input(proof_data: Vec, signal: &[u8]) -> Vec { - let mut serialized: Vec = Vec::new(); + // Calculate capacity for Vec: + // - proof_data contains the proof and proof values (proof<128> + root<32> + external_nullifier<32> + x<32> + y<32> + nullifier<32>) + // - 8 bytes for normalized signal length value (signal_len<8>) + // - variable length signal data + let mut serialized = Vec::with_capacity(proof_data.len() + 8 + signal.len()); - serialized.append(&mut proof_data.clone()); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + serialized.extend(proof_data); + serialized.extend_from_slice(&normalize_usize(signal.len())); + serialized.extend_from_slice(signal); serialized } diff --git a/rln/src/public.rs b/rln/src/public.rs index 8e50355..d9637e6 100644 --- a/rln/src/public.rs +++ b/rln/src/public.rs @@ -793,26 +793,25 @@ impl RLN { /// let mut buffer = Cursor::new(fr_to_bytes_le(&rate_commitment)); /// rln.set_leaf(identity_index, &mut buffer).unwrap(); /// - /// // We generate a random signal - /// let mut rng = rand::thread_rng(); - /// let signal: [u8; 32] = rng.gen(); - /// /// // We generate a random epoch /// let epoch = hash_to_field(b"test-epoch"); /// // We generate a random rln_identifier /// let rln_identifier = hash_to_field(b"test-rln-identifier"); - /// let external_nullifier = poseidon_hash(&[epoch, rln_identifier]); + /// // We generate a external nullifier + /// let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + /// // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + /// let message_id = Fr::from(1); /// /// // We prepare input for generate_rln_proof API /// // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] - /// let mut serialized: Vec = Vec::new(); - /// serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - /// serialized.append(&mut normalize_usize(identity_index)); - /// serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - /// serialized.append(&mut fr_to_bytes_le(&Fr::from(1))); // message_id - /// serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - /// serialized.append(&mut normalize_usize(signal_len).resize(8,0)); - /// serialized.append(&mut signal.to_vec()); + /// let prove_input = prepare_prove_input( + /// identity_secret_hash, + /// identity_index, + /// user_message_limit, + /// message_id, + /// external_nullifier, + /// &signal, + /// ); /// /// let mut input_buffer = Cursor::new(serialized); /// let mut output_buffer = Cursor::new(Vec::::new()); @@ -887,10 +886,9 @@ impl RLN { /// // We prepare input for verify_rln_proof API /// // input_data is `[ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal]` /// // that is [ proof_data || signal_len<8> | signal ] - /// proof_data.append(&mut normalize_usize(signal_len)); - /// proof_data.append(&mut signal.to_vec()); + /// let verify_input = prepare_verify_input(proof_data, &signal); /// - /// let mut input_buffer = Cursor::new(proof_data); + /// let mut input_buffer = Cursor::new(verify_input); /// let verified = rln.verify_rln_proof(&mut input_buffer).unwrap(); /// /// assert!(verified); @@ -966,7 +964,7 @@ impl RLN { /// roots_serialized.append(&mut fr_to_bytes_le(&root)); /// roots_buffer = Cursor::new(roots_serialized.clone()); /// let verified = rln - /// .verify_with_roots(&mut input_buffer.clone(), &mut roots_buffer) + /// .verify_with_roots(&mut input_buffer, &mut roots_buffer) /// .unwrap(); /// /// assert!(verified); diff --git a/rln/src/public_api_tests.rs b/rln/src/public_api_tests.rs index 37b95d9..d92df39 100644 --- a/rln/src/public_api_tests.rs +++ b/rln/src/public_api_tests.rs @@ -9,28 +9,28 @@ use std::str::FromStr; use serde_json::{json, Value}; -fn fq_from_str(s: String) -> ark_bn254::Fq { +fn fq_from_str(s: &str) -> ark_bn254::Fq { ark_bn254::Fq::from_str(&s).unwrap() } fn g1_from_str(g1: &[String]) -> ark_bn254::G1Affine { - let x = fq_from_str(g1[0].clone()); - let y = fq_from_str(g1[1].clone()); - let z = fq_from_str(g1[2].clone()); + let x = fq_from_str(&g1[0]); + let y = fq_from_str(&g1[1]); + let z = fq_from_str(&g1[2]); ark_bn254::G1Affine::from(ark_bn254::G1Projective::new(x, y, z)) } fn g2_from_str(g2: &[Vec]) -> ark_bn254::G2Affine { - let c0 = fq_from_str(g2[0][0].clone()); - let c1 = fq_from_str(g2[0][1].clone()); + let c0 = fq_from_str(&g2[0][0]); + let c1 = fq_from_str(&g2[0][1]); let x = ark_bn254::Fq2::new(c0, c1); - let c0 = fq_from_str(g2[1][0].clone()); - let c1 = fq_from_str(g2[1][1].clone()); + let c0 = fq_from_str(&g2[1][0]); + let c1 = fq_from_str(&g2[1][1]); let y = ark_bn254::Fq2::new(c0, c1); - let c0 = fq_from_str(g2[2][0].clone()); - let c1 = fq_from_str(g2[2][1].clone()); + let c0 = fq_from_str(&g2[2][0]); + let c1 = fq_from_str(&g2[2][1]); let z = ark_bn254::Fq2::new(c0, c1); ark_bn254::G2Affine::from(ark_bn254::G2Projective::new(x, y, z)) @@ -619,35 +619,36 @@ mod tree_test { let epoch = hash_to_field(b"test-epoch"); // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier + let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We prepare input for generate_rln_proof API - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized.append(&mut normalize_usize(identity_index)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&Fr::from(1))); - serialized.append(&mut fr_to_bytes_le(&utils_poseidon_hash(&[ - epoch, - rln_identifier, - ]))); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] + let prove_input = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal, + ); - let mut input_buffer = Cursor::new(serialized); + let mut input_buffer = Cursor::new(prove_input); let mut output_buffer = Cursor::new(Vec::::new()); rln.generate_rln_proof(&mut input_buffer, &mut output_buffer) .unwrap(); // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = output_buffer.into_inner(); + let proof_data = output_buffer.into_inner(); // We prepare input for verify_rln_proof API - // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] + // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] // that is [ proof_data || signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); + let verify_input = prepare_verify_input(proof_data, &signal); - let mut input_buffer = Cursor::new(proof_data); + let mut input_buffer = Cursor::new(verify_input); let verified = rln.verify_rln_proof(&mut input_buffer).unwrap(); assert!(verified); @@ -690,22 +691,23 @@ mod tree_test { let epoch = hash_to_field(b"test-epoch"); // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier + let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We prepare input for generate_rln_proof API - // input_data is [ identity_secret<32> | id_index<8> | epoch<32> | signal_len<8> | signal ] - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized.append(&mut normalize_usize(identity_index)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&Fr::from(1))); - serialized.append(&mut fr_to_bytes_le(&utils_poseidon_hash(&[ - epoch, - rln_identifier, - ]))); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] + let prove_input = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal, + ); - let mut input_buffer = Cursor::new(serialized); + let mut input_buffer = Cursor::new(prove_input); // We read input RLN witness and we serialize_compressed it let mut witness_byte: Vec = Vec::new(); @@ -720,16 +722,15 @@ mod tree_test { rln.generate_rln_proof_with_witness(&mut input_buffer, &mut output_buffer) .unwrap(); - // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = output_buffer.into_inner(); + // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] + let proof_data = output_buffer.into_inner(); // We prepare input for verify_rln_proof API - // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] + // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] // that is [ proof_data || signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); + let verify_input = prepare_verify_input(proof_data, &signal); - let mut input_buffer = Cursor::new(proof_data); + let mut input_buffer = Cursor::new(verify_input); let verified = rln.verify_rln_proof(&mut input_buffer).unwrap(); assert!(verified); @@ -773,33 +774,35 @@ mod tree_test { let epoch = hash_to_field(b"test-epoch"); // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We prepare input for generate_rln_proof API - // input_data is [ identity_secret<32> | id_index<8> | external_nullifier<32> | user_message_limit<32> | message_id<32> | signal_len<8> | signal ] - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized.append(&mut normalize_usize(identity_index)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&Fr::from(1))); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] + let prove_input = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal, + ); - let mut input_buffer = Cursor::new(serialized); + let mut input_buffer = Cursor::new(prove_input); let mut output_buffer = Cursor::new(Vec::::new()); rln.generate_rln_proof(&mut input_buffer, &mut output_buffer) .unwrap(); - // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = output_buffer.into_inner(); + // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] + let proof_data = output_buffer.into_inner(); - // We prepare input for verify_rln_proof API - // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] + // input_data is [ proof<128> |// We prepare input for verify_rln_proof API root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] // that is [ proof_data || signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); - let input_buffer = Cursor::new(proof_data); + let verify_input = prepare_verify_input(proof_data, &signal); + + let mut input_buffer = Cursor::new(verify_input); // If no roots is provided, proof validation is skipped and if the remaining proof values are valid, the proof will be correctly verified let mut roots_serialized: Vec = Vec::new(); @@ -828,9 +831,9 @@ mod tree_test { // We add the real root and we check if now the proof is verified roots_serialized.append(&mut fr_to_bytes_le(&root)); - roots_buffer = Cursor::new(roots_serialized.clone()); + roots_buffer = Cursor::new(roots_serialized); let verified = rln - .verify_with_roots(&mut input_buffer.clone(), &mut roots_buffer) + .verify_with_roots(&mut input_buffer, &mut roots_buffer) .unwrap(); assert!(verified); @@ -846,7 +849,6 @@ mod tree_test { // Generate identity pair let (identity_secret_hash, id_commitment) = keygen(); let user_message_limit = Fr::from(100); - let message_id = Fr::from(0); let rate_commitment = utils_poseidon_hash(&[id_commitment, user_message_limit]); // We set as leaf id_commitment after storing its index @@ -864,41 +866,49 @@ mod tree_test { let epoch = hash_to_field(b"test-epoch"); // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We generate two proofs using same epoch but different signals. // We prepare input for generate_rln_proof API - let mut serialized1: Vec = Vec::new(); - serialized1.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized1.append(&mut normalize_usize(identity_index)); - serialized1.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized1.append(&mut fr_to_bytes_le(&message_id)); - serialized1.append(&mut fr_to_bytes_le(&external_nullifier)); + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] + let prove_input1 = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal1, + ); - // The first part is the same for both proof input, so we clone - let mut serialized2 = serialized1.clone(); - - // We attach the first signal to the first proof input - serialized1.append(&mut normalize_usize(signal1.len())); - serialized1.append(&mut signal1.to_vec()); - - // We attach the second signal to the second proof input - serialized2.append(&mut normalize_usize(signal2.len())); - serialized2.append(&mut signal2.to_vec()); + let prove_input2 = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal2, + ); // We generate the first proof - let mut input_buffer = Cursor::new(serialized1); + let mut input_buffer = Cursor::new(prove_input1); let mut output_buffer = Cursor::new(Vec::::new()); rln.generate_rln_proof(&mut input_buffer, &mut output_buffer) .unwrap(); + + // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] let proof_data_1 = output_buffer.into_inner(); // We generate the second proof - let mut input_buffer = Cursor::new(serialized2); + let mut input_buffer = Cursor::new(prove_input2); let mut output_buffer = Cursor::new(Vec::::new()); rln.generate_rln_proof(&mut input_buffer, &mut output_buffer) .unwrap(); + + // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] let proof_data_2 = output_buffer.into_inner(); let mut input_proof_data_1 = Cursor::new(proof_data_1.clone()); @@ -935,25 +945,24 @@ mod tree_test { let signal3: [u8; 32] = rng.gen(); // We prepare proof input. Note that epoch is the same as before - let mut serialized3: Vec = Vec::new(); - serialized3.append(&mut fr_to_bytes_le(&identity_secret_hash_new)); - serialized3.append(&mut normalize_usize(identity_index_new)); - serialized3.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized3.append(&mut fr_to_bytes_le(&message_id)); - serialized3.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized3.append(&mut normalize_usize(signal3.len())); - serialized3.append(&mut signal3.to_vec()); + let prove_input3 = prepare_prove_input( + identity_secret_hash, + identity_index_new, + user_message_limit, + message_id, + external_nullifier, + &signal3, + ); // We generate the proof - let mut input_buffer = Cursor::new(serialized3); + let mut input_buffer = Cursor::new(prove_input3); let mut output_buffer = Cursor::new(Vec::::new()); rln.generate_rln_proof(&mut input_buffer, &mut output_buffer) .unwrap(); let proof_data_3 = output_buffer.into_inner(); // We attempt to recover the secret using share1 (coming from identity_secret_hash) and share3 (coming from identity_secret_hash_new) - - let mut input_proof_data_1 = Cursor::new(proof_data_1.clone()); + let mut input_proof_data_1 = Cursor::new(proof_data_1); let mut input_proof_data_3 = Cursor::new(proof_data_3); let mut output_buffer = Cursor::new(Vec::::new()); rln.recover_id_secret( @@ -1022,7 +1031,7 @@ mod stateless_test { let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); // We prepare input for generate_rln_proof API - // input_data is [ identity_secret<32> | id_index<8> | external_nullifier<32> | user_message_limit<32> | message_id<32> | signal_len<8> | signal ] + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] let x = hash_to_field(&signal); let merkle_proof = tree.proof(identity_index).expect("proof should exist"); @@ -1043,15 +1052,15 @@ mod stateless_test { rln.generate_rln_proof_with_witness(&mut input_buffer, &mut output_buffer) .unwrap(); - // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = output_buffer.into_inner(); + // output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] + let proof_data = output_buffer.into_inner(); // We prepare input for verify_rln_proof API // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] // that is [ proof_data || signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); - let input_buffer = Cursor::new(proof_data); + let verify_input = prepare_verify_input(proof_data, &signal); + + let mut input_buffer = Cursor::new(verify_input); // If no roots is provided, proof validation is skipped and if the remaining proof values are valid, the proof will be correctly verified let mut roots_serialized: Vec = Vec::new(); @@ -1078,9 +1087,9 @@ mod stateless_test { // We add the real root and we check if now the proof is verified roots_serialized.append(&mut fr_to_bytes_le(&root)); - roots_buffer = Cursor::new(roots_serialized.clone()); + roots_buffer = Cursor::new(roots_serialized); let verified = rln - .verify_with_roots(&mut input_buffer.clone(), &mut roots_buffer) + .verify_with_roots(&mut input_buffer, &mut roots_buffer) .unwrap(); assert!(verified); @@ -1205,7 +1214,7 @@ mod stateless_test { .unwrap(); let proof_data_3 = output_buffer.into_inner(); - let mut input_proof_data_1 = Cursor::new(proof_data_1.clone()); + let mut input_proof_data_1 = Cursor::new(proof_data_1); let mut input_proof_data_3 = Cursor::new(proof_data_3); let mut output_buffer = Cursor::new(Vec::::new()); rln.recover_id_secret( diff --git a/rln/src/utils.rs b/rln/src/utils.rs index 6b444c9..71dbc01 100644 --- a/rln/src/utils.rs +++ b/rln/src/utils.rs @@ -7,18 +7,19 @@ use num_bigint::{BigInt, BigUint}; use num_traits::Num; use serde_json::json; use std::io::Cursor; -use std::iter::Extend; +#[inline(always)] pub fn to_bigint(el: &Fr) -> Result { - let res: BigUint = (*el).into(); - Ok(res.into()) + Ok(BigUint::from(*el).into()) } +#[inline(always)] pub fn fr_byte_size() -> usize { let mbs = ::MODULUS_BIT_SIZE; ((mbs + 64 - (mbs % 64)) / 8) as usize } +#[inline(always)] pub fn str_to_fr(input: &str, radix: u32) -> Result { if !(radix == 10 || radix == 16) { return Err(Report::msg("wrong radix")); @@ -37,6 +38,7 @@ pub fn str_to_fr(input: &str, radix: u32) -> Result { } } +#[inline(always)] pub fn bytes_le_to_fr(input: &[u8]) -> (Fr, usize) { let el_size = fr_byte_size(); ( @@ -45,77 +47,50 @@ pub fn bytes_le_to_fr(input: &[u8]) -> (Fr, usize) { ) } -pub fn bytes_be_to_fr(input: &[u8]) -> (Fr, usize) { - let el_size = fr_byte_size(); - ( - Fr::from(BigUint::from_bytes_be(&input[0..el_size])), - el_size, - ) -} - +#[inline(always)] pub fn fr_to_bytes_le(input: &Fr) -> Vec { let input_biguint: BigUint = (*input).into(); let mut res = input_biguint.to_bytes_le(); //BigUint conversion ignores most significant zero bytes. We restore them otherwise serialization will fail (length % 8 != 0) - while res.len() != fr_byte_size() { - res.push(0); - } - res -} - -pub fn fr_to_bytes_be(input: &Fr) -> Vec { - let input_biguint: BigUint = (*input).into(); - let mut res = input_biguint.to_bytes_be(); - // BigUint conversion ignores most significant zero bytes. We restore them otherwise serialization might fail - // Fr elements are stored using 64 bits nimbs - while res.len() != fr_byte_size() { - res.insert(0, 0); - } + res.resize(fr_byte_size(), 0); res } +#[inline(always)] pub fn vec_fr_to_bytes_le(input: &[Fr]) -> Result> { - let mut bytes: Vec = Vec::new(); - //We store the vector length - bytes.extend(u64::try_from(input.len())?.to_le_bytes().to_vec()); + // Calculate capacity for Vec: + // - 8 bytes for normalized vector length (usize) + // - each Fr element requires fr_byte_size() bytes (typically 32 bytes) + let mut bytes = Vec::with_capacity(8 + input.len() * fr_byte_size()); + + // We store the vector length + bytes.extend_from_slice(&normalize_usize(input.len())); // We store each element - input.iter().for_each(|el| bytes.extend(fr_to_bytes_le(el))); - - Ok(bytes) -} - -pub fn vec_fr_to_bytes_be(input: &[Fr]) -> Result> { - let mut bytes: Vec = Vec::new(); - //We store the vector length - bytes.extend(u64::try_from(input.len())?.to_be_bytes().to_vec()); - - // We store each element - input.iter().for_each(|el| bytes.extend(fr_to_bytes_be(el))); + for el in input { + bytes.extend_from_slice(&fr_to_bytes_le(el)); + } Ok(bytes) } +#[inline(always)] pub fn vec_u8_to_bytes_le(input: &[u8]) -> Result> { - let mut bytes: Vec = Vec::new(); - //We store the vector length - bytes.extend(u64::try_from(input.len())?.to_le_bytes().to_vec()); + // Calculate capacity for Vec: + // - 8 bytes for normalized vector length (usize) + // - variable length input data + let mut bytes = Vec::with_capacity(8 + input.len()); - bytes.extend(input); - - Ok(bytes) -} - -pub fn vec_u8_to_bytes_be(input: Vec) -> Result> { - let mut bytes: Vec = Vec::new(); - //We store the vector length - bytes.extend(u64::try_from(input.len())?.to_be_bytes().to_vec()); - - bytes.extend(input); + // We store the vector length + bytes.extend_from_slice(&normalize_usize(input.len())); + + // We store the input + bytes.extend_from_slice(input); Ok(bytes) } +#[inline(always)] pub fn bytes_le_to_vec_u8(input: &[u8]) -> Result<(Vec, usize)> { let mut read: usize = 0; @@ -128,19 +103,7 @@ pub fn bytes_le_to_vec_u8(input: &[u8]) -> Result<(Vec, usize)> { Ok((res, read)) } -pub fn bytes_be_to_vec_u8(input: &[u8]) -> Result<(Vec, usize)> { - let mut read: usize = 0; - - let len = usize::try_from(u64::from_be_bytes(input[0..8].try_into()?))?; - read += 8; - - let res = input[8..8 + len].to_vec(); - - read += res.len(); - - Ok((res, read)) -} - +#[inline(always)] pub fn bytes_le_to_vec_fr(input: &[u8]) -> Result<(Vec, usize)> { let mut read: usize = 0; let mut res: Vec = Vec::new(); @@ -158,29 +121,7 @@ pub fn bytes_le_to_vec_fr(input: &[u8]) -> Result<(Vec, usize)> { Ok((res, read)) } -pub fn bytes_be_to_vec_fr(input: &[u8]) -> Result<(Vec, usize)> { - let mut read: usize = 0; - let mut res: Vec = Vec::new(); - - let len = usize::try_from(u64::from_be_bytes(input[0..8].try_into()?))?; - read += 8; - - let el_size = fr_byte_size(); - for i in 0..len { - let (curr_el, _) = bytes_be_to_fr(&input[8 + el_size * i..8 + el_size * (i + 1)]); - res.push(curr_el); - read += el_size; - } - - Ok((res, read)) -} - -pub fn normalize_usize(input: usize) -> Vec { - let mut normalized_usize = input.to_le_bytes().to_vec(); - normalized_usize.resize(8, 0); - normalized_usize -} - +#[inline(always)] pub fn bytes_le_to_vec_usize(input: &[u8]) -> Result> { let nof_elem = usize::try_from(u64::from_le_bytes(input[0..8].try_into()?))?; if nof_elem == 0 { @@ -194,141 +135,12 @@ pub fn bytes_le_to_vec_usize(input: &[u8]) -> Result> { } } -// using for test +#[inline(always)] +pub fn normalize_usize(input: usize) -> [u8; 8] { + input.to_le_bytes() +} + +#[inline(always)] // using for test pub fn generate_input_buffer() -> Cursor { Cursor::new(json!({}).to_string()) } - -/* Old conversion utilities between different libraries data types - -// Conversion Utilities between poseidon-rs Field and arkworks Fr (in order to call directly poseidon-rs' poseidon_hash) - -use ff::{PrimeField as _, PrimeFieldRepr as _}; -use poseidon_rs::Fr as PosFr; - -pub fn fr_to_posfr(value: Fr) -> PosFr { - let mut bytes = [0_u8; 32]; - let byte_vec = value.into_repr().to_bytes_be(); - bytes.copy_from_slice(&byte_vec[..]); - let mut repr = ::Repr::default(); - repr.read_be(&bytes[..]) - .expect("read from correctly sized slice always succeeds"); - PosFr::from_repr(repr).expect("value is always in range") -} - -pub fn posfr_to_fr(value: PosFr) -> Fr { - let mut bytes = [0u8; 32]; - value - .into_repr() - .write_be(&mut bytes[..]) - .expect("write to correctly sized slice always succeeds"); - Fr::from_be_bytes_mod_order(&bytes) -} - - -// Conversion Utilities between semaphore-rs Field and arkworks Fr - -use semaphore::Field; - -pub fn to_fr(el: &Field) -> Fr { - Fr::try_from(*el).unwrap() -} - -pub fn to_field(el: &Fr) -> Field { - (*el).try_into().unwrap() -} - -pub fn vec_to_fr(v: &[Field]) -> Vec { - v.iter().map(|el| to_fr(el)).collect() -} - -pub fn vec_to_field(v: &[Fr]) -> Vec { - v.iter().map(|el| to_field(el)).collect() -} - -pub fn vec_fr_to_field(input: &[Fr]) -> Vec { - input.iter().map(|el| to_field(el)).collect() -} - -pub fn vec_field_to_fr(input: &[Field]) -> Vec { - input.iter().map(|el| to_fr(el)).collect() -} - -pub fn str_to_field(input: String, radix: i32) -> Field { - assert!((radix == 10) || (radix == 16)); - - // We remove any quote present and we trim - let single_quote: char = '\"'; - let input_clean = input.replace(single_quote, ""); - let input_clean = input_clean.trim(); - - if radix == 10 { - Field::from_str(&format!( - "{:01$x}", - BigUint::from_str(input_clean).unwrap(), - 64 - )) - .unwrap() - } else { - let input_clean = input_clean.replace("0x", ""); - Field::from_str(&format!("{:0>64}", &input_clean)).unwrap() - } -} - -pub fn bytes_le_to_field(input: &[u8]) -> (Field, usize) { - let (fr_el, read) = bytes_le_to_fr(input); - (to_field(&fr_el), read) -} - -pub fn bytes_be_to_field(input: &[u8]) -> (Field, usize) { - let (fr_el, read) = bytes_be_to_fr(input); - (to_field(&fr_el), read) -} - - -pub fn field_to_bytes_le(input: &Field) -> Vec { - fr_to_bytes_le(&to_fr(input)) -} - -pub fn field_to_bytes_be(input: &Field) -> Vec { - fr_to_bytes_be(&to_fr(input)) -} - - -pub fn vec_field_to_bytes_le(input: &[Field]) -> Vec { - vec_fr_to_bytes_le(&vec_field_to_fr(input)) -} - -pub fn vec_field_to_bytes_be(input: &[Field]) -> Vec { - vec_fr_to_bytes_be(&vec_field_to_fr(input)) -} - - -pub fn bytes_le_to_vec_field(input: &[u8]) -> (Vec, usize) { - let (vec_fr, read) = bytes_le_to_vec_fr(input); - (vec_fr_to_field(&vec_fr), read) -} - -pub fn bytes_be_to_vec_field(input: &[u8]) -> (Vec, usize) { - let (vec_fr, read) = bytes_be_to_vec_fr(input); - (vec_fr_to_field(&vec_fr), read) -} - -// Arithmetic over Field elements (wrapped over arkworks algebra crate) - -pub fn add(a: &Field, b: &Field) -> Field { - to_field(&(to_fr(a) + to_fr(b))) -} - -pub fn mul(a: &Field, b: &Field) -> Field { - to_field(&(to_fr(a) * to_fr(b))) -} - -pub fn div(a: &Field, b: &Field) -> Field { - to_field(&(to_fr(a) / to_fr(b))) -} - -pub fn inv(a: &Field) -> Field { - to_field(&(Fr::from(1) / to_fr(a))) -} -*/ diff --git a/rln/tests/ffi.rs b/rln/tests/ffi.rs index ccffe57..a2308fa 100644 --- a/rln/tests/ffi.rs +++ b/rln/tests/ffi.rs @@ -486,10 +486,13 @@ mod test { // We generate a random epoch let epoch = hash_to_field(b"test-epoch"); + // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); - let message_id = Fr::from(0); let rate_commitment = utils_poseidon_hash(&[id_commitment, user_message_limit]); // We set as leaf rate_commitment, its index would be equal to no_of_leaves @@ -500,27 +503,25 @@ mod test { // We prepare input for generate_rln_proof API // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized.append(&mut normalize_usize(identity_index)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&message_id)); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); - + let prove_input = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal, + ); // We call generate_rln_proof // result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = rln_proof_gen(rln_pointer, serialized.as_ref()); + let proof_data = rln_proof_gen(rln_pointer, prove_input.as_ref()); // We prepare input for verify_rln_proof API // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] - // that is [ proof_data | signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); + // that is [ proof_data || signal_len<8> | signal ] + let verify_input = prepare_verify_input(proof_data, &signal); // We call verify_rln_proof - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; let success = verify_rln_proof(rln_pointer, input_buffer, proof_is_valid_ptr); @@ -553,11 +554,12 @@ mod test { // We generate a random epoch let epoch = hash_to_field(b"test-epoch"); + // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); - - let user_message_limit = Fr::from(100); - let message_id = Fr::from(0); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We set as leaf rate_commitment, its index would be equal to no_of_leaves let leaf_ser = fr_to_bytes_le(&rate_commitment); @@ -567,24 +569,23 @@ mod test { // We prepare input for generate_rln_proof API // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized.append(&mut normalize_usize(identity_index)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&message_id)); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal.len())); - serialized.append(&mut signal.to_vec()); + let prove_input = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal, + ); // We call generate_rln_proof // result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let mut proof_data = rln_proof_gen(rln_pointer, serialized.as_ref()); + let proof_data = rln_proof_gen(rln_pointer, prove_input.as_ref()); // We prepare input for verify_rln_proof API // input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal ] - // that is [ proof_data | signal_len<8> | signal ] - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); + // that is [ proof_data || signal_len<8> | signal ] + let verify_input = prepare_verify_input(proof_data.clone(), &signal); // We test verify_with_roots @@ -592,7 +593,7 @@ mod test { // In this case, since no root is provided, proof's root check is skipped and proof is verified if other proof values are valid let mut roots_data: Vec = Vec::new(); - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; @@ -606,7 +607,7 @@ mod test { for _ in 0..5 { roots_data.append(&mut fr_to_bytes_le(&Fr::rand(&mut rng))); } - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; @@ -622,7 +623,7 @@ mod test { // We include the root and verify the proof roots_data.append(&mut fr_to_bytes_le(&root)); - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; @@ -643,7 +644,6 @@ mod test { let (identity_secret_hash, id_commitment) = identity_pair_gen(rln_pointer); let user_message_limit = Fr::from(100); - let message_id = Fr::from(0); let rate_commitment = utils_poseidon_hash(&[id_commitment, user_message_limit]); // We set as leaf rate_commitment, its index would be equal to 0 since tree is empty @@ -665,36 +665,40 @@ mod test { // We generate a random epoch let epoch = hash_to_field(b"test-epoch"); + // We generate a random rln_identifier let rln_identifier = hash_to_field(b"test-rln-identifier"); + // We generate a external nullifier let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]); + // We choose a message_id satisfy 0 <= message_id < MESSAGE_LIMIT + let message_id = Fr::from(1); // We prepare input for generate_rln_proof API - // input_data is [ identity_secret<32> | id_index<8> | epoch<32> | signal_len<8> | signal ] - let mut serialized1: Vec = Vec::new(); - serialized1.append(&mut fr_to_bytes_le(&identity_secret_hash)); - serialized1.append(&mut normalize_usize(identity_index)); - serialized1.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized1.append(&mut fr_to_bytes_le(&message_id)); - serialized1.append(&mut fr_to_bytes_le(&external_nullifier)); + // input_data is [ identity_secret<32> | id_index<8> | user_message_limit<32> | message_id<32> | external_nullifier<32> | signal_len<8> | signal ] + let prove_input1 = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal1, + ); - // The first part is the same for both proof input, so we clone - let mut serialized2 = serialized1.clone(); - - // We attach the first signal to the first proof input - serialized1.append(&mut normalize_usize(signal1.len())); - serialized1.append(&mut signal1.to_vec()); - - // We attach the second signal to the first proof input - serialized2.append(&mut normalize_usize(signal2.len())); - serialized2.append(&mut signal2.to_vec()); + let prove_input2 = prepare_prove_input( + identity_secret_hash, + identity_index, + user_message_limit, + message_id, + external_nullifier, + &signal2, + ); // We call generate_rln_proof for first proof values // result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let proof_data_1 = rln_proof_gen(rln_pointer, serialized1.as_ref()); + let proof_data_1 = rln_proof_gen(rln_pointer, prove_input1.as_ref()); // We call generate_rln_proof // result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let proof_data_2 = rln_proof_gen(rln_pointer, serialized2.as_ref()); + let proof_data_2 = rln_proof_gen(rln_pointer, prove_input2.as_ref()); let input_proof_buffer_1 = &Buffer::from(proof_data_1.as_ref()); let input_proof_buffer_2 = &Buffer::from(proof_data_2.as_ref()); @@ -737,18 +741,18 @@ mod test { // We prepare input for generate_rln_proof API // input_data is [ identity_secret<32> | id_index<8> | epoch<32> | signal_len<8> | signal ] // Note that epoch is the same as before - let mut serialized: Vec = Vec::new(); - serialized.append(&mut fr_to_bytes_le(&identity_secret_hash_new)); - serialized.append(&mut normalize_usize(identity_index_new)); - serialized.append(&mut fr_to_bytes_le(&user_message_limit)); - serialized.append(&mut fr_to_bytes_le(&message_id)); - serialized.append(&mut fr_to_bytes_le(&external_nullifier)); - serialized.append(&mut normalize_usize(signal3.len())); - serialized.append(&mut signal3.to_vec()); + let prove_input3 = prepare_prove_input( + identity_secret_hash, + identity_index_new, + user_message_limit, + message_id, + external_nullifier, + &signal3, + ); // We call generate_rln_proof // result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ] - let proof_data_3 = rln_proof_gen(rln_pointer, serialized.as_ref()); + let proof_data_3 = rln_proof_gen(rln_pointer, prove_input3.as_ref()); // We attempt to recover the secret using share1 (coming from identity_secret_hash) and share3 (coming from identity_secret_hash_new) @@ -1211,15 +1215,14 @@ mod stateless_test { .unwrap(); let serialized = serialize_witness(&rln_witness).unwrap(); - let mut proof_data = rln_proof_gen_with_witness(rln_pointer, serialized.as_ref()); + let proof_data = rln_proof_gen_with_witness(rln_pointer, serialized.as_ref()); - proof_data.append(&mut normalize_usize(signal.len())); - proof_data.append(&mut signal.to_vec()); + let verify_input = prepare_verify_input(proof_data.clone(), &signal); // If no roots is provided, proof validation is skipped and if the remaining proof values are valid, the proof will be correctly verified let mut roots_data: Vec = Vec::new(); - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; @@ -1233,7 +1236,7 @@ mod stateless_test { for _ in 0..5 { roots_data.append(&mut fr_to_bytes_le(&Fr::rand(&mut rng))); } - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool; @@ -1248,7 +1251,7 @@ mod stateless_test { // We add the real root and we check if now the proof is verified roots_data.append(&mut fr_to_bytes_le(&root)); - let input_buffer = &Buffer::from(proof_data.as_ref()); + let input_buffer = &Buffer::from(verify_input.as_ref()); let roots_buffer = &Buffer::from(roots_data.as_ref()); let mut proof_is_valid: bool = false; let proof_is_valid_ptr = &mut proof_is_valid as *mut bool;