Files
Nova-Scotia/examples/toy_bn254.rs
enrico.eth 00085ece0e feat: continue_recursive_circuit api (#34)
* feat: `add_step` api

* fix:  error

* fix: `continue_recursive_circuit` API

* fix: typo
2023-08-21 08:51:03 -07:00

169 lines
5.2 KiB
Rust

use std::{collections::HashMap, env::current_dir, time::Instant};
use nova_scotia::{
circom::reader::load_r1cs, continue_recursive_circuit, create_public_params,
create_recursive_circuit, FileLocation, F, S,
};
use nova_snark::{provider, CompressedSNARK, PublicParams};
use serde_json::json;
fn run_test(circuit_filepath: String, witness_gen_filepath: String) {
type G1 = provider::bn256_grumpkin::bn256::Point;
type G2 = provider::bn256_grumpkin::grumpkin::Point;
println!(
"Running test with witness generator: {} and group: {}",
witness_gen_filepath,
std::any::type_name::<G1>()
);
let iteration_count = 5;
let root = current_dir().unwrap();
let circuit_file = root.join(circuit_filepath);
let r1cs = load_r1cs::<G1, G2>(&FileLocation::PathBuf(circuit_file));
let witness_generator_file = root.join(witness_gen_filepath);
let mut private_inputs = Vec::new();
for i in 0..iteration_count {
let mut private_input = HashMap::new();
private_input.insert("adder".to_string(), json!(i));
private_inputs.push(private_input);
}
let start_public_input = [F::<G1>::from(10), F::<G1>::from(10)];
let pp: PublicParams<G1, G2, _, _> = create_public_params(r1cs.clone());
println!(
"Number of constraints per step (primary circuit): {}",
pp.num_constraints().0
);
println!(
"Number of constraints per step (secondary circuit): {}",
pp.num_constraints().1
);
println!(
"Number of variables per step (primary circuit): {}",
pp.num_variables().0
);
println!(
"Number of variables per step (secondary circuit): {}",
pp.num_variables().1
);
println!("Creating a RecursiveSNARK...");
let start = Instant::now();
let mut recursive_snark = create_recursive_circuit(
FileLocation::PathBuf(witness_generator_file.clone()),
r1cs.clone(),
private_inputs,
start_public_input.to_vec(),
&pp,
)
.unwrap();
println!("RecursiveSNARK creation took {:?}", start.elapsed());
// TODO: empty?
let z0_secondary = [F::<G2>::from(0)];
// verify the recursive SNARK
println!("Verifying a RecursiveSNARK...");
let start = Instant::now();
let res = recursive_snark.verify(&pp, iteration_count, &start_public_input, &z0_secondary);
println!(
"RecursiveSNARK::verify: {:?}, took {:?}",
res,
start.elapsed()
);
assert!(res.is_ok());
let z_last = res.unwrap().0;
assert_eq!(z_last[0], F::<G1>::from(20));
assert_eq!(z_last[1], F::<G1>::from(70));
// produce a compressed SNARK
println!("Generating a CompressedSNARK using Spartan with IPA-PC...");
let start = Instant::now();
let (pk, vk) = CompressedSNARK::<_, _, _, _, S<G1>, S<G2>>::setup(&pp).unwrap();
let res = CompressedSNARK::<_, _, _, _, S<G1>, S<G2>>::prove(&pp, &pk, &recursive_snark);
println!(
"CompressedSNARK::prove: {:?}, took {:?}",
res.is_ok(),
start.elapsed()
);
assert!(res.is_ok());
let compressed_snark = res.unwrap();
// verify the compressed SNARK
println!("Verifying a CompressedSNARK...");
let start = Instant::now();
let res = compressed_snark.verify(
&vk,
iteration_count,
start_public_input.to_vec(),
z0_secondary.to_vec(),
);
println!(
"CompressedSNARK::verify: {:?}, took {:?}",
res.is_ok(),
start.elapsed()
);
assert!(res.is_ok());
// continue recursive circuit by adding 2 further steps
println!("Adding steps to our RecursiveSNARK...");
let start = Instant::now();
let iteration_count_continue = 2;
let mut private_inputs_continue = Vec::new();
for i in 0..iteration_count_continue {
let mut private_input = HashMap::new();
private_input.insert("adder".to_string(), json!(5 + i));
private_inputs_continue.push(private_input);
}
let res = continue_recursive_circuit(
&mut recursive_snark,
z_last,
FileLocation::PathBuf(witness_generator_file),
r1cs,
private_inputs_continue,
start_public_input.to_vec(),
&pp,
);
assert!(res.is_ok());
println!(
"Adding 2 steps to our RecursiveSNARK took {:?}",
start.elapsed()
);
// verify the recursive SNARK with the added steps
println!("Verifying a RecursiveSNARK...");
let start = Instant::now();
let res = recursive_snark.verify(&pp, iteration_count + iteration_count_continue, &start_public_input, &z0_secondary);
println!(
"RecursiveSNARK::verify: {:?}, took {:?}",
res,
start.elapsed()
);
assert!(res.is_ok());
assert_eq!(res.clone().unwrap().0[0], F::<G1>::from(31));
assert_eq!(res.unwrap().0[1], F::<G1>::from(115));
}
fn main() {
let group_name = "bn254";
let circuit_filepath = format!("examples/toy/{}/toy.r1cs", group_name);
for witness_gen_filepath in [
format!("examples/toy/{}/toy_cpp/toy", group_name),
format!("examples/toy/{}/toy_js/toy.wasm", group_name),
] {
run_test(circuit_filepath.clone(), witness_gen_filepath);
}
}