Use circom_witnesscalc crate (git)

This commit is contained in:
sydhds
2025-04-03 14:44:07 +02:00
parent ba467d370c
commit 744141187d
4 changed files with 951 additions and 54 deletions

834
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,19 @@ ark-relations = { version = "0.5.0", default-features = false, features = [
] }
ark-circom = { version = "0.5.0" }
ark-r1cs-std = { version = "0.5.0" }
# circom-witnesscalc = { git = "https://github.com/iden3/circom-witnesscalc", branch = "main" }
# Dec 8, 2024 (Note: name is circom_XX and not circom-X in this git rev id)
circom_witnesscalc = { git = "https://github.com/iden3/circom-witnesscalc", rev = "5cb365b6e4d9052ecc69d4567fcf5bc061c20e94" }
# Dec 16, 2024
# circom_witnesscalc = { git = "https://github.com/iden3/circom-witnesscalc", rev = "bdc15673f7351a1792342e68c659b78d4b327425" }
# Jan 31, 2025
# circom_witnesscalc = { git = "https://github.com/iden3/circom-witnesscalc", rev = "cec2cdefad044e5c6b796db75267901cc2e6fd6b" }
# Last (e.g. March 23, 2025 - latest)
# circom-witnesscalc = { git = "https://github.com/iden3/circom-witnesscalc", rev = "de9e6f15800d3f37e5d60da4dbc8e07b49c815e6" }
# local path
# circom-witnesscalc = { path = "../../circom-witnesscalc" }
# circom_witnesscalc = { path = "../../circom-witnesscalc" }
# error handling
color-eyre = "0.6.2"
@@ -94,5 +107,9 @@ required-features = ["arkzkey"]
name = "poseidon_tree_benchmark"
harness = false
[[bench]]
name = "calc_witness_benchmark"
harness = false
[package.metadata.docs.rs]
all-features = true

View File

@@ -0,0 +1,83 @@
use std::time::Duration;
use criterion::{criterion_group, criterion_main, Criterion, BenchmarkId};
use rln::circuit::{calc_witness_2, calculate_rln_witness, graph_from_folder, zkey_from_folder, Fr, TEST_TREE_HEIGHT};
use rln::hashers::{hash_to_field, poseidon_hash};
use rln::iden3calc::calc_witness;
use rln::poseidon_tree::PoseidonTree;
use rln::protocol::{inputs_for_witness_calculation, keygen, rln_witness_from_json, rln_witness_from_values, rln_witness_to_json, RLNWitnessInput};
use utils::ZerokitMerkleTree;
type ConfigOf<T> = <T as ZerokitMerkleTree>::Config;
fn get_test_witness() -> RLNWitnessInput {
let leaf_index = 3;
// Generate identity pair
let (identity_secret_hash, id_commitment) = keygen();
let user_message_limit = Fr::from(100);
let rate_commitment = poseidon_hash(&[id_commitment, user_message_limit]);
//// generate merkle tree
let default_leaf = Fr::from(0);
let mut tree = PoseidonTree::new(
TEST_TREE_HEIGHT,
default_leaf,
ConfigOf::<PoseidonTree>::default(),
)
.unwrap();
tree.set(leaf_index, rate_commitment.into()).unwrap();
let merkle_proof = tree.proof(leaf_index).expect("proof should exist");
let signal = b"hey hey";
let x = hash_to_field(signal);
// We set the remaining values to random ones
let epoch = hash_to_field(b"test-epoch");
let rln_identifier = hash_to_field(b"test-rln-identifier");
let external_nullifier = poseidon_hash(&[epoch, rln_identifier]);
rln_witness_from_values(
identity_secret_hash,
&merkle_proof,
x,
external_nullifier,
user_message_limit,
Fr::from(1),
)
.unwrap()
}
fn bench_calc_witness(c: &mut Criterion) {
// We generate all relevant keys
let proving_key = zkey_from_folder();
// let verification_key = &proving_key.0.vk;
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();
let inputs_1 = inputs_for_witness_calculation(&rln_witness)
.unwrap()
.into_iter()
.map(|(name, values)| (name.to_string(), values));
let inputs_2 = inputs_for_witness_calculation(&rln_witness)
.unwrap()
.into_iter()
.map(|(name, values)| (name.to_string(), values));
let mut group = c.benchmark_group("calc_witness");
// group.sample_size(50);
group.measurement_time(Duration::from_secs(11));
group.bench_function("Circom-witnesscalc current", |b| b.iter(|| calc_witness(inputs_1.clone(), graph_data) ));
// group.bench_function("Circom-witnesscalc crate(git)", |b| b.iter(|| calculate_rln_witness(inputs, graph_data) ));
group.bench_function("Circom-witnesscalc crate(git)", |b| b.iter(|| calc_witness_2(inputs_2.clone(), graph_data) ));
group.finish();
}
criterion_group!(benches, bench_calc_witness);
criterion_main!(benches);

View File

@@ -1,16 +1,22 @@
// This crate provides interfaces for the zero-knowledge circuit and keys
use std::collections::HashMap;
use ::lazy_static::lazy_static;
use ark_bn254::{
Bn254, Fq as ArkFq, Fq2 as ArkFq2, Fr as ArkFr, G1Affine as ArkG1Affine,
G1Projective as ArkG1Projective, G2Affine as ArkG2Affine, G2Projective as ArkG2Projective,
};
use ark_ff::{BigInteger, PrimeField};
use ark_groth16::{ProvingKey, VerifyingKey};
use ark_relations::r1cs::ConstraintMatrices;
use cfg_if::cfg_if;
use circom_witnesscalc::{calc_witness, deserialize_inputs, graph, Error, InputSignalsInfo};
use circom_witnesscalc::graph::Node;
use circom_witnesscalc::storage::deserialize_witnesscalc_graph;
use color_eyre::{Report, Result};
use crate::iden3calc::calc_witness;
use ruint::aliases::U256;
// use crate::iden3calc::calc_witness;
use crate::iden3calc::graph::{fr_to_u256, u256_to_fr};
#[cfg(feature = "arkzkey")]
use {
@@ -101,7 +107,66 @@ pub fn calculate_rln_witness<I: IntoIterator<Item = (String, Vec<Fr>)>>(
inputs: I,
graph_data: &[u8],
) -> Vec<Fr> {
calc_witness(inputs, graph_data)
// calc_witness(inputs, graph_data)
let res = calc_witness_2(inputs, graph_data).unwrap();
res.iter().map(|v| u256_to_fr(&v)).collect()
}
pub fn calc_witness_2<I: IntoIterator<Item = (String, Vec<Fr>)>>(inputs: I, graph_data: &[u8]) -> std::result::Result<Vec<U256>, Error> {
// HashMap<String, U256>
// let inputs = deserialize_inputs(inputs.as_bytes())?;
let inputs: HashMap<String, Vec<U256>> = inputs
.into_iter()
.map(|(key, value)| (key, value.iter().map(fr_to_u256).collect()))
.collect();
let (nodes, signals, input_mapping): (Vec<Node>, Vec<usize>, InputSignalsInfo) =
deserialize_witnesscalc_graph(std::io::Cursor::new(graph_data)).unwrap();
let mut inputs_buffer = get_inputs_buffer(get_inputs_size(&nodes));
populate_inputs(&inputs, &input_mapping, &mut inputs_buffer);
Ok(graph::evaluate(&nodes, inputs_buffer.as_slice(), &signals))
}
fn get_inputs_buffer(size: usize) -> Vec<U256> {
let mut inputs = vec![U256::ZERO; size];
inputs[0] = U256::from(1);
inputs
}
fn get_inputs_size(nodes: &[Node]) -> usize {
let mut start = false;
let mut max_index = 0usize;
for &node in nodes.iter() {
if let Node::Input(i) = node {
if i > max_index {
max_index = i;
}
start = true
} else if start {
break;
}
}
max_index + 1
}
fn populate_inputs(
input_list: &HashMap<String, Vec<U256>>, inputs_info: &InputSignalsInfo,
input_buffer: &mut [U256]) {
for (key, value) in input_list {
let (offset, len) = inputs_info[key];
if len != value.len() {
panic!("Invalid input length for {}", key);
}
// println!("input {}, offset {}, len {}", key, offset, len);
for (i, v) in value.iter().enumerate() {
input_buffer[offset + i] = *v;
}
}
}
pub fn graph_from_folder() -> &'static [u8] {